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

import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

/**
 * @title InstrumentRegistry
 * @notice Maps lineId → M0/M1 ERC-20s, ISO-4217 metadata, and pause per line.
 */
contract InstrumentRegistry is AccessControl {
    bytes32 public constant REGISTRY_ADMIN_ROLE = keccak256("REGISTRY_ADMIN_ROLE");

    struct Line {
        address tokenM0;
        address tokenM1;
        uint8 decimals;
        uint16 iso4217Numeric;
        bool isXAU;
        bool active;
    }

    mapping(bytes32 lineId => Line) private _lines;
    bytes32[] private _allLineIds;

    event LineRegistered(
        bytes32 indexed lineId,
        address tokenM0,
        address tokenM1,
        uint8 decimals,
        uint16 iso4217Numeric,
        bool isXAU
    );
    event LineUpdated(bytes32 indexed lineId, bool active);
    event LineTokensUpdated(bytes32 indexed lineId, address tokenM0, address tokenM1);

    constructor(address admin) {
        require(admin != address(0), "InstrumentRegistry: zero admin");
        _grantRole(DEFAULT_ADMIN_ROLE, admin);
        _grantRole(REGISTRY_ADMIN_ROLE, admin);
    }

    function registerLine(
        bytes32 lineId,
        address tokenM0,
        address tokenM1,
        uint8 decimals_,
        uint16 iso4217Numeric,
        bool isXAU
    ) external onlyRole(REGISTRY_ADMIN_ROLE) {
        require(lineId != bytes32(0), "InstrumentRegistry: zero lineId");
        require(tokenM0 != address(0) && tokenM1 != address(0), "InstrumentRegistry: zero token");
        require(_lines[lineId].tokenM0 == address(0), "InstrumentRegistry: exists");

        _lines[lineId] = Line({
            tokenM0: tokenM0,
            tokenM1: tokenM1,
            decimals: decimals_,
            iso4217Numeric: iso4217Numeric,
            isXAU: isXAU,
            active: true
        });

        _allLineIds.push(lineId);
        emit LineRegistered(lineId, tokenM0, tokenM1, decimals_, iso4217Numeric, isXAU);
    }

    /// @notice All registered line ids (order of registration).
    function allLineIds() external view returns (bytes32[] memory) {
        return _allLineIds;
    }

    function setLineActive(bytes32 lineId, bool active) external onlyRole(REGISTRY_ADMIN_ROLE) {
        require(_lines[lineId].tokenM0 != address(0), "InstrumentRegistry: unknown line");
        _lines[lineId].active = active;
        emit LineUpdated(lineId, active);
    }

    function setLineTokens(bytes32 lineId, address tokenM0, address tokenM1)
        external
        onlyRole(REGISTRY_ADMIN_ROLE)
    {
        require(_lines[lineId].tokenM0 != address(0), "InstrumentRegistry: unknown line");
        require(tokenM0 != address(0) && tokenM1 != address(0), "InstrumentRegistry: zero token");
        _lines[lineId].tokenM0 = tokenM0;
        _lines[lineId].tokenM1 = tokenM1;
        emit LineTokensUpdated(lineId, tokenM0, tokenM1);
    }

    function getLine(bytes32 lineId) external view returns (Line memory) {
        return _lines[lineId];
    }
}
