/**
 * ML Client
 *
 * Maneja interacción con ML Engine y LLM Agent
 */

import { AxiosInstance } from 'axios';
import {
  ApiResponse,
  Signal,
  SignalDirection,
  Prediction,
} from '../types';
import { Trading PlatformConfig } from '../client';

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

export interface SignalFilter {
  symbol?: string;
  direction?: SignalDirection;
  minConfidence?: number;
  active?: boolean;
  page?: number;
  limit?: number;
}

export interface BacktestRequest {
  symbol: string;
  timeframe: string;
  startDate: string;
  endDate: string;
  strategy: string;
  parameters?: Record<string, unknown>;
}

export interface BacktestResult {
  id: string;
  symbol: string;
  timeframe: string;
  strategy: string;
  startDate: string;
  endDate: string;
  metrics: {
    totalReturn: number;
    sharpeRatio: number;
    maxDrawdown: number;
    winRate: number;
    profitFactor: number;
    totalTrades: number;
    avgWin: number;
    avgLoss: number;
  };
  trades: Array<{
    entryDate: string;
    exitDate: string;
    side: SignalDirection;
    entryPrice: number;
    exitPrice: number;
    pnl: number;
    pnlPercent: number;
  }>;
  equity: Array<{ date: string; value: number }>;
}

export interface ChatMessage {
  role: 'user' | 'assistant' | 'system';
  content: string;
  timestamp?: string;
}

export interface ChatRequest {
  message: string;
  conversationId?: string;
  context?: {
    symbol?: string;
    timeframe?: string;
    includeSignals?: boolean;
    includePositions?: boolean;
  };
}

export interface ChatResponse {
  conversationId: string;
  message: ChatMessage;
  suggestions?: string[];
  actions?: Array<{
    type: string;
    label: string;
    payload: unknown;
  }>;
}

export class MLClient {
  private http: AxiosInstance;
  private config: Trading PlatformConfig;

  constructor(http: AxiosInstance, config: Trading PlatformConfig) {
    this.http = http;
    this.config = config;
  }

  // ============================================================================
  // Predictions
  // ============================================================================

  /**
   * Get price prediction
   */
  async getPrediction(params: PredictionRequest): Promise<Prediction> {
    const response = await this.http.post<ApiResponse<Prediction>>(
      '/ml/predict',
      params
    );
    return response.data.data;
  }

  /**
   * Get multiple predictions
   */
  async getBatchPredictions(
    symbols: string[],
    timeframe: string
  ): Promise<Prediction[]> {
    const response = await this.http.post<ApiResponse<Prediction[]>>(
      '/ml/predict/batch',
      { symbols, timeframe }
    );
    return response.data.data;
  }

  // ============================================================================
  // Signals
  // ============================================================================

  /**
   * Get active signals
   */
  async getSignals(filter?: SignalFilter): Promise<Signal[]> {
    const response = await this.http.get<ApiResponse<Signal[]>>('/ml/signals', {
      params: filter,
    });
    return response.data.data;
  }

  /**
   * Get signal by ID
   */
  async getSignal(signalId: string): Promise<Signal> {
    const response = await this.http.get<ApiResponse<Signal>>(
      `/ml/signals/${signalId}`
    );
    return response.data.data;
  }

  /**
   * Subscribe to signals for a symbol
   */
  async subscribeToSignals(symbol: string): Promise<{ subscribed: boolean }> {
    const response = await this.http.post<ApiResponse<{ subscribed: boolean }>>(
      '/ml/signals/subscribe',
      { symbol }
    );
    return response.data.data;
  }

  /**
   * Unsubscribe from signals
   */
  async unsubscribeFromSignals(symbol: string): Promise<void> {
    await this.http.post('/ml/signals/unsubscribe', { symbol });
  }

  /**
   * Get signal history
   */
  async getSignalHistory(filter?: {
    symbol?: string;
    startDate?: string;
    endDate?: string;
    page?: number;
    limit?: number;
  }): Promise<Signal[]> {
    const response = await this.http.get<ApiResponse<Signal[]>>(
      '/ml/signals/history',
      { params: filter }
    );
    return response.data.data;
  }

  /**
   * Get signal performance
   */
  async getSignalPerformance(filter?: {
    symbol?: string;
    timeframe?: string;
    startDate?: string;
    endDate?: string;
  }): Promise<{
    totalSignals: number;
    accuracy: number;
    avgReturn: number;
    bestSignal: Signal;
    worstSignal: Signal;
  }> {
    const response = await this.http.get<ApiResponse<any>>(
      '/ml/signals/performance',
      { params: filter }
    );
    return response.data.data;
  }

  // ============================================================================
  // Backtesting
  // ============================================================================

  /**
   * Run a backtest
   */
  async runBacktest(params: BacktestRequest): Promise<BacktestResult> {
    const response = await this.http.post<ApiResponse<BacktestResult>>(
      '/ml/backtest',
      params
    );
    return response.data.data;
  }

  /**
   * Get backtest results
   */
  async getBacktestResults(): Promise<BacktestResult[]> {
    const response = await this.http.get<ApiResponse<BacktestResult[]>>(
      '/ml/backtest/results'
    );
    return response.data.data;
  }

  /**
   * Get backtest by ID
   */
  async getBacktest(backtestId: string): Promise<BacktestResult> {
    const response = await this.http.get<ApiResponse<BacktestResult>>(
      `/ml/backtest/${backtestId}`
    );
    return response.data.data;
  }

  /**
   * Get available strategies for backtesting
   */
  async getStrategies(): Promise<Array<{
    id: string;
    name: string;
    description: string;
    parameters: Array<{
      name: string;
      type: string;
      default: unknown;
      description: string;
    }>;
  }>> {
    const response = await this.http.get<ApiResponse<any[]>>('/ml/strategies');
    return response.data.data;
  }

  // ============================================================================
  // Analysis
  // ============================================================================

  /**
   * Get market analysis for a symbol
   */
  async getAnalysis(
    symbol: string,
    timeframe?: string
  ): Promise<{
    symbol: string;
    timeframe: string;
    trend: 'bullish' | 'bearish' | 'neutral';
    strength: number;
    support: number[];
    resistance: number[];
    indicators: Record<string, number>;
    summary: string;
  }> {
    const response = await this.http.get<ApiResponse<any>>(
      `/ml/analysis/${symbol}`,
      { params: { timeframe } }
    );
    return response.data.data;
  }

  /**
   * Detect AMD phases (Accumulation/Manipulation/Distribution)
   */
  async detectAMD(
    symbol: string,
    timeframe: string
  ): Promise<{
    currentPhase: 'accumulation' | 'manipulation' | 'distribution' | 'unknown';
    confidence: number;
    phaseStart: string;
    expectedTransition: string;
    recommendation: string;
  }> {
    const response = await this.http.post<ApiResponse<any>>('/ml/analysis/amd', {
      symbol,
      timeframe,
    });
    return response.data.data;
  }

  // ============================================================================
  // Chat (LLM Agent)
  // ============================================================================

  /**
   * Send message to AI copilot
   */
  async chat(request: ChatRequest): Promise<ChatResponse> {
    const response = await this.http.post<ApiResponse<ChatResponse>>(
      '/llm/chat',
      request
    );
    return response.data.data;
  }

  /**
   * Get chat history
   */
  async getChatHistory(conversationId: string): Promise<ChatMessage[]> {
    const response = await this.http.get<ApiResponse<ChatMessage[]>>(
      `/llm/chat/${conversationId}/history`
    );
    return response.data.data;
  }

  /**
   * Get all conversations
   */
  async getConversations(): Promise<Array<{
    id: string;
    title: string;
    lastMessage: string;
    updatedAt: string;
  }>> {
    const response = await this.http.get<ApiResponse<any[]>>('/llm/conversations');
    return response.data.data;
  }

  /**
   * Delete a conversation
   */
  async deleteConversation(conversationId: string): Promise<void> {
    await this.http.delete(`/llm/conversations/${conversationId}`);
  }

  /**
   * Ask a specific question (one-shot, no conversation context)
   */
  async ask(question: string, context?: Record<string, unknown>): Promise<string> {
    const response = await this.http.post<ApiResponse<{ answer: string }>>(
      '/llm/ask',
      { question, context }
    );
    return response.data.data.answer;
  }

  /**
   * Get explanation for a trading concept
   */
  async explain(concept: string): Promise<{
    concept: string;
    explanation: string;
    examples?: string[];
    relatedConcepts?: string[];
  }> {
    const response = await this.http.post<ApiResponse<any>>('/llm/explain', {
      concept,
    });
    return response.data.data;
  }

  // ============================================================================
  // Models
  // ============================================================================

  /**
   * Get available ML models
   */
  async getModels(): Promise<Array<{
    id: string;
    name: string;
    type: string;
    version: string;
    accuracy: number;
    lastTrainedAt: string;
    status: 'active' | 'training' | 'inactive';
  }>> {
    const response = await this.http.get<ApiResponse<any[]>>('/ml/models');
    return response.data.data;
  }

  /**
   * Get model details
   */
  async getModel(modelId: string): Promise<{
    id: string;
    name: string;
    type: string;
    version: string;
    metrics: Record<string, number>;
    config: Record<string, unknown>;
    lastTrainedAt: string;
  }> {
    const response = await this.http.get<ApiResponse<any>>(`/ml/models/${modelId}`);
    return response.data.data;
  }
}
