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

import {Test, console} from "forge-std/Test.sol";
import "../../../contracts/bridge/trustless/BondManager.sol";
import "../../../contracts/bridge/trustless/ChallengeManager.sol";
import "../../../contracts/bridge/trustless/InboxETH.sol";
import "../../../contracts/bridge/trustless/LiquidityPoolETH.sol";

/**
 * @title GasBenchmarkTest
 * @notice Gas benchmarking for bridge operations
 */
contract GasBenchmarkTest is Test {
    BondManager public bondManager;
    ChallengeManager public challengeManager;
    InboxETH public inbox;
    LiquidityPoolETH public liquidityPool;

    address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    address public relayer = address(0x1111);
    address public challenger = address(0x2222);
    address public recipient = address(0x3333);

    function setUp() public {
        bondManager = new BondManager(11000, 1 ether);
        challengeManager = new ChallengeManager(address(bondManager), 30 minutes);
        liquidityPool = new LiquidityPoolETH(WETH, 5, 11000);
        inbox = new InboxETH(address(bondManager), address(challengeManager), address(liquidityPool));

        liquidityPool.authorizeRelease(address(inbox));
        vm.deal(relayer, 100 ether);
        vm.deal(challenger, 100 ether);
        
        // Set initial timestamp to avoid cooldown issues with uninitialized lastClaimTime
        vm.warp(1000);
    }

    function test_GasBenchmark_SubmitClaim() public {
        uint256 gasBefore = gasleft();
        
        vm.warp(block.timestamp + 1); // Advance time
        vm.prank(relayer);
        inbox.submitClaim{value: bondManager.getRequiredBond(1 ether)}(
            5001,
            address(0),
            1 ether,
            recipient,
            ""
        );
        
        uint256 gasUsed = gasBefore - gasleft();
        console.log("Gas used for submitClaim:", gasUsed);
        
        // Target: < 500k gas (adjusted for via-ir compilation)
        assertLt(gasUsed, 500000, "Gas should be reasonable");
    }

    function test_GasBenchmark_ChallengeClaim() public {
        // Submit claim first
        vm.warp(block.timestamp + 1); // Advance time
        vm.prank(relayer);
        inbox.submitClaim{value: bondManager.getRequiredBond(1 ether)}(
            5002,
            address(0),
            1 ether,
            recipient,
            ""
        );

        // Generate fraud proof (simplified - will be invalid)
        bytes memory proof = abi.encode("fraud_proof");

        uint256 gasBefore = gasleft();
        
        vm.prank(challenger);
        // Expect revert since proof is invalid
        vm.expectRevert(); // Expect revert (InvalidFraudProof)
        challengeManager.challengeClaim(
            5002,
            ChallengeManager.FraudProofType.NonExistentDeposit,
            proof
        );
        
        uint256 gasUsed = gasBefore - gasleft();
        console.log("Gas used for challengeClaim (invalid proof):", gasUsed);
        
        // Target: < 300k gas even for invalid proof rejection
        assertLt(gasUsed, 300000, "Gas should be reasonable");
    }

    function test_GasBenchmark_FinalizeClaim() public {
        // Submit claim
        vm.warp(block.timestamp + 1); // Advance time
        vm.prank(relayer);
        inbox.submitClaim{value: bondManager.getRequiredBond(1 ether)}(
            5003,
            address(0),
            1 ether,
            recipient,
            ""
        );

        // Wait for challenge window
        vm.warp(block.timestamp + 30 minutes + 1);

        uint256 gasBefore = gasleft();
        
        challengeManager.finalizeClaim(5003);
        
        uint256 gasUsed = gasBefore - gasleft();
        console.log("Gas used for finalizeClaim:", gasUsed);
        
        // Target: < 80k gas
        assertLt(gasUsed, 100000, "Gas should be reasonable");
    }

    function test_GasBenchmark_BatchFinalize() public {
        // Submit 5 claims - start at 1001
        uint256 currentTime = 1001;
        for (uint256 i = 0; i < 5; i++) {
            vm.deal(relayer, 100 ether);
            // Advance time to respect cooldown (61 seconds between claims)
            vm.warp(currentTime);
            vm.prank(relayer);
            inbox.submitClaim{value: bondManager.getRequiredBond(1 ether)}(
                6000 + i,
                address(0),
                1 ether,
                recipient,
                ""
            );
            currentTime += 61 seconds;
        }

        vm.warp(block.timestamp + 30 minutes + 1);

        uint256[] memory depositIds = new uint256[](5);
        for (uint256 i = 0; i < 5; i++) {
            depositIds[i] = 6000 + i;
        }

        uint256 gasBefore = gasleft();
        
        challengeManager.finalizeClaimsBatch(depositIds);
        
        uint256 gasUsed = gasBefore - gasleft();
        console.log("Gas used for batch finalize (5 claims):", gasUsed);
        console.log("Average gas per claim:", gasUsed / 5);
        
        // Batch should save gas vs individual calls
        assertLt(gasUsed, 500000, "Batch should be efficient");
    }
}

