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

import "@openzeppelin/contracts/access/AccessControl.sol";

contract AtomicFeePolicy is AccessControl {
    bytes32 public constant POLICY_MANAGER_ROLE = keccak256("POLICY_MANAGER_ROLE");

    struct CorridorPolicy {
        uint16 fulfillerFeeBps;
        uint16 protocolFeeBps;
        uint16 bondBps;
        uint16 slashPenaltyBps;
        uint256 maxFulfilmentDelay;
        uint256 maxSettlementDelay;
    }

    mapping(bytes32 => CorridorPolicy) public corridorPolicies;

    event CorridorPolicySet(
        bytes32 indexed corridorId,
        uint16 fulfillerFeeBps,
        uint16 protocolFeeBps,
        uint16 bondBps,
        uint16 slashPenaltyBps,
        uint256 maxFulfilmentDelay,
        uint256 maxSettlementDelay
    );

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

    function setCorridorPolicy(
        bytes32 corridorId,
        uint16 fulfillerFeeBps,
        uint16 protocolFeeBps,
        uint16 bondBps,
        uint16 slashPenaltyBps,
        uint256 maxFulfilmentDelay,
        uint256 maxSettlementDelay
    ) external onlyRole(POLICY_MANAGER_ROLE) {
        corridorPolicies[corridorId] = CorridorPolicy({
            fulfillerFeeBps: fulfillerFeeBps,
            protocolFeeBps: protocolFeeBps,
            bondBps: bondBps,
            slashPenaltyBps: slashPenaltyBps,
            maxFulfilmentDelay: maxFulfilmentDelay,
            maxSettlementDelay: maxSettlementDelay
        });
        emit CorridorPolicySet(
            corridorId,
            fulfillerFeeBps,
            protocolFeeBps,
            bondBps,
            slashPenaltyBps,
            maxFulfilmentDelay,
            maxSettlementDelay
        );
    }

    function quoteFees(bytes32 corridorId, uint256 amountIn)
        external
        view
        returns (uint256 fulfillerFee, uint256 protocolFee)
    {
        CorridorPolicy memory policy = corridorPolicies[corridorId];
        fulfillerFee = (amountIn * policy.fulfillerFeeBps) / 10_000;
        protocolFee = (amountIn * policy.protocolFeeBps) / 10_000;
    }

    function requiredBond(bytes32 corridorId, uint256 reservedLiquidity) external view returns (uint256) {
        CorridorPolicy memory policy = corridorPolicies[corridorId];
        uint256 effectiveBps = policy.bondBps;
        uint256 slashFloor = 10_000 + policy.slashPenaltyBps;
        if (effectiveBps < slashFloor) {
            effectiveBps = slashFloor;
        }
        return (reservedLiquidity * effectiveBps) / 10_000;
    }
}
