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

import "../ccip/IRouterClient.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

/**
 * @title CCIP Relay Bridge
 * @notice Bridge that accepts messages from a relay router
 * @dev Modified version of CCIPWETH9Bridge that accepts relay router
 */
contract CCIPRelayBridge is AccessControl {
    bytes32 public constant ROUTER_ROLE = keccak256("ROUTER_ROLE");
    
    address public immutable weth9;
    address public relayRouter;
    
    // Track cross-chain transfers for replay protection
    mapping(bytes32 => bool) public processedTransfers;
    mapping(address => uint256) public nonces;
    
    event CrossChainTransferCompleted(
        bytes32 indexed messageId,
        uint64 indexed sourceChainSelector,
        address indexed recipient,
        uint256 amount
    );
    
    constructor(address _weth9, address _relayRouter) {
        require(_weth9 != address(0), "CCIPRelayBridge: zero WETH9");
        require(_relayRouter != address(0), "CCIPRelayBridge: zero router");
        
        weth9 = _weth9;
        relayRouter = _relayRouter;
        _grantRole(ROUTER_ROLE, _relayRouter);
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }
    
    /**
     * @notice Update relay router address
     */
    function updateRelayRouter(address newRelayRouter) external onlyRole(DEFAULT_ADMIN_ROLE) {
        require(newRelayRouter != address(0), "CCIPRelayBridge: zero address");
        _revokeRole(ROUTER_ROLE, relayRouter);
        relayRouter = newRelayRouter;
        _grantRole(ROUTER_ROLE, newRelayRouter);
    }
    
    /**
     * @notice Receive WETH9 tokens from another chain via relay
     * @param message The CCIP message
     */
    function ccipReceive(
        IRouterClient.Any2EVMMessage calldata message
    ) external onlyRole(ROUTER_ROLE) {
        // Replay protection
        require(!processedTransfers[message.messageId], "CCIPRelayBridge: transfer already processed");
        processedTransfers[message.messageId] = true;
        
        // Validate token amounts
        require(message.tokenAmounts.length > 0, "CCIPRelayBridge: no tokens");
        require(message.tokenAmounts[0].token == weth9, "CCIPRelayBridge: invalid token");
        
        uint256 amount = message.tokenAmounts[0].amount;
        require(amount > 0, "CCIPRelayBridge: invalid amount");
        
        // Decode transfer data (recipient, amount, sender, nonce)
        (address recipient, , , ) = abi.decode(
            message.data,
            (address, uint256, address, uint256)
        );
        
        require(recipient != address(0), "CCIPRelayBridge: zero recipient");
        
        // Transfer WETH9 to recipient
        require(IERC20(weth9).transfer(recipient, amount), "CCIPRelayBridge: transfer failed");
        
        emit CrossChainTransferCompleted(
            message.messageId,
            message.sourceChainSelector,
            recipient,
            amount
        );
    }
    
    /**
     * @notice Get user nonce
     */
    function getUserNonce(address user) external view returns (uint256) {
        return nonces[user];
    }
}

