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

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/ICoupon.sol";
import "./interfaces/ICompliance.sol";

/// @title Settlement — 交易结算合约
/// @notice 原子交换：券 ↔ 稳定币 同时转移，支持多稳定币
/// @dev 使用 Transparent Proxy 部署
contract Settlement is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {
    bytes32 public constant SETTLER_ROLE = keccak256("SETTLER_ROLE");
    bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");

    ICoupon public couponContract;
    ICompliance public compliance;

    // 多稳定币支持
    mapping(address => bool) public supportedStablecoins;
    address public defaultStablecoin; // USDC

    // --- Events ---
    event TradeSettled(
        uint256 indexed tokenId,
        address indexed buyer,
        address indexed seller,
        uint256 price,
        address stablecoin
    );
    event RefundExecuted(
        uint256 indexed tokenId,
        address indexed buyer,
        address indexed seller,
        uint256 refundAmount,
        address stablecoin
    );
    event StablecoinAdded(address indexed token);
    event StablecoinRemoved(address indexed token);

    function initialize(
        address _couponContract,
        address _compliance,
        address _defaultStablecoin,
        address admin
    ) external initializer {
        __AccessControl_init();
        __ReentrancyGuard_init();

        couponContract = ICoupon(_couponContract);
        compliance = ICompliance(_compliance);
        defaultStablecoin = _defaultStablecoin;
        supportedStablecoins[_defaultStablecoin] = true;

        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(SETTLER_ROLE, admin);
        _grantRole(GOVERNANCE_ROLE, admin);
    }

    /// @notice 原子交换：券 ↔ 稳定币 同时转移
    /// @param tokenId 券 token ID
    /// @param buyer 买方地址
    /// @param seller 卖方地址
    /// @param price 成交价格（USDC 精度）
    /// @param stablecoin 使用的稳定币地址
    function executeSwap(
        uint256 tokenId,
        address buyer,
        address seller,
        uint256 price,
        address stablecoin
    ) external onlyRole(SETTLER_ROLE) nonReentrant {
        require(supportedStablecoins[stablecoin], "Settlement: unsupported stablecoin");
        require(buyer != address(0) && seller != address(0), "Settlement: zero address");
        require(price > 0, "Settlement: zero price");

        // 合规检查
        ICoupon.CouponConfig memory config = couponContract.getConfig(tokenId);
        compliance.preTradeCheck(buyer, seller, price, config.couponType);

        // Utility Track: 价格 ≤ 面值上限
        if (config.couponType == ICoupon.CouponType.Utility) {
            require(price <= config.maxPrice, "Utility: price exceeds max price");
        }

        // 转售次数检查
        require(
            couponContract.getResaleCount(tokenId) < config.maxResaleCount,
            "Settlement: max resale count exceeded"
        );

        // 到期检查
        require(block.timestamp <= config.expiryDate, "Settlement: coupon expired");

        // 原子交换（要么全部成功，要么全部回滚）
        IERC20(stablecoin).transferFrom(buyer, seller, price);
        couponContract.safeTransferFrom(seller, buyer, tokenId);
        couponContract.incrementResaleCount(tokenId);

        emit TradeSettled(tokenId, buyer, seller, price, stablecoin);
    }

    /// @notice 使用默认稳定币的原子交换（便捷方法）
    function executeSwap(
        uint256 tokenId,
        address buyer,
        address seller,
        uint256 price
    ) external onlyRole(SETTLER_ROLE) nonReentrant {
        _executeSwapInternal(tokenId, buyer, seller, price, defaultStablecoin);
    }

    /// @notice 退款：反向原子交换
    function executeRefund(
        uint256 tokenId,
        address buyer,
        address seller,
        uint256 refundAmount,
        address stablecoin
    ) external onlyRole(SETTLER_ROLE) nonReentrant {
        require(supportedStablecoins[stablecoin], "Settlement: unsupported stablecoin");
        require(refundAmount > 0, "Settlement: zero refund");

        // 合规检查
        require(!compliance.isBlacklisted(buyer), "Settlement: buyer blacklisted");
        require(!compliance.isBlacklisted(seller), "Settlement: seller blacklisted");

        // 反向原子交换
        couponContract.safeTransferFrom(buyer, seller, tokenId);
        IERC20(stablecoin).transferFrom(seller, buyer, refundAmount);

        emit RefundExecuted(tokenId, buyer, seller, refundAmount, stablecoin);
    }

    /// @notice 添加支持的稳定币
    function addStablecoin(address token) external onlyRole(GOVERNANCE_ROLE) {
        require(token != address(0), "Settlement: zero address");
        supportedStablecoins[token] = true;
        emit StablecoinAdded(token);
    }

    /// @notice 移除稳定币支持
    function removeStablecoin(address token) external onlyRole(GOVERNANCE_ROLE) {
        require(token != defaultStablecoin, "Settlement: cannot remove default");
        supportedStablecoins[token] = false;
        emit StablecoinRemoved(token);
    }

    // --- Internal ---

    function _executeSwapInternal(
        uint256 tokenId,
        address buyer,
        address seller,
        uint256 price,
        address stablecoin
    ) internal {
        require(buyer != address(0) && seller != address(0), "Settlement: zero address");
        require(price > 0, "Settlement: zero price");

        ICoupon.CouponConfig memory config = couponContract.getConfig(tokenId);
        compliance.preTradeCheck(buyer, seller, price, config.couponType);

        if (config.couponType == ICoupon.CouponType.Utility) {
            require(price <= config.maxPrice, "Utility: price exceeds max price");
        }

        require(
            couponContract.getResaleCount(tokenId) < config.maxResaleCount,
            "Settlement: max resale count exceeded"
        );
        require(block.timestamp <= config.expiryDate, "Settlement: coupon expired");

        IERC20(stablecoin).transferFrom(buyer, seller, price);
        couponContract.safeTransferFrom(seller, buyer, tokenId);
        couponContract.incrementResaleCount(tokenId);

        emit TradeSettled(tokenId, buyer, seller, price, stablecoin);
    }
}
