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

/// @title ExchangeRateOracle — 汇率预言机集成
/// @notice 集成 Chainlink Price Feed，提供各币种对 USD 汇率
/// @dev 支持多币种，内置过期保护（最多15分钟）
contract ExchangeRateOracle is Initializable, AccessControlUpgradeable {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

    // 币种 → Chainlink Price Feed 地址
    mapping(string => address) public priceFeeds;
    // 支持的币种列表
    string[] public supportedCurrencies;

    // 汇率数据最大容许延迟（秒）
    uint256 public maxStaleness;

    // --- Events ---
    event PriceFeedSet(string indexed currency, address feed);
    event PriceFeedRemoved(string indexed currency);
    event MaxStalenessUpdated(uint256 oldValue, uint256 newValue);

    function initialize(uint256 _maxStaleness, address admin) external initializer {
        __AccessControl_init();

        maxStaleness = _maxStaleness > 0 ? _maxStaleness : 900; // 默认 15 分钟

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

    /// @notice 获取某币种对 USD 的汇率
    /// @param currency 币种标识（如 "CNY", "JPY", "EUR"）
    /// @return rate 汇率（Chainlink 精度，通常 8 位小数）
    function getRate(string calldata currency) external view returns (uint256 rate) {
        address feed = priceFeeds[currency];
        require(feed != address(0), "Oracle: unsupported currency");

        (, int256 answer,, uint256 updatedAt,) = IChainlinkPriceFeed(feed).latestRoundData();
        require(answer > 0, "Oracle: invalid price");
        require(block.timestamp - updatedAt <= maxStaleness, "Oracle: stale price data");

        rate = uint256(answer);
    }

    /// @notice 获取汇率及详细信息
    function getRateDetails(string calldata currency)
        external
        view
        returns (uint256 rate, uint256 updatedAt, uint8 decimals)
    {
        address feed = priceFeeds[currency];
        require(feed != address(0), "Oracle: unsupported currency");

        (, int256 answer,, uint256 _updatedAt,) = IChainlinkPriceFeed(feed).latestRoundData();
        require(answer > 0, "Oracle: invalid price");

        rate = uint256(answer);
        updatedAt = _updatedAt;
        decimals = IChainlinkPriceFeed(feed).decimals();
    }

    /// @notice 设置币种的 Price Feed 地址
    function setPriceFeed(string calldata currency, address feed) external onlyRole(ADMIN_ROLE) {
        require(feed != address(0), "Oracle: zero address");
        require(bytes(currency).length > 0, "Oracle: empty currency");

        // 新增还是更新
        if (priceFeeds[currency] == address(0)) {
            supportedCurrencies.push(currency);
        }

        priceFeeds[currency] = feed;
        emit PriceFeedSet(currency, feed);
    }

    /// @notice 移除币种 Price Feed
    function removePriceFeed(string calldata currency) external onlyRole(ADMIN_ROLE) {
        require(priceFeeds[currency] != address(0), "Oracle: feed not found");
        priceFeeds[currency] = address(0);
        emit PriceFeedRemoved(currency);
    }

    /// @notice 更新最大过期时间
    function setMaxStaleness(uint256 _maxStaleness) external onlyRole(ADMIN_ROLE) {
        require(_maxStaleness > 0, "Oracle: zero staleness");
        uint256 old = maxStaleness;
        maxStaleness = _maxStaleness;
        emit MaxStalenessUpdated(old, _maxStaleness);
    }

    /// @notice 获取支持的币种数量
    function supportedCurrencyCount() external view returns (uint256) {
        return supportedCurrencies.length;
    }
}
