// 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";

/// @title Treasury — 资金托管合约
/// @notice 保障资金锁定、交易 Escrow、资金释放与费用分割
/// @dev 使用 Transparent Proxy 部署
contract Treasury is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {
    bytes32 public constant SETTLER_ROLE = keccak256("SETTLER_ROLE");
    bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");

    IERC20 public stablecoin;
    address public platformFeeCollector;

    // 发行方保障资金（自愿缴纳，提升信用评级）
    mapping(address => uint256) public guaranteeFunds;
    // 发行方冻结的销售款（自愿，作为兑付保障）
    mapping(address => uint256) public frozenSalesRevenue;
    // Escrow 托管
    mapping(uint256 => EscrowInfo) public escrows;

    struct EscrowInfo {
        address buyer;
        uint256 amount;
        bool released;
        bool refunded;
    }

    // --- Events ---
    event GuaranteeFundDeposited(address indexed issuer, uint256 amount);
    event GuaranteeFundWithdrawn(address indexed issuer, uint256 amount);
    event GuaranteeFundActivated(address indexed issuer, uint256 totalClaim);
    event SalesRevenueFrozen(address indexed issuer, uint256 amount);
    event SalesRevenueReleased(address indexed issuer, uint256 amount);
    event FundsEscrowed(uint256 indexed orderId, address indexed buyer, uint256 amount);
    event FundsReleased(uint256 indexed orderId, address indexed seller, uint256 amount, uint256 platformFee);
    event FundsRefunded(uint256 indexed orderId, address indexed buyer, uint256 amount);

    function initialize(
        address _stablecoin,
        address _platformFeeCollector,
        address admin
    ) external initializer {
        __AccessControl_init();
        __ReentrancyGuard_init();

        stablecoin = IERC20(_stablecoin);
        platformFeeCollector = _platformFeeCollector;

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

    // ========================
    // 保障资金管理
    // ========================

    /// @notice 发行方缴纳保障资金
    function depositGuaranteeFund(uint256 amount) external nonReentrant {
        require(amount > 0, "Treasury: zero amount");
        stablecoin.transferFrom(msg.sender, address(this), amount);
        guaranteeFunds[msg.sender] += amount;
        emit GuaranteeFundDeposited(msg.sender, amount);
    }

    /// @notice 发行方提取保障资金（需治理审批）
    function withdrawGuaranteeFund(address issuer, uint256 amount) external onlyRole(GOVERNANCE_ROLE) nonReentrant {
        require(guaranteeFunds[issuer] >= amount, "Treasury: insufficient guarantee");
        guaranteeFunds[issuer] -= amount;
        stablecoin.transfer(issuer, amount);
        emit GuaranteeFundWithdrawn(issuer, amount);
    }

    /// @notice 发行方违约时启用保障资金赔付
    function activateGuaranteeFund(
        address issuer,
        address[] calldata claimants,
        uint256[] calldata amounts
    ) external onlyRole(GOVERNANCE_ROLE) nonReentrant {
        require(claimants.length == amounts.length, "Treasury: length mismatch");

        uint256 totalClaim = 0;
        for (uint256 i = 0; i < claimants.length; i++) {
            totalClaim += amounts[i];
        }
        require(guaranteeFunds[issuer] >= totalClaim, "Treasury: insufficient guarantee fund");

        guaranteeFunds[issuer] -= totalClaim;
        for (uint256 i = 0; i < claimants.length; i++) {
            stablecoin.transfer(claimants[i], amounts[i]);
        }

        emit GuaranteeFundActivated(issuer, totalClaim);
    }

    // ========================
    // 销售款冻结
    // ========================

    /// @notice 发行方冻结销售款（自愿，作为兑付保障）
    function freezeSalesRevenue(uint256 amount) external nonReentrant {
        require(amount > 0, "Treasury: zero amount");
        stablecoin.transferFrom(msg.sender, address(this), amount);
        frozenSalesRevenue[msg.sender] += amount;
        emit SalesRevenueFrozen(msg.sender, amount);
    }

    /// @notice 释放冻结销售款（需治理审批）
    function releaseSalesRevenue(address issuer, uint256 amount) external onlyRole(GOVERNANCE_ROLE) nonReentrant {
        require(frozenSalesRevenue[issuer] >= amount, "Treasury: insufficient frozen revenue");
        frozenSalesRevenue[issuer] -= amount;
        stablecoin.transfer(issuer, amount);
        emit SalesRevenueReleased(issuer, amount);
    }

    // ========================
    // 交易 Escrow
    // ========================

    /// @notice 交易资金托管（原子交换中间态）
    function escrow(uint256 orderId, address buyer, uint256 amount) external onlyRole(SETTLER_ROLE) nonReentrant {
        require(amount > 0, "Treasury: zero escrow");
        require(escrows[orderId].amount == 0, "Treasury: escrow exists");

        stablecoin.transferFrom(buyer, address(this), amount);
        escrows[orderId] = EscrowInfo({
            buyer: buyer,
            amount: amount,
            released: false,
            refunded: false
        });

        emit FundsEscrowed(orderId, buyer, amount);
    }

    /// @notice 释放托管资金给卖方
    function release(
        uint256 orderId,
        address seller,
        uint256 amount,
        uint256 platformFee
    ) external onlyRole(SETTLER_ROLE) nonReentrant {
        EscrowInfo storage info = escrows[orderId];
        require(info.amount > 0, "Treasury: no escrow");
        require(!info.released && !info.refunded, "Treasury: already settled");
        require(amount + platformFee <= info.amount, "Treasury: exceeds escrow");

        info.released = true;

        // 卖方收款
        stablecoin.transfer(seller, amount);
        // 平台手续费归集
        if (platformFee > 0) {
            stablecoin.transfer(platformFeeCollector, platformFee);
        }

        emit FundsReleased(orderId, seller, amount, platformFee);
    }

    /// @notice 退回托管资金给买方
    function refundEscrow(uint256 orderId) external onlyRole(SETTLER_ROLE) nonReentrant {
        EscrowInfo storage info = escrows[orderId];
        require(info.amount > 0, "Treasury: no escrow");
        require(!info.released && !info.refunded, "Treasury: already settled");

        info.refunded = true;
        stablecoin.transfer(info.buyer, info.amount);

        emit FundsRefunded(orderId, info.buyer, info.amount);
    }

    // ========================
    // 管理
    // ========================

    /// @notice 更新平台手续费收集地址
    function setPlatformFeeCollector(address _collector) external onlyRole(GOVERNANCE_ROLE) {
        require(_collector != address(0), "Treasury: zero address");
        platformFeeCollector = _collector;
    }
}
