/**
 * usePredictions Hook
 * Custom hook for fetching ML price predictions for a specific symbol and timeframe
 * Uses TanStack Query for efficient caching and refetching
 */

import { useQuery, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/apiClient';
import type { MLPrediction } from '../../types/mlOverlay.types';

// ============================================================================
// Constants
// ============================================================================

const STALE_TIME = 30000; // 30 seconds
const CACHE_TIME = 300000; // 5 minutes
const ML_API_URL = import.meta.env.VITE_ML_URL || 'http://localhost:3083';

// ============================================================================
// Types
// ============================================================================

export interface PredictionResponse {
  symbol: string;
  timeframe: string;
  predictions: MLPrediction[];
  model: string;
  confidence: number;
  generatedAt: string;
}

export interface UsePredictionsOptions {
  symbol: string;
  timeframe: string;
  enabled?: boolean;
  refetchInterval?: number | false;
  lookAhead?: number; // Number of candles to predict ahead
}

export interface UsePredictionsResult {
  predictions: MLPrediction[];
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  isFetching: boolean;
  refetch: () => void;
  model: string | null;
  confidence: number;
  lastUpdated: Date | null;
}

// ============================================================================
// API Function
// ============================================================================

async function fetchPredictions(
  symbol: string,
  timeframe: string,
  lookAhead: number
): Promise<PredictionResponse> {
  try {
    // Try the Express proxy first
    const response = await apiClient.get(`/proxy/ml/predictions/${symbol}/${timeframe}`, {
      params: { lookAhead },
    });
    return response.data;
  } catch (proxyError) {
    // Fallback to direct ML engine call
    try {
      const response = await fetch(
        `${ML_API_URL}/api/ml/predictions/${symbol}/${timeframe}?lookAhead=${lookAhead}`
      );

      if (!response.ok) {
        throw new Error(`Failed to fetch predictions: ${response.statusText}`);
      }

      return response.json();
    } catch (directError) {
      console.error('Both proxy and direct ML calls failed:', { proxyError, directError });
      throw directError;
    }
  }
}

// ============================================================================
// Hook
// ============================================================================

export function usePredictions({
  symbol,
  timeframe,
  enabled = true,
  refetchInterval = 60000,
  lookAhead = 5,
}: UsePredictionsOptions): UsePredictionsResult {
  const queryClient = useQueryClient();

  const queryKey = ['ml-predictions', symbol, timeframe, lookAhead];

  const {
    data,
    isLoading,
    isError,
    error,
    isFetching,
    refetch,
  } = useQuery({
    queryKey,
    queryFn: () => fetchPredictions(symbol, timeframe, lookAhead),
    staleTime: STALE_TIME,
    gcTime: CACHE_TIME,
    enabled: enabled && !!symbol && !!timeframe,
    refetchInterval,
    retry: 2,
    retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000),
  });

  // Prefetch next timeframe predictions
  const prefetchNextTimeframe = () => {
    const timeframes = ['1m', '5m', '15m', '30m', '1h', '4h', '1d'];
    const currentIndex = timeframes.indexOf(timeframe);
    const nextTimeframe = timeframes[currentIndex + 1] || timeframes[0];

    queryClient.prefetchQuery({
      queryKey: ['ml-predictions', symbol, nextTimeframe, lookAhead],
      queryFn: () => fetchPredictions(symbol, nextTimeframe, lookAhead),
      staleTime: STALE_TIME,
    });
  };

  // Trigger prefetch when data is successfully loaded
  if (data && !isLoading) {
    prefetchNextTimeframe();
  }

  return {
    predictions: data?.predictions || [],
    isLoading,
    isError,
    error: error as Error | null,
    isFetching,
    refetch,
    model: data?.model || null,
    confidence: data?.confidence || 0,
    lastUpdated: data?.generatedAt ? new Date(data.generatedAt) : null,
  };
}

export default usePredictions;
