// 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 "./interfaces/ICoupon.sol";

/// @title Compliance — 合规合约
/// @notice OFAC 黑名单筛查、Travel Rule、KYC 差异化检查、账户冻结
/// @dev 使用 Transparent Proxy 部署
contract Compliance is Initializable, AccessControlUpgradeable {
    bytes32 public constant COMPLIANCE_OFFICER_ROLE = keccak256("COMPLIANCE_OFFICER_ROLE");
    bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
    bytes32 public constant KYC_PROVIDER_ROLE = keccak256("KYC_PROVIDER_ROLE");

    // OFAC 黑名单
    mapping(address => bool) private _blacklist;
    // 冻结账户（紧急冻结，需 Governance 多签）
    mapping(address => bool) private _frozen;
    // KYC 等级映射: 0=L0(未验证), 1=L1(基本), 2=L2(增强), 3=L3(机构)
    mapping(address => uint8) private _kycLevels;
    // Travel Rule 记录
    mapping(address => mapping(address => bool)) private _travelRuleRecorded;
    // Travel Rule 详情
    mapping(bytes32 => TravelRuleRecord) private _travelRuleRecords;

    struct TravelRuleRecord {
        address sender;
        address receiver;
        bytes32 senderInfoHash;
        bytes32 receiverInfoHash;
        uint256 recordedAt;
    }

    // Travel Rule 阈值（美元，USDC 精度 6 位）
    uint256 public constant TRAVEL_RULE_THRESHOLD = 3000e6; // $3,000
    // 大额交易阈值
    uint256 public constant LARGE_TRADE_THRESHOLD = 10000e6; // $10,000

    // --- Events ---
    event AddressBlacklisted(address indexed account, string reason);
    event AddressRemovedFromBlacklist(address indexed account);
    event AccountFrozen(address indexed account);
    event AccountUnfrozen(address indexed account);
    event KycLevelUpdated(address indexed account, uint8 oldLevel, uint8 newLevel);
    event TravelRuleRecorded(
        address indexed sender,
        address indexed receiver,
        bytes32 senderInfoHash,
        bytes32 receiverInfoHash
    );

    function initialize(address admin) external initializer {
        __AccessControl_init();

        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(COMPLIANCE_OFFICER_ROLE, admin);
        _grantRole(GOVERNANCE_ROLE, admin);
        _grantRole(KYC_PROVIDER_ROLE, admin);
    }

    // ========================
    // OFAC 黑名单
    // ========================

    /// @notice OFAC 筛查
    function isBlacklisted(address account) external view returns (bool) {
        return _blacklist[account];
    }

    /// @notice 添加 OFAC 黑名单
    function addToBlacklist(address account, string calldata reason)
        external
        onlyRole(COMPLIANCE_OFFICER_ROLE)
    {
        _blacklist[account] = true;
        emit AddressBlacklisted(account, reason);
    }

    /// @notice 从黑名单移除
    function removeFromBlacklist(address account) external onlyRole(GOVERNANCE_ROLE) {
        _blacklist[account] = false;
        emit AddressRemovedFromBlacklist(account);
    }

    // ========================
    // 账户冻结
    // ========================

    /// @notice 查询是否冻结
    function isFrozen(address account) external view returns (bool) {
        return _frozen[account];
    }

    /// @notice 紧急冻结（需 Governance 多签）
    function freezeAccount(address account) external onlyRole(GOVERNANCE_ROLE) {
        _frozen[account] = true;
        emit AccountFrozen(account);
    }

    /// @notice 解除冻结
    function unfreezeAccount(address account) external onlyRole(GOVERNANCE_ROLE) {
        _frozen[account] = false;
        emit AccountUnfrozen(account);
    }

    // ========================
    // KYC 等级管理
    // ========================

    /// @notice 获取 KYC 等级
    function getKycLevel(address account) external view returns (uint8) {
        return _kycLevels[account];
    }

    /// @notice 设置 KYC 等级
    function setKycLevel(address account, uint8 level) external onlyRole(KYC_PROVIDER_ROLE) {
        require(level <= 3, "Compliance: invalid KYC level");
        uint8 oldLevel = _kycLevels[account];
        _kycLevels[account] = level;
        emit KycLevelUpdated(account, oldLevel, level);
    }

    /// @notice 批量设置 KYC 等级
    function batchSetKycLevel(address[] calldata accounts, uint8[] calldata levels)
        external
        onlyRole(KYC_PROVIDER_ROLE)
    {
        require(accounts.length == levels.length, "Compliance: length mismatch");
        for (uint256 i = 0; i < accounts.length; i++) {
            require(levels[i] <= 3, "Compliance: invalid KYC level");
            uint8 oldLevel = _kycLevels[accounts[i]];
            _kycLevels[accounts[i]] = levels[i];
            emit KycLevelUpdated(accounts[i], oldLevel, levels[i]);
        }
    }

    /// @notice 要求最低 KYC 等级（revert if不满足）
    function requireKycLevel(address account, uint8 requiredLevel) external view {
        require(_kycLevels[account] >= requiredLevel, "Compliance: insufficient KYC level");
    }

    // ========================
    // Travel Rule
    // ========================

    /// @notice 记录 Travel Rule 数据（≥$3,000 强制）
    function recordTravelRule(
        address sender,
        address receiver,
        bytes32 senderInfoHash,
        bytes32 receiverInfoHash
    ) external onlyRole(COMPLIANCE_OFFICER_ROLE) {
        require(sender != address(0) && receiver != address(0), "Compliance: zero address");
        require(senderInfoHash != bytes32(0) && receiverInfoHash != bytes32(0), "Compliance: empty hash");

        _travelRuleRecorded[sender][receiver] = true;

        bytes32 recordId = keccak256(abi.encodePacked(sender, receiver, block.timestamp));
        _travelRuleRecords[recordId] = TravelRuleRecord({
            sender: sender,
            receiver: receiver,
            senderInfoHash: senderInfoHash,
            receiverInfoHash: receiverInfoHash,
            recordedAt: block.timestamp
        });

        emit TravelRuleRecorded(sender, receiver, senderInfoHash, receiverInfoHash);
    }

    /// @notice 查询 Travel Rule 是否已记录
    function hasTravelRuleRecord(address sender, address receiver) external view returns (bool) {
        return _travelRuleRecorded[sender][receiver];
    }

    // ========================
    // 综合合规检查
    // ========================

    /// @notice 交易前合规检查（Settlement 调用）
    function preTradeCheck(
        address buyer,
        address seller,
        uint256 amount,
        ICoupon.CouponType couponType
    ) external view {
        // OFAC 黑名单检查
        require(!_blacklist[buyer], "Compliance: buyer blacklisted");
        require(!_blacklist[seller], "Compliance: seller blacklisted");

        // 冻结检查
        require(!_frozen[buyer], "Compliance: buyer frozen");
        require(!_frozen[seller], "Compliance: seller frozen");

        // Utility Track: 双方至少 KYC L1
        if (couponType == ICoupon.CouponType.Utility) {
            require(_kycLevels[buyer] >= 1, "Compliance: buyer needs KYC L1 for Utility");
            require(_kycLevels[seller] >= 1, "Compliance: seller needs KYC L1 for Utility");
        }
        // Securities Track: 双方至少 KYC L2
        else {
            require(_kycLevels[buyer] >= 2, "Compliance: buyer needs KYC L2 for Security");
            require(_kycLevels[seller] >= 2, "Compliance: seller needs KYC L2 for Security");
        }

        // 大额交易: KYC L2+
        if (amount >= LARGE_TRADE_THRESHOLD) {
            require(_kycLevels[buyer] >= 2, "Compliance: buyer needs KYC L2 for large trade");
            require(_kycLevels[seller] >= 2, "Compliance: seller needs KYC L2 for large trade");
        }
    }

    /// @notice P2P 转移合规路由
    function p2pComplianceCheck(
        address sender,
        address receiver,
        uint256 amount
    ) external view {
        require(!_blacklist[sender], "Compliance: sender blacklisted");
        require(!_blacklist[receiver], "Compliance: receiver blacklisted");
        require(!_frozen[sender], "Compliance: sender frozen");
        require(!_frozen[receiver], "Compliance: receiver frozen");

        // ≥$3,000 强制 Travel Rule
        if (amount >= TRAVEL_RULE_THRESHOLD) {
            require(_kycLevels[sender] >= 2, "Compliance: sender needs KYC L2 for Travel Rule");
            require(_kycLevels[receiver] >= 2, "Compliance: receiver needs KYC L2 for Travel Rule");
            require(_travelRuleRecorded[sender][receiver], "Compliance: Travel Rule data required");
        }
    }
}
