// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/AccessControl.sol";

contract StablecoinReferenceRegistry is AccessControl {
    bytes32 public constant STABLECOIN_REGISTRAR_ROLE = keccak256("STABLECOIN_REGISTRAR");

    enum StablecoinStatus { ACTIVE, SUSPENDED, REVOKED }

    struct StablecoinEntry {
        string tokenSymbol;
        address tokenAddress;
        string issuerOrBridge;
        string legalClaimType;
        string redemptionPath;
        string reserveDisclosureRef;
        uint8 riskTier;
        address pauseAuthority;
        StablecoinStatus status;
        bool exists;
    }

    mapping(address => StablecoinEntry) private _byAddress;
    address[] private _addressList;

    event StablecoinRegistered(
        address indexed tokenAddress,
        string tokenSymbol,
        StablecoinStatus status
    );
    event StablecoinStatusUpdated(address indexed tokenAddress, StablecoinStatus status);

    constructor(address admin) {
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(STABLECOIN_REGISTRAR_ROLE, admin);
    }

    function register(
        address tokenAddress,
        string calldata tokenSymbol,
        string calldata issuerOrBridge,
        string calldata legalClaimType,
        string calldata redemptionPath,
        string calldata reserveDisclosureRef,
        uint8 riskTier,
        address pauseAuthority
    ) external onlyRole(STABLECOIN_REGISTRAR_ROLE) {
        require(tokenAddress != address(0), "DBIS: zero address");
        require(!_byAddress[tokenAddress].exists, "DBIS: already registered");
        _setEntry(tokenAddress, tokenSymbol, issuerOrBridge, legalClaimType, redemptionPath, reserveDisclosureRef, riskTier, pauseAuthority);
        _addressList.push(tokenAddress);
        emit StablecoinRegistered(tokenAddress, tokenSymbol, StablecoinStatus.ACTIVE);
    }

    function _setEntry(
        address tokenAddress,
        string calldata tokenSymbol,
        string calldata issuerOrBridge,
        string calldata legalClaimType,
        string calldata redemptionPath,
        string calldata reserveDisclosureRef,
        uint8 riskTier,
        address pauseAuthority
    ) private {
        StablecoinEntry storage e = _byAddress[tokenAddress];
        e.tokenSymbol = tokenSymbol;
        e.tokenAddress = tokenAddress;
        e.issuerOrBridge = issuerOrBridge;
        e.legalClaimType = legalClaimType;
        e.redemptionPath = redemptionPath;
        e.reserveDisclosureRef = reserveDisclosureRef;
        e.riskTier = riskTier;
        e.pauseAuthority = pauseAuthority;
        e.status = StablecoinStatus.ACTIVE;
        e.exists = true;
    }

    function setStatus(address tokenAddress, StablecoinStatus status) external onlyRole(STABLECOIN_REGISTRAR_ROLE) {
        require(_byAddress[tokenAddress].exists, "DBIS: not registered");
        _byAddress[tokenAddress].status = status;
        emit StablecoinStatusUpdated(tokenAddress, status);
    }

    function getEntry(address tokenAddress) external view returns (StablecoinEntry memory) {
        return _byAddress[tokenAddress];
    }

    function isActive(address tokenAddress) external view returns (bool) {
        return _byAddress[tokenAddress].exists && _byAddress[tokenAddress].status == StablecoinStatus.ACTIVE;
    }

    function getRegisteredCount() external view returns (uint256) {
        return _addressList.length;
    }

    function getRegisteredAt(uint256 index) external view returns (address) {
        require(index < _addressList.length, "DBIS: index");
        return _addressList[index];
    }
}
