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

/**
 * @title IISO4217WToken
 * @notice Interface for ISO-4217 W tokens (e.g., USDW, EURW, GBPW)
 * @dev M1 eMoney tokens representing 1:1 redeemable digital claims on fiat currency
 * 
 * COMPLIANCE:
 * - Classification: M1 eMoney
 * - Legal Tender: NO
 * - Synthetic / Reserve Unit: NO
 * - Commodity-Backed: NO
 * - Money Multiplier: m = 1.0 (fixed, no fractional reserve)
 */
interface IISO4217WToken {
    /**
     * @notice Get the ISO-4217 currency code this token represents
     * @return currencyCode 3-letter ISO-4217 code (e.g., "USD")
     */
    function currencyCode() external view returns (string memory);

    /**
     * @notice Get total supply of tokens
     * @return supply Total supply
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Get verified reserve balance for this currency
     * @return reserveBalance Reserve balance in base currency units
     */
    function verifiedReserve() external view returns (uint256);

    /**
     * @notice Check if reserves are sufficient
     * @return isSufficient True if verifiedReserve >= totalSupply
     */
    function isReserveSufficient() external view returns (bool);

    /**
     * @notice Get custodian address
     * @return custodian Custodian address
     */
    function custodian() external view returns (address);

    /**
     * @notice Get mint controller address
     * @return mintController Mint controller address
     */
    function mintController() external view returns (address);

    /**
     * @notice Get burn controller address
     * @return burnController Burn controller address
     */
    function burnController() external view returns (address);

    /**
     * @notice Get compliance guard address
     * @return complianceGuard Compliance guard address
     */
    function complianceGuard() external view returns (address);

    /**
     * @notice Mint tokens to an address
     * @param to Address to mint to
     * @param amount Amount to mint
     */
    function mint(address to, uint256 amount) external;

    /**
     * @notice Burn tokens from an address
     * @param from Address to burn from
     * @param amount Amount to burn
     */
    function burn(address from, uint256 amount) external;

    event Minted(address indexed to, uint256 amount, string indexed currencyCode);
    event Burned(address indexed from, uint256 amount, string indexed currencyCode);
    event ReserveUpdated(uint256 newReserve, uint256 timestamp);
    event ReserveInsufficient(uint256 reserve, uint256 supply);
}
