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

import {Test} from "forge-std/Test.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {UniswapV3ExternalUnwinder} from "../src/UniswapV3ExternalUnwinder.sol";

interface IWETHFork {
    function deposit() external payable;
    function transfer(address to, uint256 value) external returns (bool);
}

contract UniswapV3ExternalUnwinderMainnetForkTest is Test {
    address constant UNISWAP_V3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    address constant CWUSDC = 0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a;

    UniswapV3ExternalUnwinder internal unwinder;

    function setUp() public {
        string memory rpcUrl = vm.envString("ETHEREUM_MAINNET_RPC");
        vm.createSelectFork(rpcUrl);
        unwinder = new UniswapV3ExternalUnwinder(UNISWAP_V3_ROUTER);
    }

    function testFork_knownRoute_WETHToUSDC_singleHopWorks() public {
        vm.deal(address(this), 1 ether);
        IWETHFork(WETH).deposit{value: 1 ether}();
        IERC20(WETH).approve(address(unwinder), 1 ether);
        uint256 before = IERC20(USDC).balanceOf(address(this));

        uint256 amountOut = unwinder.unwind(WETH, USDC, 1 ether, 1, abi.encode(uint24(3000)));

        uint256 afterBal = IERC20(USDC).balanceOf(address(this));
        assertGt(amountOut, 0, "amountOut > 0");
        assertEq(afterBal - before, amountOut, "USDC received");
    }

    function testFork_cWUSDCToUSDC_routeUnavailableOnUniswapV3() public {
        deal(CWUSDC, address(this), 1_000_000);
        IERC20(CWUSDC).approve(address(unwinder), 1_000_000);

        vm.expectRevert();
        unwinder.unwind(CWUSDC, USDC, 1_000_000, 1, abi.encode(uint24(3000)));
    }
}
