/**
 * @file tokenization-integration.ts
 * @notice Tokenized asset support in ISO Currency service
 */

import { ISOCurrencyService, CurrencyInfo, ExchangeRate } from './iso-currency.service';
import { TokenRegistry } from '../../contracts/tokenization/TokenRegistry';

export interface TokenizedCurrencyInfo extends CurrencyInfo {
    fabricTokenId: string;
    besuTokenAddress: string;
    reserveId: string;
    backingRatio: number; // 1.0 for 1:1 backing
}

export class TokenizationISOCurrencyIntegration {
    private isoCurrencyService: ISOCurrencyService;
    private tokenRegistry: TokenRegistry;

    constructor(
        isoCurrencyService: ISOCurrencyService,
        tokenRegistry: TokenRegistry
    ) {
        this.isoCurrencyService = isoCurrencyService;
        this.tokenRegistry = tokenRegistry;
    }

    /**
     * Register tokenized asset as ISO currency
     */
    async registerTokenizedCurrency(
        currencyCode: string,
        fabricTokenId: string,
        besuTokenAddress: string,
        reserveId: string
    ): Promise<void> {
        // Register in ISO Currency service
        await this.isoCurrencyService.registerCurrency(currencyCode, besuTokenAddress, true);

        // Store tokenized asset metadata
        const tokenizedInfo: TokenizedCurrencyInfo = {
            currencyCode,
            tokenAddress: besuTokenAddress,
            xauRate: '0', // Will be updated by oracle
            isActive: true,
            isTokenized: true,
            fabricTokenId,
            besuTokenAddress,
            reserveId,
            backingRatio: 1.0
        };

        // Store in registry or database
        // In production, this would be stored in a database
        console.log('Tokenized currency registered:', tokenizedInfo);
    }

    /**
     * Get tokenized currency info
     */
    async getTokenizedCurrency(currencyCode: string): Promise<TokenizedCurrencyInfo | null> {
        const currencyInfo = await this.isoCurrencyService.getCurrencyInfo(currencyCode);
        
        if (!currencyInfo || !currencyInfo.isTokenized) {
            return null;
        }

        // Get token metadata from registry
        if (currencyInfo.tokenAddress) {
            const tokenMetadata = await this.tokenRegistry.getToken(currencyInfo.tokenAddress);
            
            return {
                ...currencyInfo,
                fabricTokenId: tokenMetadata.tokenId,
                besuTokenAddress: currencyInfo.tokenAddress,
                reserveId: tokenMetadata.backingReserve,
                backingRatio: tokenMetadata.backedAmount > 0 
                    ? Number(tokenMetadata.totalSupply) / Number(tokenMetadata.backedAmount)
                    : 1.0
            };
        }

        return null;
    }

    /**
     * Get exchange rate for tokenized asset
     */
    async getTokenizedExchangeRate(
        fromCurrency: string,
        toCurrency: string
    ): Promise<ExchangeRate> {
        // Check if currencies are tokenized
        const fromTokenized = await this.getTokenizedCurrency(fromCurrency);
        const toTokenized = await this.getTokenizedCurrency(toCurrency);

        // If both are tokenized, use 1:1 rate (same underlying asset)
        if (fromTokenized && toTokenized && fromTokenized.currencyCode === toTokenized.currencyCode) {
            return {
                fromCurrency,
                toCurrency,
                rate: '1.0',
                timestamp: Date.now()
            };
        }

        // Otherwise, use standard exchange rate
        return await this.isoCurrencyService.getExchangeRate(fromCurrency, toCurrency);
    }

    /**
     * Map currency code to token address
     */
    async getTokenAddressForCurrency(currencyCode: string): Promise<string | null> {
        const currencyInfo = await this.isoCurrencyService.getCurrencyInfo(currencyCode);
        return currencyInfo?.tokenAddress || null;
    }

    /**
     * Get all tokenized currencies
     */
    async getAllTokenizedCurrencies(): Promise<TokenizedCurrencyInfo[]> {
        const allCurrencies = await this.isoCurrencyService.getSupportedCurrencies();
        const tokenized: TokenizedCurrencyInfo[] = [];

        for (const currencyCode of allCurrencies) {
            const tokenizedInfo = await this.getTokenizedCurrency(currencyCode);
            if (tokenizedInfo) {
                tokenized.push(tokenizedInfo);
            }
        }

        return tokenized;
    }

    /**
     * Update tokenized currency XAU rate
     */
    async updateTokenizedXAURate(currencyCode: string, xauRate: string): Promise<void> {
        // Update in ISO Currency service
        await this.isoCurrencyService.updateXAURate(currencyCode, xauRate);
    }
}
