// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/Treasury.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockStablecoin is ERC20 {
    constructor() ERC20("USD Coin", "USDC") {}

    function decimals() public pure override returns (uint8) {
        return 6;
    }

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}

contract TreasuryTest is Test {
    Treasury treasury;
    MockStablecoin usdc;

    address admin = address(1);
    address feeCollector = address(2);
    address issuer = address(3);
    address buyer = address(4);
    address seller = address(5);
    address claimant1 = address(6);
    address claimant2 = address(7);

    function setUp() public {
        vm.startPrank(admin);

        usdc = new MockStablecoin();
        treasury = new Treasury();
        treasury.initialize(address(usdc), feeCollector, admin);

        // Fund accounts
        usdc.mint(issuer, 100_000e6);
        usdc.mint(buyer, 100_000e6);
        usdc.mint(seller, 100_000e6);

        vm.stopPrank();

        // Approvals
        vm.prank(issuer);
        usdc.approve(address(treasury), type(uint256).max);
        vm.prank(buyer);
        usdc.approve(address(treasury), type(uint256).max);
        vm.prank(seller);
        usdc.approve(address(treasury), type(uint256).max);
    }

    // === Guarantee Fund ===

    function test_DepositGuaranteeFund() public {
        vm.prank(issuer);
        treasury.depositGuaranteeFund(10000e6);
        assertEq(treasury.guaranteeFunds(issuer), 10000e6);
    }

    function test_WithdrawGuaranteeFund() public {
        vm.prank(issuer);
        treasury.depositGuaranteeFund(10000e6);

        vm.prank(admin);
        treasury.withdrawGuaranteeFund(issuer, 5000e6);
        assertEq(treasury.guaranteeFunds(issuer), 5000e6);
    }

    function test_ActivateGuaranteeFund() public {
        vm.prank(issuer);
        treasury.depositGuaranteeFund(10000e6);

        address[] memory claimants = new address[](2);
        claimants[0] = claimant1;
        claimants[1] = claimant2;
        uint256[] memory amounts = new uint256[](2);
        amounts[0] = 3000e6;
        amounts[1] = 2000e6;

        vm.prank(admin);
        treasury.activateGuaranteeFund(issuer, claimants, amounts);

        assertEq(usdc.balanceOf(claimant1), 3000e6);
        assertEq(usdc.balanceOf(claimant2), 2000e6);
        assertEq(treasury.guaranteeFunds(issuer), 5000e6);
    }

    function test_ActivateInsufficientReverts() public {
        vm.prank(issuer);
        treasury.depositGuaranteeFund(1000e6);

        address[] memory claimants = new address[](1);
        claimants[0] = claimant1;
        uint256[] memory amounts = new uint256[](1);
        amounts[0] = 5000e6;

        vm.prank(admin);
        vm.expectRevert("Treasury: insufficient guarantee fund");
        treasury.activateGuaranteeFund(issuer, claimants, amounts);
    }

    // === Escrow ===

    function test_EscrowAndRelease() public {
        vm.prank(admin);
        treasury.escrow(1, buyer, 1000e6);

        assertEq(usdc.balanceOf(address(treasury)), 1000e6);

        vm.prank(admin);
        treasury.release(1, seller, 950e6, 50e6);

        assertEq(usdc.balanceOf(seller), 100_000e6 + 950e6);
        assertEq(usdc.balanceOf(feeCollector), 50e6);
    }

    function test_EscrowRefund() public {
        uint256 buyerBefore = usdc.balanceOf(buyer);

        vm.prank(admin);
        treasury.escrow(1, buyer, 1000e6);

        vm.prank(admin);
        treasury.refundEscrow(1);

        assertEq(usdc.balanceOf(buyer), buyerBefore);
    }

    function test_DoubleReleaseReverts() public {
        vm.prank(admin);
        treasury.escrow(1, buyer, 1000e6);

        vm.prank(admin);
        treasury.release(1, seller, 950e6, 50e6);

        vm.prank(admin);
        vm.expectRevert("Treasury: already settled");
        treasury.release(1, seller, 950e6, 50e6);
    }

    function test_ReleaseExceedsEscrowReverts() public {
        vm.prank(admin);
        treasury.escrow(1, buyer, 1000e6);

        vm.prank(admin);
        vm.expectRevert("Treasury: exceeds escrow");
        treasury.release(1, seller, 1000e6, 100e6);
    }

    function test_DuplicateEscrowReverts() public {
        vm.prank(admin);
        treasury.escrow(1, buyer, 1000e6);

        vm.prank(admin);
        vm.expectRevert("Treasury: escrow exists");
        treasury.escrow(1, buyer, 500e6);
    }

    // === Sales Revenue ===

    function test_FreezeSalesRevenue() public {
        vm.prank(issuer);
        treasury.freezeSalesRevenue(5000e6);
        assertEq(treasury.frozenSalesRevenue(issuer), 5000e6);
    }

    function test_ReleaseSalesRevenue() public {
        vm.prank(issuer);
        treasury.freezeSalesRevenue(5000e6);

        vm.prank(admin);
        treasury.releaseSalesRevenue(issuer, 3000e6);
        assertEq(treasury.frozenSalesRevenue(issuer), 2000e6);
    }

    // === Fee Collector ===

    function test_SetPlatformFeeCollector() public {
        address newCollector = address(99);
        vm.prank(admin);
        treasury.setPlatformFeeCollector(newCollector);
        assertEq(treasury.platformFeeCollector(), newCollector);
    }
}
