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

import "forge-std/Test.sol";
import "../../contracts/bridge/UniversalCCIPBridge.sol";
import "../../contracts/liquidity/LiquidityManager.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

/**
 * @title Reentrancy Security Tests
 * @notice Tests for reentrancy protection
 */
contract ReentrancySecurityTest is Test {
    UniversalCCIPBridge public bridge;
    LiquidityManager public liquidityManager;
    
    address public admin;
    address public attacker;
    
    function setUp() public {
        admin = makeAddr("admin");
        attacker = makeAddr("attacker");
        
        vm.startPrank(admin);
        
        UniversalCCIPBridge bridgeImpl = new UniversalCCIPBridge();
        bytes memory bridgeInitData = abi.encodeWithSelector(
            UniversalCCIPBridge.initialize.selector,
            makeAddr("registry"),
            makeAddr("router"),
            admin
        );
        ERC1967Proxy bridgeProxy = new ERC1967Proxy(address(bridgeImpl), bridgeInitData);
        bridge = UniversalCCIPBridge(payable(address(bridgeProxy)));
        
        LiquidityManager lmImpl = new LiquidityManager();
        bytes memory lmInitData = abi.encodeWithSelector(LiquidityManager.initialize.selector, admin);
        ERC1967Proxy lmProxy = new ERC1967Proxy(address(lmImpl), lmInitData);
        liquidityManager = LiquidityManager(address(lmProxy));
        
        vm.stopPrank();
    }

    function testBridgeReentrancyProtection() public {
        // Deploy malicious token that attempts reentrancy
        MaliciousToken maliciousToken = new MaliciousToken(payable(address(bridge)));
        
        vm.startPrank(attacker);
        
        UniversalCCIPBridge.BridgeOperation memory op = UniversalCCIPBridge.BridgeOperation({
            token: address(maliciousToken),
            amount: 1000e18,
            destinationChain: 1,
            recipient: attacker,
            assetType: bytes32(0),
            usePMM: false,
            useVault: false,
            complianceProof: "",
            vaultInstructions: ""
        });
        
        // Should fail due to reentrancy guard
        vm.expectRevert();
        bridge.bridge(op);
        
        vm.stopPrank();
    }

    function testLiquidityManagerReentrancy() public {
        // Test that liquidity manager has nonReentrant and returns safely for unconfigured token
        vm.startPrank(attacker);
        
        uint256 result = liquidityManager.provideLiquidity(makeAddr("token"), 1000e18, "");
        assertEq(result, 0, "Unconfigured token should return 0");
        
        vm.stopPrank();
    }
}

/**
 * @title MaliciousToken
 * @notice Mock token that attempts reentrancy attack
 */
contract MaliciousToken {
    address payable public bridge;
    
    constructor(address payable _bridge) {
        bridge = _bridge;
    }
    
    function transferFrom(address, address, uint256) external returns (bool) {
        // Attempt reentrancy
        UniversalCCIPBridge.BridgeOperation memory op = UniversalCCIPBridge.BridgeOperation({
            token: address(this),
            amount: 1000e18,
            destinationChain: 1,
            recipient: msg.sender,
            assetType: bytes32(0),
            usePMM: false,
            useVault: false,
            complianceProof: "",
            vaultInstructions: ""
        });
        
        UniversalCCIPBridge(bridge).bridge(op);
        return true;
    }
}
