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

import "forge-std/Test.sol";
import "../../contracts/iso4217w/controllers/BurnController.sol";
import "../../contracts/iso4217w/ISO4217WToken.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract BurnControllerTest is Test {
    BurnController public burnController;
    ISO4217WToken public token;

    address public admin = address(0x1);
    address public redeemer = address(0x2);
    address public user = address(0x3);
    address public custodian = address(0x4);

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

        burnController = new BurnController(admin);

        // Deploy token
        ISO4217WToken implementation = new ISO4217WToken();
        bytes memory initData = abi.encodeWithSelector(
            ISO4217WToken.initialize.selector,
            "USDW Token",
            "USDW",
            "USD",
            2,
            custodian,
            address(0x999), // mint controller placeholder
            address(burnController),
            address(0x888), // compliance guard placeholder
            admin
        );

        ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initData);
        token = ISO4217WToken(address(proxy));

        // Grant roles
        token.grantRole(keccak256("BURNER_ROLE"), address(burnController));
        burnController.grantRole(keccak256("REDEEMER_ROLE"), redeemer);
        burnController.approveToken(address(token));

        // Set reserve before mint (token enforces reserve >= supply)
        token.grantRole(keccak256("RESERVE_UPDATE_ROLE"), admin);
        token.updateVerifiedReserve(10000e2);

        // Mint some tokens to user
        token.grantRole(keccak256("MINTER_ROLE"), admin);
        token.mint(user, 1000e2);

        vm.stopPrank();
    }

    function test_Redeem() public {
        assertEq(token.balanceOf(user), 1000e2);

        vm.prank(redeemer);
        bytes32 redemptionId = burnController.redeem(address(token), user, 500e2);

        assertEq(token.balanceOf(user), 500e2);
        assertEq(token.totalSupply(), 500e2);
        assertNotEq(redemptionId, bytes32(0));

        // Check redemption record
        BurnController.Redemption memory redemption = burnController.getRedemption(redemptionId);
        assertEq(redemption.token, address(token));
        assertEq(redemption.redeemer, user);
        assertEq(redemption.amount, 500e2);
        assertTrue(redemption.processed);
    }

    function test_Burn() public {
        vm.prank(admin);
        burnController.burn(address(token), user, 300e2);

        assertEq(token.balanceOf(user), 700e2);
        assertEq(token.totalSupply(), 700e2);
    }

    function test_CanRedeem() public {
        bool canRedeem = burnController.canRedeem(address(token), 500e2);
        assertTrue(canRedeem, "Should be able to redeem");

        bool cannotRedeem = burnController.canRedeem(address(token), 2000e2);
        assertFalse(cannotRedeem, "Should not be able to redeem more than supply");
    }

    function test_Redeem_RevertIfNotApprovedToken() public {
        address unapprovedToken = address(0x999);

        vm.prank(redeemer);
        vm.expectRevert("BurnController: token not approved");
        burnController.redeem(unapprovedToken, user, 100e2);
    }
}
