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

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./interfaces/IComplianceGuard.sol";
import "./libraries/ISO4217WCompliance.sol";

/**
 * @title ComplianceGuard
 * @notice Enforces compliance rules for ISO-4217 W tokens
 * @dev Hard constraints: m=1.0, GRU isolation, reserve constraints
 */
contract ComplianceGuard is IComplianceGuard, AccessControl {
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");

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

    /**
     * @notice Validate mint operation
     * @param currencyCode ISO-4217 currency code
     * @param amount Amount to mint
     * @param currentSupply Current token supply
     * @param verifiedReserve Verified reserve balance
     * @return isValid True if mint is compliant
     * @return reasonCode Reason if not compliant
     */
    function validateMint(
        string memory currencyCode,
        uint256 amount,
        uint256 currentSupply,
        uint256 verifiedReserve
    ) external pure override returns (bool isValid, bytes32 reasonCode) {
        // Check ISO-4217 format
        if (!ISO4217WCompliance.isValidISO4217Format(currencyCode)) {
            return (false, keccak256("INVALID_ISO4217_FORMAT"));
        }
        
        // Check GRU isolation
        if (ISO4217WCompliance.violatesGRUIsolation(currencyCode)) {
            return (false, keccak256("GRU_ISOLATION_VIOLATION"));
        }
        
        // Validate money multiplier = 1.0
        (bool multiplierValid, bytes32 multiplierReason) = ISO4217WCompliance.validateMoneyMultiplier(
            verifiedReserve,
            currentSupply
        );
        if (!multiplierValid) {
            return (false, multiplierReason);
        }
        
        // Validate reserve for mint
        (bool reserveValid, bytes32 reserveReason) = ISO4217WCompliance.validateReserveForMint(
            verifiedReserve,
            currentSupply,
            amount
        );
        if (!reserveValid) {
            return (false, reserveReason);
        }
        
        // Event emission removed - this is a pure function for validation only
        // Events should be emitted by calling functions if needed
        return (true, bytes32(0));
    }

    /**
     * @notice Validate that money multiplier = 1.0
     * @dev Hard constraint: m = 1.0 (no fractional reserve)
     * @param reserve Reserve balance
     * @param supply Token supply
     * @return isValid True if multiplier = 1.0
     */
    function validateMoneyMultiplier(uint256 reserve, uint256 supply) external pure override returns (bool isValid) {
        (isValid, ) = ISO4217WCompliance.validateMoneyMultiplier(reserve, supply);
    }

    /**
     * @notice Check if currency is ISO-4217 compliant
     * @param currencyCode Currency code to validate
     * @return isISO4217 True if ISO-4217 compliant
     */
    function isISO4217Compliant(string memory currencyCode) external pure override returns (bool isISO4217) {
        return ISO4217WCompliance.isValidISO4217Format(currencyCode) &&
               !ISO4217WCompliance.violatesGRUIsolation(currencyCode);
    }

    /**
     * @notice Check if operation violates GRU isolation
     * @param currencyCode Currency code
     * @return violatesIsolation True if GRU linkage detected
     */
    function violatesGRUIsolation(string memory currencyCode) external pure override returns (bool violatesIsolation) {
        return ISO4217WCompliance.violatesGRUIsolation(currencyCode);
    }

    /**
     * @notice Validate reserve sufficiency
     * @param reserve Reserve balance
     * @param supply Token supply
     * @return isSufficient True if reserve >= supply
     */
    function isReserveSufficient(uint256 reserve, uint256 supply) external pure override returns (bool isSufficient) {
        return ISO4217WCompliance.isReserveSufficient(reserve, supply);
    }
}
