pragma solidity 0.8.20;

import {Test} from "forge-std/Test.sol";
import {StdChains} from "forge-std/StdChains.sol";

import "../../src/GhostAuthority.sol";
import "../../src/Treasury.sol";
import "../../src/StandardBondingCalculator.sol";

import "@uniswap-v2-periphery-1.1.0-beta.0/interfaces/IWETH.sol";

contract GhostTreasuryRedemptionTest is Test {
    address public constant owner    = 0x0000000000000000000000000000000000000001;
    address public constant governor = 0x0000000000000000000000000000000000000002;
    address public constant guardian = 0x0000000000000000000000000000000000000003;

    uint256 public constant amount = 69 * 1e18;
    address public constant dai    = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address public constant pair   = 0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11;
    address public constant router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    address public constant weth   = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    GhostTreasury treasury;
    GhostAuthority authority;
    GhostBondingCalculator calculator;

    function setUp() public {
        vm.startPrank(owner);
        authority = new GhostAuthority(
            governor,
            guardian,
            owner,
            owner
        );
        treasury = new GhostTreasury(dai, 69, address(authority));
        calculator = new GhostBondingCalculator(dai, 4000, 1);
        vm.stopPrank();

        vm.startPrank(governor);
        treasury.enable(ITreasury.STATUS.RESERVETOKEN, weth, address(calculator));
        treasury.enable(ITreasury.STATUS.LIQUIDITYTOKEN, pair, address(calculator));
        vm.stopPrank();
    }

    function test_mainnet_redemptionWorksCorrectly() public {
        vm.deal(owner, amount);
        vm.startPrank(owner);
        IWETH(weth).deposit{value: amount}();
        IERC20(weth).transfer(address(treasury), amount);
        assertEq(IERC20(weth).balanceOf(address(treasury)), amount);
        vm.stopPrank();

        assertEq(treasury.totalReserves(), 0);

        vm.prank(governor);
        treasury.auditReserves();

        uint256 prevTotalReserves = treasury.totalReserves();
        assertEq(prevTotalReserves > 0, true);
        assertEq(IERC20(pair).balanceOf(address(treasury)), 0);
        assertEq(IERC20(pair).balanceOf(address(treasury)), 0);

        vm.prank(governor);
        treasury.redeemReserve(router, amount);

        assertEq(IERC20(dai).balanceOf(address(treasury)), 0);
        assertEq(IERC20(weth).balanceOf(address(treasury)), 0);
        assertEq(IERC20(pair).balanceOf(address(treasury)) > 0, true);

        uint256 liquidity = IERC20(pair).balanceOf(address(treasury));
        vm.prank(governor);
        treasury.forfeitReserves(router, liquidity, false);

        assertEq(IERC20(dai).balanceOf(address(treasury)) > 0, true);
        assertEq(IERC20(weth).balanceOf(address(treasury)) > 0, true);
        assertEq(IERC20(pair).balanceOf(address(treasury)), 0);
    }
}
