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

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "../ccip/CCIPWETH9Bridge.sol";

/**
 * @title CcipBridgeAdapter138
 * @notice Export-only module: only WETH9 to Ethereum Mainnet; only callable by StrategyExecutor138.
 * @dev Destination selector fixed to 5009297550715157269. Gate: exportsEnabled must be true.
 * See docs/treasury/EXECUTOR_ALLOWLIST_MATRIX.md and EXPORT_STATE_MACHINE.md.
 */
contract CcipBridgeAdapter138 is AccessControl, ReentrancyGuard {
    using SafeERC20 for IERC20;

    uint64 public constant MAINNET_SELECTOR = 5009297550715157269;

    address public immutable weth9;
    address public immutable bridgeWeth9;
    address public immutable receiverMainnet;
    address public strategyExecutor;
    bool private _executorSet;

    bool public exportsEnabled;

    event ExportInitiated(bytes32 indexed messageId, uint256 amount);
    event ExportsEnabledSet(bool enabled);

    error ExportsDisabled();
    error OnlyExecutor();
    error ZeroAmount();
    error DeadlineExpired();
    error InsufficientOutput();

    constructor(
        address _weth9,
        address _bridgeWeth9,
        address _receiverMainnet,
        address admin
    ) {
        if (_weth9 == address(0) || _bridgeWeth9 == address(0) || _receiverMainnet == address(0)) {
            revert("CcipBridgeAdapter138: zero address");
        }
        weth9 = _weth9;
        bridgeWeth9 = _bridgeWeth9;
        receiverMainnet = _receiverMainnet;
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
    }

    function setStrategyExecutor(address _executor) external onlyRole(DEFAULT_ADMIN_ROLE) {
        if (_executorSet) revert("CcipBridgeAdapter138: executor already set");
        if (_executor == address(0)) revert("CcipBridgeAdapter138: zero executor");
        _executorSet = true;
        strategyExecutor = _executor;
    }

    function setExportsEnabled(bool enabled) external onlyRole(DEFAULT_ADMIN_ROLE) {
        exportsEnabled = enabled;
        emit ExportsEnabledSet(enabled);
    }

    /**
     * @notice Send WETH9 to Ethereum Mainnet. Only callable by StrategyExecutor138.
     * @param amount Amount of WETH9 to send.
     * @param minAmount Unused; reserved for future slippage/quote checks.
     * @param deadline Revert if block.timestamp > deadline.
     */
    function sendWeth9ToMainnet(uint256 amount, uint256 minAmount, uint256 deadline)
        external
        payable
        nonReentrant
        returns (bytes32 messageId)
    {
        if (msg.sender != strategyExecutor) revert OnlyExecutor();
        if (!exportsEnabled) revert ExportsDisabled();
        if (amount == 0) revert ZeroAmount();
        if (block.timestamp > deadline) revert DeadlineExpired();
        if (minAmount > 0 && amount < minAmount) revert InsufficientOutput();

        IERC20(weth9).safeTransferFrom(msg.sender, address(this), amount);
        IERC20(weth9).approve(bridgeWeth9, amount);

        messageId = CCIPWETH9Bridge(payable(bridgeWeth9)).sendCrossChain{value: msg.value}(
            MAINNET_SELECTOR,
            receiverMainnet,
            amount
        );

        emit ExportInitiated(messageId, amount);
        return messageId;
    }
}
