/**
 * useSignals Hook
 * Custom hook for fetching ML trading signals for a specific symbol
 * Provides real-time signals with BUY/SELL/HOLD recommendations
 */

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '@/lib/apiClient';
import type { EnhancedSignalMarker } from '../../modules/trading/components/charts/overlays/SignalMarkers';

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

const STALE_TIME = 15000; // 15 seconds (signals need to be fresh)
const CACHE_TIME = 180000; // 3 minutes

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

export type SignalDirection = 'long' | 'short';
export type SignalStrength = 'strong' | 'moderate' | 'weak';

export interface TradingSignal {
  signal_id: string;
  symbol: string;
  direction: SignalDirection;
  entry_price: number;
  stop_loss: number;
  take_profit: number;
  risk_reward_ratio: number;
  confidence_score: number;
  prob_tp_first: number;
  amd_phase: string;
  volatility_regime: string;
  valid_until: string;
  created_at: string;
  strength?: SignalStrength;
  reasoning?: string[];
}

export interface SignalsResponse {
  symbol: string;
  signals: TradingSignal[];
  activeSignal: TradingSignal | null;
  timestamp: string;
}

export interface UseSignalsOptions {
  symbol: string;
  enabled?: boolean;
  refetchInterval?: number | false;
  includeHistory?: boolean;
  historyLimit?: number;
}

export interface UseSignalsResult {
  signals: TradingSignal[];
  activeSignal: TradingSignal | null;
  markers: EnhancedSignalMarker[];
  isLoading: boolean;
  isError: boolean;
  error: Error | null;
  isFetching: boolean;
  refetch: () => void;
  generateSignal: () => void;
  isGenerating: boolean;
}

// ============================================================================
// API Functions
// ============================================================================

async function fetchSignals(
  symbol: string,
  includeHistory: boolean,
  historyLimit: number
): Promise<SignalsResponse> {
  try {
    const response = await apiClient.get(`/proxy/ml/signals/latest/${symbol}`, {
      params: { includeHistory, limit: historyLimit },
    });

    const signal = response.data?.signal || response.data;

    return {
      symbol,
      signals: signal ? [signal] : [],
      activeSignal: signal || null,
      timestamp: new Date().toISOString(),
    };
  } catch (error) {
    if ((error as { response?: { status: number } }).response?.status === 404) {
      return {
        symbol,
        signals: [],
        activeSignal: null,
        timestamp: new Date().toISOString(),
      };
    }
    throw error;
  }
}

async function requestSignalGeneration(symbol: string): Promise<TradingSignal | null> {
  const response = await apiClient.post('/proxy/ml/signals/generate', { symbol });
  return response.data?.signal || response.data || null;
}

// ============================================================================
// Helper Functions
// ============================================================================

function convertSignalToMarker(signal: TradingSignal): EnhancedSignalMarker {
  const signalType = signal.direction === 'long' ? 'BUY' : 'SELL';
  const color = signal.direction === 'long' ? '#10b981' : '#ef4444';

  return {
    time: new Date(signal.created_at).getTime(),
    position: signal.direction === 'long' ? 'belowBar' : 'aboveBar',
    color,
    text: `${signalType} ${Math.round(signal.confidence_score * 100)}%`,
    shape: signal.direction === 'long' ? 'arrowUp' : 'arrowDown',
    signalType,
    confidence: signal.confidence_score,
    price: signal.entry_price,
    stopLoss: signal.stop_loss,
    takeProfit: signal.take_profit,
    riskReward: signal.risk_reward_ratio,
  };
}

function getSignalStrength(confidence: number): SignalStrength {
  if (confidence >= 0.8) return 'strong';
  if (confidence >= 0.6) return 'moderate';
  return 'weak';
}

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

export function useSignals({
  symbol,
  enabled = true,
  refetchInterval = 30000,
  includeHistory = false,
  historyLimit = 10,
}: UseSignalsOptions): UseSignalsResult {
  const queryClient = useQueryClient();

  const queryKey = ['ml-signals', symbol, includeHistory, historyLimit];

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

  // Mutation for generating new signals
  const generateMutation = useMutation({
    mutationFn: () => requestSignalGeneration(symbol),
    onSuccess: (newSignal) => {
      if (newSignal) {
        // Update cache with new signal
        queryClient.setQueryData<SignalsResponse>(queryKey, (old) => ({
          symbol,
          signals: [newSignal, ...(old?.signals || [])].slice(0, historyLimit),
          activeSignal: newSignal,
          timestamp: new Date().toISOString(),
        }));
      }
      // Refetch to ensure consistency
      refetch();
    },
  });

  // Convert signals to markers for chart overlay
  const signals = data?.signals || [];
  const signalsWithStrength = signals.map((s) => ({
    ...s,
    strength: s.strength || getSignalStrength(s.confidence_score),
  }));

  const markers: EnhancedSignalMarker[] = signalsWithStrength.map(convertSignalToMarker);

  return {
    signals: signalsWithStrength,
    activeSignal: data?.activeSignal || null,
    markers,
    isLoading,
    isError,
    error: error as Error | null,
    isFetching,
    refetch,
    generateSignal: generateMutation.mutate,
    isGenerating: generateMutation.isPending,
  };
}

export default useSignals;
