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

/// @title Redemption1155 — ERC-1155 券兑付合约
/// @notice 支持多单位一次性兑付（burn），平台不介入资金
/// @dev Transparent Proxy 部署。消费者持券到店兑付，合约负责销毁。
contract Redemption1155 is Initializable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    ICouponBatch public couponBatchContract;
    ICompliance public compliance;

    struct RedemptionRecord {
        uint256 typeId;
        uint256 amount;        // 本次兑付数量
        address consumer;
        address issuer;
        bytes32 storeId;
        uint256 redeemedAt;
    }

    uint256 public totalRedemptions;
    mapping(uint256 => RedemptionRecord) public redemptions;

    // --- Events ---
    event BatchCouponRedeemed(
        uint256 indexed typeId,
        uint256 amount,
        address indexed consumer,
        address indexed issuer,
        bytes32 storeId,
        uint256 redemptionId
    );

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

        couponBatchContract = ICouponBatch(_couponBatchContract);
        compliance = ICompliance(_compliance);

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

    /// @notice 兑付 `amount` 单位的 typeId 券
    /// @param typeId ERC-1155 token type ID
    /// @param amount 兑付数量
    /// @param storeId 门店 ID 哈希
    function redeem(
        uint256 typeId,
        uint256 amount,
        bytes32 storeId
    ) external nonReentrant {
        require(amount > 0, "Redemption1155: zero amount");

        // 余额检查（隐含所有权验证）
        require(
            couponBatchContract.balanceOf(msg.sender, typeId) >= amount,
            "Redemption1155: insufficient balance"
        );

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

        ICouponBatch.BatchCouponConfig memory config = couponBatchContract.getConfig(typeId);

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

        // 门店限制检查
        if (config.allowedStores.length > 0) {
            require(
                _isAllowedStore(storeId, config.allowedStores),
                "Redemption1155: store not allowed"
            );
        }

        // 销毁券
        couponBatchContract.burn(msg.sender, typeId, amount);

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

        emit BatchCouponRedeemed(
            typeId, amount, msg.sender, config.issuer, storeId, redemptionId
        );
    }

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

    /// @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;
    }
}
