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

import "./UniversalCCIPBridge.sol";
import "../vault/libraries/GRUConstants.sol";

/**
 * @title GRUCCIPBridge
 * @notice Specialized bridge for Global Reserve Unit (GRU) tokens
 * @dev Supports layer conversions (M00/M0/M1) and XAU triangulation
 */
contract GRUCCIPBridge is UniversalCCIPBridge {
    using GRUConstants for *;

    struct GRUBridgeOperation {
        address token;
        uint256 amount;
        uint64 destinationChain;
        address recipient;
        string sourceLayer;
        string targetLayer;
        bool useXAUTriangulation;
    }

    event GRULayerConversion(
        bytes32 indexed messageId,
        string sourceLayer,
        string targetLayer,
        uint256 sourceAmount,
        uint256 targetAmount
    );

    event GRUCrossCurrencyBridge(
        bytes32 indexed messageId,
        address sourceToken,
        address destToken,
        uint256 amount
    );

    /**
     * @notice Bridge GRU with layer conversion
     */
    function bridgeGRUWithConversion(
        address token,
        string calldata sourceLayer,
        uint256 amount,
        uint64 destinationChain,
        string calldata targetLayer,
        address recipient
    ) external nonReentrant returns (bytes32 messageId) {
        require(GRUConstants.isValidGRULayer(sourceLayer), "Invalid source layer");
        require(GRUConstants.isValidGRULayer(targetLayer), "Invalid target layer");
        
        UniversalAssetRegistry.UniversalAsset memory asset = assetRegistry.getAsset(token);
        require(asset.assetType == UniversalAssetRegistry.AssetType.GRU, "Not GRU asset");
        require(asset.isActive, "Asset not active");
        
        uint256 targetAmount = _convertGRULayers(sourceLayer, targetLayer, amount);
        
        BridgeOperation memory op = BridgeOperation({
            token: token,
            amount: amount,
            destinationChain: destinationChain,
            recipient: recipient,
            assetType: bytes32(uint256(UniversalAssetRegistry.AssetType.GRU)),
            usePMM: false,
            useVault: false,
            complianceProof: "",
            vaultInstructions: ""
        });
        
        messageId = this.bridge(op);
        
        emit GRULayerConversion(messageId, sourceLayer, targetLayer, amount, targetAmount);
        
        return messageId;
    }

    /**
     * @notice Convert between GRU layers
     */
    function _convertGRULayers(
        string memory sourceLayer,
        string memory targetLayer,
        uint256 amount
    ) internal pure returns (uint256) {
        bytes32 sourceHash = keccak256(bytes(sourceLayer));
        bytes32 targetHash = keccak256(bytes(targetLayer));
        bytes32 m00Hash = keccak256(bytes(GRUConstants.GRU_M00));
        bytes32 m0Hash = keccak256(bytes(GRUConstants.GRU_M0));
        bytes32 m1Hash = keccak256(bytes(GRUConstants.GRU_M1));
        
        if (sourceHash == m00Hash && targetHash == m0Hash) {
            return GRUConstants.m00ToM0(amount);
        }
        if (sourceHash == m00Hash && targetHash == m1Hash) {
            return GRUConstants.m00ToM1(amount);
        }
        if (sourceHash == m0Hash && targetHash == m00Hash) {
            return GRUConstants.m0ToM00(amount);
        }
        if (sourceHash == m0Hash && targetHash == m1Hash) {
            return GRUConstants.m0ToM1(amount);
        }
        if (sourceHash == m1Hash && targetHash == m00Hash) {
            return GRUConstants.m1ToM00(amount);
        }
        if (sourceHash == m1Hash && targetHash == m0Hash) {
            return GRUConstants.m1ToM0(amount);
        }
        
        return amount;
    }
}
