/**
 * LLM Agent Service
 * Client for connecting to the LLM Agent API (Predictions & Backtesting) via Express Proxy
 * ARCH-001: All LLM calls now go through authenticated Express gateway
 *
 * @version 2.0.0
 */

import { apiClient } from '@/lib/apiClient';

// ============================================================================
// Types - Predictions
// ============================================================================

export interface PredictionRequest {
  symbol: string;
  timeframe?: string;
}

export interface AMDPhaseInfo {
  phase: string;
  confidence: number;
  support: number;
  resistance: number;
}

export interface SignalInfo {
  direction: 'LONG' | 'SHORT' | 'HOLD';
  confidence: number;
  entry_price: number;
  stop_loss: number;
  take_profit: number;
}

export interface RangePredictionInfo {
  predicted_high: number;
  predicted_low: number;
  expected_range_pct: number;
}

export interface ICTContextInfo {
  market_bias: string;
  order_blocks: Array<{ type: string; price: number }>;
  fair_value_gaps: Array<{ type: string; high: number; low: number }>;
}

export interface PredictionResponse {
  symbol: string;
  timeframe: string;
  timestamp: string;
  current_price: number;
  amd_phase: AMDPhaseInfo;
  signal: SignalInfo;
  range_prediction: RangePredictionInfo;
  ict_context: ICTContextInfo;
  confluence_score: number;
  explanation: string;
  risk_assessment?: {
    allowed: boolean;
    recommended_size: number;
    position_risk_pct: number;
    checks: Record<string, boolean>;
  };
}

export interface ActiveSignal {
  symbol: string;
  direction: string;
  confidence: number;
  confluence_score: number;
  entry_price: number;
  stop_loss: number;
  take_profit: number;
  timestamp: string;
}

export interface RiskSummary {
  level: string;
  limits: {
    max_position_size_pct: number;
    max_daily_drawdown_pct: number;
    max_total_exposure_pct: number;
  };
  current_state: {
    daily_pnl: number;
    total_exposure_pct: number;
    open_trades: number;
  };
  circuit_breaker_active: boolean;
}

// ============================================================================
// Types - Backtesting
// ============================================================================

export interface BacktestRequest {
  initial_balance: number;
  risk_per_trade_pct: number;
  max_open_trades: number;
  min_confluence_score: number;
  min_confidence: number;
  symbols: string[];
  timeframe: string;
  days_back: number;
  use_amd_filter: boolean;
  use_killzone_filter: boolean;
}

export interface BacktestStatus {
  id: string;
  status: 'pending' | 'running' | 'completed' | 'failed';
  progress: number;
  started_at?: string;
  completed_at?: string;
  error?: string;
}

export interface BacktestSummary {
  id: string;
  initial_balance: number;
  final_balance: number;
  total_return: number;
  total_return_pct: number;
  total_trades: number;
  win_rate: number;
  profit_factor: number;
  max_drawdown_pct: number;
  sharpe_ratio: number;
  duration_days: number;
}

export interface BacktestTrade {
  id: string;
  symbol: string;
  direction: string;
  entry_price: number;
  exit_price: number;
  entry_time: string;
  exit_time: string;
  pnl: number;
  pnl_pips: number;
  status: string;
  confidence: number;
  amd_phase: string;
  confluence_score: number;
}

export interface EquityCurvePoint {
  timestamp: string;
  equity: number;
  balance: number;
  drawdown_pct: number;
}

export interface BacktestResult {
  summary: {
    initial_balance: number;
    final_balance: number;
    total_return: number;
    total_return_pct: number;
    duration_days: number;
  };
  performance: {
    total_trades: number;
    winning_trades: number;
    losing_trades: number;
    win_rate: number;
    profit_factor: number;
    sharpe_ratio: number;
    sortino_ratio: number;
  };
  risk: {
    max_drawdown: number;
    max_drawdown_pct: number;
    avg_winner: number;
    avg_loser: number;
    largest_winner: number;
    largest_loser: number;
  };
  activity: {
    avg_trade_pnl: number;
    avg_trade_duration_hours: number;
    trades_per_day: number;
  };
  monthly_returns: Record<string, number>;
  trades_by_phase: Record<string, { count: number; wins: number; pnl: number; win_rate: number }>;
  trades_by_symbol: Record<string, { count: number; wins: number; pnl: number; win_rate: number }>;
  equity_curve: EquityCurvePoint[];
  trades: BacktestTrade[];
}

// ============================================================================
// Predictions API
// ============================================================================

/**
 * Analyze a symbol with all ML models
 */
export async function analyzeSymbol(
  symbol: string,
  timeframe: string = '5m'
): Promise<PredictionResponse | null> {
  try {
    const response = await apiClient.post('/proxy/llm/analyze', { symbol, timeframe });
    return response.data;
  } catch (error) {
    console.error('Error analyzing symbol:', error);
    return null;
  }
}

/**
 * Get active signals above minimum confluence
 */
export async function getActiveSignals(
  _minConfluence: number = 0.6
): Promise<ActiveSignal[]> {
  try {
    const response = await apiClient.get('/proxy/llm/signals/active');
    return response.data || [];
  } catch (error) {
    console.error('Error fetching active signals:', error);
    return [];
  }
}

/**
 * Get current risk summary
 */
export async function getRiskSummary(): Promise<RiskSummary | null> {
  try {
    const response = await apiClient.get('/proxy/llm/risk/summary');
    return response.data;
  } catch (error) {
    console.error('Error fetching risk summary:', error);
    return null;
  }
}

/**
 * Set risk level
 */
export async function setRiskLevel(
  level: 'minimal' | 'conservative' | 'moderate' | 'aggressive'
): Promise<boolean> {
  try {
    const response = await apiClient.post('/proxy/llm/risk/level', { level });
    return response.status === 200;
  } catch (error) {
    console.error('Error setting risk level:', error);
    return false;
  }
}

/**
 * Validate a trade against risk rules
 */
export async function validateTrade(params: {
  symbol: string;
  side: 'BUY' | 'SELL';
  size: number;
  entry_price: number;
  stop_loss: number;
  pip_value?: number;
}): Promise<{
  allowed: boolean;
  recommended_size: number;
  position_risk_pct: number;
  checks: Record<string, boolean>;
  formatted_message: string;
} | null> {
  try {
    const response = await apiClient.post('/proxy/llm/validate-trade', {
      symbol: params.symbol,
      direction: params.side === 'BUY' ? 'long' : 'short',
      size: params.size,
      entry: params.entry_price,
      stopLoss: params.stop_loss,
      takeProfit: 0, // Will be calculated by backend
    });
    return response.data;
  } catch (error) {
    console.error('Error validating trade:', error);
    return null;
  }
}

// ============================================================================
// Backtesting API
// ============================================================================

/**
 * Start a new backtest (background)
 */
export async function startBacktest(
  params: Partial<BacktestRequest>
): Promise<BacktestStatus | null> {
  try {
    const request = {
      symbol: params.symbols?.[0] || 'XAUUSD',
      strategy: 'ensemble',
      startDate: new Date(Date.now() - (params.days_back || 365) * 24 * 60 * 60 * 1000).toISOString(),
      endDate: new Date().toISOString(),
      parameters: {
        initial_balance: params.initial_balance || 1000,
        risk_per_trade_pct: params.risk_per_trade_pct || 1.0,
        max_open_trades: params.max_open_trades || 3,
        min_confluence_score: params.min_confluence_score || 0.65,
        min_confidence: params.min_confidence || 0.60,
        use_amd_filter: params.use_amd_filter ?? true,
        use_killzone_filter: params.use_killzone_filter ?? true,
      },
    };

    const response = await apiClient.post('/proxy/llm/backtest/run', request);
    return response.data;
  } catch (error) {
    console.error('Error starting backtest:', error);
    return null;
  }
}

/**
 * Run a quick synchronous backtest (< 90 days)
 */
export async function runQuickBacktest(params: {
  initial_balance?: number;
  days?: number;
  symbol?: string;
}): Promise<BacktestResult | null> {
  try {
    const response = await apiClient.get('/proxy/llm/backtest/quick', {
      params: { symbol: params.symbol || 'XAUUSD' },
    });
    return response.data;
  } catch (error) {
    console.error('Error running quick backtest:', error);
    return null;
  }
}

/**
 * Get backtest status
 */
export async function getBacktestStatus(id: string): Promise<BacktestStatus | null> {
  try {
    const response = await apiClient.get(`/proxy/llm/backtest/status/${id}`);
    return response.data;
  } catch (error) {
    if ((error as { response?: { status: number } }).response?.status === 404) return null;
    console.error('Error fetching backtest status:', error);
    return null;
  }
}

/**
 * Get backtest results
 */
export async function getBacktestResults(id: string): Promise<BacktestResult | null> {
  try {
    const response = await apiClient.get(`/proxy/llm/backtest/results/${id}`);
    return response.data;
  } catch (error) {
    if ((error as { response?: { status: number } }).response?.status === 404) return null;
    console.error('Error fetching backtest results:', error);
    return null;
  }
}

/**
 * List recent backtests
 */
export async function listBacktests(limit: number = 10): Promise<BacktestSummary[]> {
  try {
    const response = await apiClient.get('/proxy/llm/backtest/list', {
      params: { limit },
    });
    return response.data || [];
  } catch (error) {
    console.error('Error listing backtests:', error);
    return [];
  }
}

/**
 * Delete a backtest
 */
export async function deleteBacktest(id: string): Promise<boolean> {
  try {
    const response = await apiClient.delete(`/proxy/llm/backtest/${id}`);
    return response.status === 200;
  } catch (error) {
    console.error('Error deleting backtest:', error);
    return false;
  }
}

// ============================================================================
// Health Check
// ============================================================================

/**
 * Check LLM Agent health
 */
export async function checkHealth(): Promise<{
  llmAgent: boolean;
  predictions: boolean;
  backtesting: boolean;
}> {
  const results = {
    llmAgent: false,
    predictions: false,
    backtesting: false,
  };

  try {
    const response = await apiClient.get('/proxy/llm/health');
    results.llmAgent = response.data?.status === 'healthy';
    results.predictions = results.llmAgent;
    results.backtesting = results.llmAgent;
  } catch (error) {
    console.error('Error checking LLM Agent health:', error);
  }

  return results;
}

// ============================================================================
// Polling utilities
// ============================================================================

/**
 * Poll for backtest completion
 */
export async function waitForBacktest(
  id: string,
  onProgress?: (progress: number) => void,
  pollInterval: number = 2000,
  timeout: number = 600000 // 10 minutes
): Promise<BacktestResult | null> {
  const startTime = Date.now();

  while (Date.now() - startTime < timeout) {
    const status = await getBacktestStatus(id);

    if (!status) {
      throw new Error('Backtest not found');
    }

    if (onProgress) {
      onProgress(status.progress);
    }

    if (status.status === 'completed') {
      return await getBacktestResults(id);
    }

    if (status.status === 'failed') {
      throw new Error(status.error || 'Backtest failed');
    }

    await new Promise(resolve => setTimeout(resolve, pollInterval));
  }

  throw new Error('Backtest timed out');
}
