/**
 * Custom hook for ML Analysis data fetching and caching
 */

import { useState, useEffect, useCallback, useRef } from 'react';
import {
  ICTAnalysis,
  EnsembleSignal,
  ScanResult,
  getICTAnalysis,
  getEnsembleSignal,
  getQuickSignal,
  scanSymbols,
  checkHealth,
} from '../services/mlService';

// Default trading symbols
export const DEFAULT_SYMBOLS = [
  'EURUSD',
  'GBPUSD',
  'USDJPY',
  'XAUUSD',
  'BTCUSD',
  'ETHUSD',
];

// Cache duration in milliseconds
const CACHE_DURATION = 60000; // 1 minute

interface CacheEntry<T> {
  data: T;
  timestamp: number;
}

interface UseMLAnalysisResult {
  // Data
  ictAnalysis: ICTAnalysis | null;
  ensembleSignal: EnsembleSignal | null;
  scanResults: ScanResult[];

  // State
  loading: boolean;
  error: string | null;
  isHealthy: boolean;

  // Actions
  refreshICT: () => Promise<void>;
  refreshEnsemble: () => Promise<void>;
  refreshScan: () => Promise<void>;
  refreshAll: () => Promise<void>;
  setSymbol: (symbol: string) => void;
  setTimeframe: (timeframe: string) => void;
}

interface UseMLAnalysisOptions {
  symbol?: string;
  timeframe?: string;
  autoRefresh?: boolean;
  refreshInterval?: number;
  symbols?: string[];
  minConfidence?: number;
}

export function useMLAnalysis(options: UseMLAnalysisOptions = {}): UseMLAnalysisResult {
  const {
    symbol: initialSymbol = 'EURUSD',
    timeframe: initialTimeframe = '1H',
    autoRefresh = false,
    refreshInterval = 60000,
    symbols = DEFAULT_SYMBOLS,
    minConfidence = 0.6,
  } = options;

  // State
  const [symbol, setSymbol] = useState(initialSymbol);
  const [timeframe, setTimeframe] = useState(initialTimeframe);
  const [ictAnalysis, setIctAnalysis] = useState<ICTAnalysis | null>(null);
  const [ensembleSignal, setEnsembleSignal] = useState<EnsembleSignal | null>(null);
  const [scanResults, setScanResults] = useState<ScanResult[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [isHealthy, setIsHealthy] = useState(true);

  // Cache refs
  const ictCacheRef = useRef<Map<string, CacheEntry<ICTAnalysis>>>(new Map());
  const ensembleCacheRef = useRef<Map<string, CacheEntry<EnsembleSignal>>>(new Map());
  const scanCacheRef = useRef<CacheEntry<ScanResult[]> | null>(null);

  // Helper to check cache validity
  const isCacheValid = <T,>(entry: CacheEntry<T> | undefined | null): boolean => {
    if (!entry) return false;
    return Date.now() - entry.timestamp < CACHE_DURATION;
  };

  // Fetch ICT Analysis
  const refreshICT = useCallback(async () => {
    const cacheKey = `${symbol}-${timeframe}`;
    const cached = ictCacheRef.current.get(cacheKey);

    if (isCacheValid(cached)) {
      setIctAnalysis(cached!.data);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const data = await getICTAnalysis(symbol, timeframe);
      if (data) {
        setIctAnalysis(data);
        ictCacheRef.current.set(cacheKey, {
          data,
          timestamp: Date.now(),
        });
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch ICT analysis');
    } finally {
      setLoading(false);
    }
  }, [symbol, timeframe]);

  // Fetch Ensemble Signal
  const refreshEnsemble = useCallback(async () => {
    const cacheKey = `${symbol}-${timeframe}`;
    const cached = ensembleCacheRef.current.get(cacheKey);

    if (isCacheValid(cached)) {
      setEnsembleSignal(cached!.data);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const data = await getEnsembleSignal(symbol, timeframe);
      if (data) {
        setEnsembleSignal(data);
        ensembleCacheRef.current.set(cacheKey, {
          data,
          timestamp: Date.now(),
        });
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch ensemble signal');
    } finally {
      setLoading(false);
    }
  }, [symbol, timeframe]);

  // Fetch Scan Results
  const refreshScan = useCallback(async () => {
    if (isCacheValid(scanCacheRef.current)) {
      setScanResults(scanCacheRef.current!.data);
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const results = await scanSymbols(symbols, minConfidence);
      setScanResults(results);
      scanCacheRef.current = {
        data: results,
        timestamp: Date.now(),
      };
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to scan symbols');
    } finally {
      setLoading(false);
    }
  }, [symbols, minConfidence]);

  // Refresh all data
  const refreshAll = useCallback(async () => {
    setLoading(true);
    setError(null);

    try {
      // Check health first
      const healthy = await checkHealth();
      setIsHealthy(healthy);

      if (!healthy) {
        setError('ML Engine is not available');
        return;
      }

      // Fetch all data in parallel
      await Promise.all([
        refreshICT(),
        refreshEnsemble(),
        refreshScan(),
      ]);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to refresh data');
    } finally {
      setLoading(false);
    }
  }, [refreshICT, refreshEnsemble, refreshScan]);

  // Initial fetch
  useEffect(() => {
    refreshAll();
  }, []);

  // Refetch when symbol or timeframe changes
  useEffect(() => {
    refreshICT();
    refreshEnsemble();
  }, [symbol, timeframe, refreshICT, refreshEnsemble]);

  // Auto-refresh
  useEffect(() => {
    if (!autoRefresh) return;

    const interval = setInterval(() => {
      // Clear cache and refresh
      ictCacheRef.current.clear();
      ensembleCacheRef.current.clear();
      scanCacheRef.current = null;
      refreshAll();
    }, refreshInterval);

    return () => clearInterval(interval);
  }, [autoRefresh, refreshInterval, refreshAll]);

  return {
    ictAnalysis,
    ensembleSignal,
    scanResults,
    loading,
    error,
    isHealthy,
    refreshICT,
    refreshEnsemble,
    refreshScan,
    refreshAll,
    setSymbol,
    setTimeframe,
  };
}

/**
 * Hook for quick signals polling
 */
export function useQuickSignals(
  symbols: string[] = DEFAULT_SYMBOLS,
  pollInterval: number = 30000
) {
  const [signals, setSignals] = useState<Map<string, { action: string; confidence: number; score: number }>>(
    new Map()
  );
  const [loading, setLoading] = useState(true);

  const fetchSignals = useCallback(async () => {
    try {
      const results = await Promise.all(
        symbols.map(async (symbol) => {
          const signal = await getQuickSignal(symbol);
          return { symbol, signal };
        })
      );

      const newSignals = new Map();
      results.forEach(({ symbol, signal }) => {
        if (signal) {
          newSignals.set(symbol, signal);
        }
      });
      setSignals(newSignals);
    } catch (error) {
      console.error('Error fetching quick signals:', error);
    } finally {
      setLoading(false);
    }
  }, [symbols]);

  useEffect(() => {
    fetchSignals();
    const interval = setInterval(fetchSignals, pollInterval);
    return () => clearInterval(interval);
  }, [fetchSignals, pollInterval]);

  return { signals, loading, refresh: fetchSignals };
}

export default useMLAnalysis;
