// 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 {IAtomicSettlementAdapter} from "./interfaces/IAtomicSettlementAdapter.sol";

contract AtomicSettlementRouter is AccessControl {
    using SafeERC20 for IERC20;

    bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE");
    bytes32 public constant ADAPTER_MANAGER_ROLE = keccak256("ADAPTER_MANAGER_ROLE");

    mapping(bytes32 => address) public adapters;

    event AdapterSet(bytes32 indexed settlementMode, address indexed adapter);
    event SettlementExecuted(
        bytes32 indexed obligationId,
        bytes32 indexed settlementMode,
        address indexed token,
        uint256 amount,
        bytes32 settlementId
    );

    error MissingAdapter();

    constructor(address admin) {
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(ADAPTER_MANAGER_ROLE, admin);
    }

    function setAdapter(bytes32 settlementMode, address adapter) external onlyRole(ADAPTER_MANAGER_ROLE) {
        adapters[settlementMode] = adapter;
        emit AdapterSet(settlementMode, adapter);
    }

    function executeSettlement(
        bytes32 obligationId,
        bytes32 settlementMode,
        address token,
        uint256 amount,
        address recipient,
        bytes calldata data
    ) external payable onlyRole(COORDINATOR_ROLE) returns (bytes32 settlementId) {
        address adapter = adapters[settlementMode];
        if (adapter == address(0)) revert MissingAdapter();

        IERC20(token).safeTransfer(adapter, amount);
        settlementId = IAtomicSettlementAdapter(adapter).executeSettlement{value: msg.value}(
            obligationId,
            token,
            amount,
            recipient,
            data
        );
        emit SettlementExecuted(obligationId, settlementMode, token, amount, settlementId);
    }
}
