/**
 * Firefly Bridge Client
 * Interfaces with Hyperledger Firefly API for multi-chain orchestration
 */

import axios, { AxiosInstance } from 'axios';
import WebSocket from 'ws';

export interface FireflyTokenTransfer {
    namespace: string;
    pool: string;      // Token pool (contract address)
    from: string;      // Sender identity
    to: string;        // Recipient identity  
    amount: string;
    message?: {
        data: any;     // Off-chain data via DataExchange
    };
}

export interface FireflyEvent {
    id: string;
    type: string;
    namespace: string;
    reference: string;
    created: string;
    info: any;
}

export class FireflyBridgeClient {
    private api: AxiosInstance;
    private ws: WebSocket | null = null;
    private namespace: string;

    constructor(apiUrl: string, namespace: string = 'default') {
        this.api = axios.create({
            baseURL: apiUrl,
            headers: {
                'Content-Type': 'application/json'
            }
        });
        this.namespace = namespace;
    }

    /**
     * Transfer token via Firefly
     */
    async transferToken(transfer: FireflyTokenTransfer): Promise<any> {
        const response = await this.api.post('/tokens/transfers', {
            ...transfer,
            namespace: this.namespace
        });
        return response.data;
    }

    /**
     * Get token pools in namespace
     */
    async getTokenPools(): Promise<any[]> {
        const response = await this.api.get(`/namespaces/${this.namespace}/tokens/pools`);
        return response.data;
    }

    /**
     * Create token pool
     */
    async createTokenPool(pool: {
        name: string;
        type: 'fungible' | 'nonfungible';
        config?: any;
    }): Promise<any> {
        const response = await this.api.post(`/namespaces/${this.namespace}/tokens/pools`, {
            ...pool,
            namespace: this.namespace
        });
        return response.data;
    }

    /**
     * Listen to Firefly events via WebSocket
     */
    async listenToEvents(
        callback: (event: FireflyEvent) => void,
        eventTypes?: string[]
    ): Promise<void> {
        const wsUrl = this.api.defaults.baseURL?.replace('http', 'ws') + '/ws';
        this.ws = new WebSocket(wsUrl);

        this.ws.on('message', (data: Buffer) => {
            try {
                const event: FireflyEvent = JSON.parse(data.toString());
                
                // Filter by namespace and event types
                if (event.namespace === this.namespace) {
                    if (!eventTypes || eventTypes.includes(event.type)) {
                        callback(event);
                    }
                }
            } catch (error) {
                console.error('Error parsing Firefly event:', error);
            }
        });

        this.ws.on('error', (error) => {
            console.error('Firefly WebSocket error:', error);
        });

        this.ws.on('close', () => {
            console.log('Firefly WebSocket closed, reconnecting...');
            // Reconnect logic
            setTimeout(() => this.listenToEvents(callback, eventTypes), 5000);
        });
    }

    /**
     * Get transaction status
     */
    async getTransactionStatus(txId: string): Promise<any> {
        const response = await this.api.get(`/namespaces/${this.namespace}/transactions/${txId}`);
        return response.data;
    }

    /**
     * Get blockchain connector status
     */
    async getConnectorStatus(connector: string): Promise<any> {
        const response = await this.api.get(`/namespaces/${this.namespace}/blockchain/${connector}`);
        return response.data;
    }

    /**
     * Close WebSocket connection
     */
    close(): void {
        if (this.ws) {
            this.ws.close();
            this.ws = null;
        }
    }
}
