import { useEffect, useState } from 'react';
import { io, Socket } from 'socket.io-client';
import { buildTradingSocketOptions } from '../../../shared/realtime.js';
import { supabase } from '../lib/supabaseClient';

export interface TradingControlSnapshot {
    mode: 'RUNNING' | 'PAUSED';
    lastChangedBy: string;
    lastChangedAt: number;
    reason?: string;
}

export interface HealthSnapshot {
    tradingLoopHealthy: boolean;
    tradingLoopLastRun: number | null;
    monitorLoopHealthy: boolean;
    monitorLoopLastRun: number | null;
    orderSyncHealthy: boolean;
    orderSyncLastRun: number | null;
    lockContentionCount: number;
    reconciliationLoopHealthy: boolean;
    reconciliationLoopLastRun: number | null;
    reconciliationMismatchCount: number;
    reconciliationMissingFromExchange: number;
    reconciliationMissingInDb: number;
    reconciliationNoGoTrades: number;
    reconciliationParityMismatchTrades?: number;
    reconciliationParityQuarantinedTrades?: number;
    reconciliationParityAutoClosedTrades?: number;
    reconciliationParityMaxMismatchNotionalUsd?: number;
    reconciliationParityTotalMismatchNotionalUsd?: number;
    reconciliationIntegrityWatchdogTriggered: boolean;
    reconciliationLockContentionCount: number;
    tradingControl: TradingControlSnapshot;
}

export interface BotState {
    symbols: {
        [symbol: string]: {
            price: number;
            change24h: number;
            changeToday: number;
            session: string;
            volatility: string;
            signal: string;
            signalTime?: number;
            tradingMode?: 'Paper' | 'Live' | 'Alerts';
            activePosition?: {
                side: 'BUY' | 'SELL';
                entryPrice: number;
                size: number;
                stopLoss: number;
                takeProfit: number;
                unrealizedPnl?: number;
                unrealizedPnlPercent?: number;
                marketValue?: number;
                profileId?: string;
            } | null;
            priceHistory: Array<{ timestamp: number; price: number }>;
            rules: {
                [ruleName: string]: {
                    passed: boolean;
                    reason: string;
                    metadata?: any;
                };
            };
            profileSignals?: {
                [profileId: string]: {
                    profileName?: string;
                    signal: string;
                    passed: boolean;
                    reason?: string;
                    execution?: {
                        status: 'EXECUTED' | 'BLOCKED' | 'SKIPPED';
                        code: string;
                        reason: string;
                        orderId?: string;
                    };
                    rules?: {
                        [ruleName: string]: {
                            passed: boolean;
                            reason: string;
                            metadata?: any;
                        };
                    };
                };
            };
            indicators: {
                ema20_1h?: number;
                ema20_15m?: number;
                ema50_4h?: number;
                ema200_4h?: number;
                rsi_1h?: number;
                rsi_15m?: number;
            };
        };
    };
    alerts: Array<{
        timestamp: number;
        type: 'signal' | 'pulse' | 'error' | 'info';
        symbol: string;
        message: string;
    }>;
    positions: Array<{
        id: string;
        symbol: string;
        side: 'BUY' | 'SELL';
        size: number;
        entryPrice: number;
        currentPrice: number;
        stopLoss: number;
        takeProfit: number;
        unrealizedPnl: number;
        unrealizedPnlPercent: number;
        marketValue: number;
        profileId?: string;
        profileName?: string;
        tradeId?: string;
    }>;
    orders: Array<{
        id: string;
        symbol: string;
        type: string;
        side: string;
        qty: number;
        price: number;
        status: string;
        timestamp: number;
        profileId?: string;
        trade_id?: string;
        subTag?: string;
        action?: string;
        source?: 'BOT' | 'MANUAL';
    }>;
    history: Array<{
        symbol: string;
        side: string;
        entryPrice: number;
        exitPrice: number;
        size: number;
        pnl: number;
        pnlPercent: number;
        reason: string;
        timestamp: number;
        profileId?: string;
        trade_id?: string;
        source?: 'BOT' | 'MANUAL';
    }>;
    settings: {
        executionMode: string;
        riskPerTrade: number;
        totalCapital: number;
        maxOpenTrades: number;
        isAlgoEnabled: boolean;
        enabledRules: string[];
    };
    health?: HealthSnapshot;
    uptime: number;
    accountSnapshot?: {
        buying_power: number;
        cash: number;
        currency: string;
        timestamp: number;
    } | null;
    orderFailures?: Array<{
        profileId?: string;
        userId?: string;
        symbol: string;
        side: 'BUY' | 'SELL';
        qty: number;
        reason: string;
        tradeId?: string;
        subTag?: string;
        timestamp: number;
    }>;
    operationalEvents?: Array<{
        id: string;
        type: string;
        severity: string;
        message: string;
        profileId?: string;
        userId?: string;
        symbol?: string;
        timestamp: number;
    }>;
}

export const DEFAULT_BOT_STATE: BotState = {
    symbols: {},
    positions: [],
    alerts: [],
    orders: [],
    history: [],
    settings: {
        executionMode: 'Alerts',
        riskPerTrade: 0.01,
        totalCapital: 1000,
        maxOpenTrades: 3,
        isAlgoEnabled: false,
        enabledRules: []
    },
    health: {
        tradingLoopHealthy: true,
        tradingLoopLastRun: null,
        monitorLoopHealthy: true,
        monitorLoopLastRun: null,
        orderSyncHealthy: true,
        orderSyncLastRun: null,
        lockContentionCount: 0,
        reconciliationLoopHealthy: true,
        reconciliationLoopLastRun: null,
        reconciliationMismatchCount: 0,
        reconciliationMissingFromExchange: 0,
        reconciliationMissingInDb: 0,
        reconciliationNoGoTrades: 0,
        reconciliationIntegrityWatchdogTriggered: false,
        reconciliationLockContentionCount: 0,
        tradingControl: {
            mode: 'RUNNING',
            lastChangedBy: 'system',
            lastChangedAt: Date.now()
        }
    },
    uptime: 0,
    accountSnapshot: null,
    orderFailures: [],
    operationalEvents: []
};

export const applySymbolUpdate = (
    prev: BotState,
    symbol: string,
    data: BotState['symbols'][string]
): BotState => ({
    ...prev,
    symbols: {
        ...prev.symbols,
        [symbol]: data
    }
});

export const appendAlertUpdate = (prev: BotState, alert: BotState['alerts'][0]): BotState => ({
    ...prev,
    alerts: [...prev.alerts, alert]
});

export const replacePositionsUpdate = (prev: BotState, positions: BotState['positions']): BotState => ({
    ...prev,
    positions
});

export const replaceOrdersUpdate = (prev: BotState, orders: BotState['orders']): BotState => ({
    ...prev,
    orders
});

export const appendHistoryUpdate = (prev: BotState, trade: BotState['history'][0]): BotState => ({
    ...prev,
    history: [...prev.history, trade]
});

export const replaceSettingsUpdate = (prev: BotState, settings: BotState['settings']): BotState => ({
    ...prev,
    settings
});

export const useWebSocket = (url: string) => {
    const [socket, setSocket] = useState<Socket | null>(null);
    const [botState, setBotState] = useState<BotState>(DEFAULT_BOT_STATE);
    const [connected, setConnected] = useState(false);
    const EVENT_BUFFER_LIMIT = 2000;

    useEffect(() => {
        let isCancelled = false;
        let newSocket: Socket | null = null;

        const connectSocket = async () => {
            console.log('🔌 Attempting to connect to:', url);
            const { data } = await supabase.auth.getSession();
            const token = data.session?.access_token;

            if (!token) {
                console.warn('Socket connection skipped: missing authenticated session token');
                setConnected(false);
                return;
            }

            const socketOptions = buildTradingSocketOptions(token, import.meta.env.VITE_SOCKET_PATH);

            newSocket = io(url, socketOptions);

            newSocket.on('connect', () => {
                console.log('✅ Connected to bot');
                setConnected(true);
            });

            newSocket.on('disconnect', () => {
                console.log('❌ Disconnected from bot');
                setConnected(false);
            });

            newSocket.on('connect_error', (error) => {
                console.error('🚨 Connection error:', error.message);
            });

            newSocket.on('state', (state: BotState) => {
                setBotState(prev => ({
                    ...prev,
                    ...state,
                    health: state.health || prev.health
                }));
            });

            newSocket.on('health_update', (health: HealthSnapshot) => {
                setBotState(prev => ({
                    ...prev,
                    health
                }));
            });

            newSocket.on('symbol_update', ({ symbol, data }: any) => {
                setBotState(prev => applySymbolUpdate(prev, symbol, data));
            });

            newSocket.on('new_alert', (alert: BotState['alerts'][0]) => {
                setBotState(prev => appendAlertUpdate(prev, alert));
            });

            newSocket.on('positions_update', (positions: BotState['positions']) => {
                setBotState(prev => replacePositionsUpdate(prev, positions));
            });

            newSocket.on('orders_update', (orders: BotState['orders']) => {
                setBotState(prev => replaceOrdersUpdate(prev, orders));
            });

            newSocket.on('history_update', (trade: BotState['history'][0]) => {
                setBotState(prev => appendHistoryUpdate(prev, trade));
            });

            newSocket.on('settings_update', (settings: BotState['settings']) => {
                setBotState(prev => replaceSettingsUpdate(prev, settings));
            });

            newSocket.on('account_snapshot', (snapshot: any) => {
                setBotState(prev => ({
                    ...prev,
                    accountSnapshot: snapshot
                }));
            });

            newSocket.on('order_failure', (failure: any) => {
                const enrichedFailure = {
                    ...failure,
                    timestamp: failure.timestamp || Date.now()
                };
                setBotState(prev => ({
                    ...prev,
                    orderFailures: [enrichedFailure, ...(prev.orderFailures || [])].slice(0, EVENT_BUFFER_LIMIT)
                }));
            });

            newSocket.on('operational_event', (event: any) => {
                setBotState(prev => ({
                    ...prev,
                    operationalEvents: [event, ...(prev.operationalEvents || [])].slice(0, EVENT_BUFFER_LIMIT)
                }));
            });

            newSocket.on('operational_event_cleared', () => {
                setBotState(prev => ({
                    ...prev,
                    operationalEvents: []
                }));
            });

            if (!isCancelled) {
                setSocket(newSocket);
            } else {
                newSocket.close();
            }
        };

        connectSocket().catch((error) => {
            console.error('🚨 Failed to initialize socket:', error);
            setConnected(false);
        });

        return () => {
            isCancelled = true;
            if (newSocket) {
                newSocket.close();
            }
        };
    }, [url]);

    return { socket, botState, connected };
};
