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

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./IRWATokenRegistry.sol";
import "./IRWAToken.sol";
import "./libraries/RWATaxonomy.sol";

/**
 * @title RWATokenRegistry
 * @notice Single source of on-chain truth for Li* index ticker → token address.
 */
contract RWATokenRegistry is AccessControl, IRWATokenRegistry {
    bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");

    mapping(bytes32 => IndexRecord) private _records;
    bytes32[] private _tickers;

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

    function registerIndex(
        string calldata indexTicker,
        address token,
        string calldata symbol
    ) external onlyRole(REGISTRAR_ROLE) {
        require(token != address(0), "RWATokenRegistry: zero token");
        bytes32 key = RWATaxonomy.validateProduct(indexTicker, "Commodities", "M00");
        require(!_records[key].isActive, "RWATokenRegistry: exists");

        IRWAToken rwa = IRWAToken(token);
        require(rwa.isRwaIndex(), "RWATokenRegistry: not RWA");
        require(!rwa.isEmoney(), "RWATokenRegistry: emoney forbidden");
        require(
            keccak256(bytes(rwa.indexTicker())) == key,
            "RWATokenRegistry: ticker mismatch"
        );

        _records[key] = IndexRecord({
            token: token,
            indexTicker: indexTicker,
            symbol: symbol,
            classification: rwa.classification(),
            isActive: true,
            registeredAt: block.timestamp
        });
        _tickers.push(key);

        emit IndexRegistered(indexTicker, token, symbol);
    }

    function getToken(string calldata indexTicker) external view returns (address) {
        bytes32 key = RWATaxonomy.hashString(indexTicker);
        require(_records[key].isActive, "RWATokenRegistry: unknown");
        return _records[key].token;
    }

    function getRecord(string calldata indexTicker) external view returns (IndexRecord memory) {
        bytes32 key = RWATaxonomy.hashString(indexTicker);
        require(_records[key].isActive, "RWATokenRegistry: unknown");
        return _records[key];
    }

    function isRegistered(string calldata indexTicker) external view returns (bool) {
        bytes32 key = RWATaxonomy.hashString(indexTicker);
        return _records[key].isActive;
    }

    function deactivateIndex(string calldata indexTicker) external onlyRole(DEFAULT_ADMIN_ROLE) {
        bytes32 key = RWATaxonomy.hashString(indexTicker);
        IndexRecord storage rec = _records[key];
        require(rec.isActive, "RWATokenRegistry: inactive");
        rec.isActive = false;
        emit IndexDeactivated(indexTicker, rec.token);
    }

    function tickerCount() external view returns (uint256) {
        return _tickers.length;
    }
}
