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

/// @title Redemption — 兑付合约
/// @notice 消费者直接与发行方结算，平台不介入；兑付时销毁券
/// @dev 使用 Transparent Proxy 部署
contract Redemption is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    ICoupon public couponContract;
    ICompliance public compliance;

    // 兑付记录
    struct RedemptionRecord {
        uint256 tokenId;
        address consumer;
        address issuer;
        bytes32 storeId;
        uint256 redeemedAt;
    }

    uint256 public totalRedemptions;
    mapping(uint256 => RedemptionRecord) public redemptions; // redemptionId → record

    // --- Events ---
    event CouponRedeemed(
        uint256 indexed tokenId,
        address indexed consumer,
        address indexed issuer,
        bytes32 storeId,
        uint256 redemptionId
    );

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

        couponContract = ICoupon(_couponContract);
        compliance = ICompliance(_compliance);

        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(ADMIN_ROLE, admin);
    }

    /// @notice 消费者兑付券 — 销毁 NFT，触发事件通知发行方
    /// @param tokenId 券 token ID
    /// @param storeId 门店 ID（bytes32 哈希）
    function redeem(uint256 tokenId, bytes32 storeId) external nonReentrant {
        // 所有权验证
        require(couponContract.ownerOf(tokenId) == msg.sender, "Redemption: not owner");

        // 合规检查
        require(!compliance.isBlacklisted(msg.sender), "Redemption: blacklisted");

        ICoupon.CouponConfig memory config = couponContract.getConfig(tokenId);

        // 到期验证
        require(block.timestamp <= config.expiryDate, "Redemption: coupon expired");

        // 门店限定验证
        if (config.allowedStores.length > 0) {
            require(_isAllowedStore(storeId, config.allowedStores), "Redemption: store not allowed");
        }

        // 销毁券（burn）
        couponContract.burn(tokenId);

        // 记录兑付
        uint256 redemptionId = totalRedemptions++;
        redemptions[redemptionId] = RedemptionRecord({
            tokenId: tokenId,
            consumer: msg.sender,
            issuer: config.issuer,
            storeId: storeId,
            redeemedAt: block.timestamp
        });

        // 通知发行方（event），平台不介入消费数据
        emit CouponRedeemed(tokenId, msg.sender, config.issuer, storeId, redemptionId);
    }

    /// @notice 查询兑付记录
    function getRedemption(uint256 redemptionId) external view returns (RedemptionRecord memory) {
        return redemptions[redemptionId];
    }

    // --- Internal ---

    /// @dev 检查门店是否在允许列表中
    function _isAllowedStore(bytes32 storeId, bytes32[] memory allowedStores) internal pure returns (bool) {
        for (uint256 i = 0; i < allowedStores.length; i++) {
            if (allowedStores[i] == storeId) return true;
        }
        return false;
    }
}
