/**
 * Trading Client
 *
 * Maneja operaciones de trading: órdenes, posiciones, watchlists
 */

import { AxiosInstance } from 'axios';
import {
  ApiResponse,
  PaginatedResponse,
  Order,
  OrderType,
  OrderSide,
  Position,
  Trade,
  Symbol,
  TradingAgent,
  AgentProfile,
} from '../types';
import { Trading PlatformConfig } from '../client';

export interface CreateOrderParams {
  symbol: string;
  type: OrderType;
  side: OrderSide;
  quantity: number;
  price?: number;
  stopPrice?: number;
  takeProfit?: number;
  stopLoss?: number;
  timeInForce?: 'GTC' | 'IOC' | 'FOK';
}

export interface OrdersFilter {
  symbol?: string;
  status?: string;
  side?: OrderSide;
  startDate?: string;
  endDate?: string;
  page?: number;
  limit?: number;
}

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

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

  // ============================================================================
  // Symbols
  // ============================================================================

  /**
   * Get all available symbols
   */
  async getSymbols(filter?: { type?: string; exchange?: string }): Promise<Symbol[]> {
    const response = await this.http.get<ApiResponse<Symbol[]>>('/trading/symbols', {
      params: filter,
    });
    return response.data.data;
  }

  /**
   * Get symbol details
   */
  async getSymbol(symbolId: string): Promise<Symbol> {
    const response = await this.http.get<ApiResponse<Symbol>>(
      `/trading/symbols/${symbolId}`
    );
    return response.data.data;
  }

  // ============================================================================
  // Orders
  // ============================================================================

  /**
   * Create a new order
   */
  async createOrder(params: CreateOrderParams): Promise<Order> {
    const response = await this.http.post<ApiResponse<Order>>(
      '/trading/orders',
      params
    );
    return response.data.data;
  }

  /**
   * Get orders with filters
   */
  async getOrders(filter?: OrdersFilter): Promise<PaginatedResponse<Order>> {
    const response = await this.http.get<PaginatedResponse<Order>>(
      '/trading/orders',
      { params: filter }
    );
    return response.data;
  }

  /**
   * Get order by ID
   */
  async getOrder(orderId: string): Promise<Order> {
    const response = await this.http.get<ApiResponse<Order>>(
      `/trading/orders/${orderId}`
    );
    return response.data.data;
  }

  /**
   * Cancel an order
   */
  async cancelOrder(orderId: string): Promise<Order> {
    const response = await this.http.delete<ApiResponse<Order>>(
      `/trading/orders/${orderId}`
    );
    return response.data.data;
  }

  /**
   * Cancel all open orders
   */
  async cancelAllOrders(symbol?: string): Promise<{ cancelled: number }> {
    const response = await this.http.delete<ApiResponse<{ cancelled: number }>>(
      '/trading/orders',
      { params: { symbol } }
    );
    return response.data.data;
  }

  /**
   * Modify an order
   */
  async modifyOrder(
    orderId: string,
    params: Partial<Pick<CreateOrderParams, 'price' | 'stopPrice' | 'quantity'>>
  ): Promise<Order> {
    const response = await this.http.patch<ApiResponse<Order>>(
      `/trading/orders/${orderId}`,
      params
    );
    return response.data.data;
  }

  // ============================================================================
  // Positions
  // ============================================================================

  /**
   * Get all open positions
   */
  async getPositions(): Promise<Position[]> {
    const response = await this.http.get<ApiResponse<Position[]>>(
      '/trading/positions'
    );
    return response.data.data;
  }

  /**
   * Get position by ID
   */
  async getPosition(positionId: string): Promise<Position> {
    const response = await this.http.get<ApiResponse<Position>>(
      `/trading/positions/${positionId}`
    );
    return response.data.data;
  }

  /**
   * Close a position
   */
  async closePosition(positionId: string, quantity?: number): Promise<Position> {
    const response = await this.http.post<ApiResponse<Position>>(
      `/trading/positions/${positionId}/close`,
      { quantity }
    );
    return response.data.data;
  }

  /**
   * Modify position (SL/TP)
   */
  async modifyPosition(
    positionId: string,
    params: { stopLoss?: number; takeProfit?: number }
  ): Promise<Position> {
    const response = await this.http.patch<ApiResponse<Position>>(
      `/trading/positions/${positionId}`,
      params
    );
    return response.data.data;
  }

  /**
   * Close all positions
   */
  async closeAllPositions(): Promise<{ closed: number }> {
    const response = await this.http.post<ApiResponse<{ closed: number }>>(
      '/trading/positions/close-all'
    );
    return response.data.data;
  }

  // ============================================================================
  // Trade History
  // ============================================================================

  /**
   * Get trade history
   */
  async getTrades(filter?: {
    symbol?: string;
    startDate?: string;
    endDate?: string;
    page?: number;
    limit?: number;
  }): Promise<PaginatedResponse<Trade>> {
    const response = await this.http.get<PaginatedResponse<Trade>>(
      '/trading/trades',
      { params: filter }
    );
    return response.data;
  }

  // ============================================================================
  // Watchlists
  // ============================================================================

  /**
   * Get user's watchlists
   */
  async getWatchlists(): Promise<Array<{ id: string; name: string; symbols: string[] }>> {
    const response = await this.http.get<ApiResponse<any[]>>('/trading/watchlists');
    return response.data.data;
  }

  /**
   * Create watchlist
   */
  async createWatchlist(name: string, symbols?: string[]): Promise<{ id: string; name: string }> {
    const response = await this.http.post<ApiResponse<any>>('/trading/watchlists', {
      name,
      symbols,
    });
    return response.data.data;
  }

  /**
   * Add symbol to watchlist
   */
  async addToWatchlist(watchlistId: string, symbol: string): Promise<void> {
    await this.http.post(`/trading/watchlists/${watchlistId}/symbols`, { symbol });
  }

  /**
   * Remove symbol from watchlist
   */
  async removeFromWatchlist(watchlistId: string, symbol: string): Promise<void> {
    await this.http.delete(`/trading/watchlists/${watchlistId}/symbols/${symbol}`);
  }

  /**
   * Delete watchlist
   */
  async deleteWatchlist(watchlistId: string): Promise<void> {
    await this.http.delete(`/trading/watchlists/${watchlistId}`);
  }

  // ============================================================================
  // Trading Agents
  // ============================================================================

  /**
   * Get user's trading agents
   */
  async getAgents(): Promise<TradingAgent[]> {
    const response = await this.http.get<ApiResponse<TradingAgent[]>>(
      '/trading/agents'
    );
    return response.data.data;
  }

  /**
   * Get agent by ID
   */
  async getAgent(agentId: string): Promise<TradingAgent> {
    const response = await this.http.get<ApiResponse<TradingAgent>>(
      `/trading/agents/${agentId}`
    );
    return response.data.data;
  }

  /**
   * Create a new trading agent
   */
  async createAgent(params: {
    name: string;
    profile: AgentProfile;
    initialBalance: number;
  }): Promise<TradingAgent> {
    const response = await this.http.post<ApiResponse<TradingAgent>>(
      '/trading/agents',
      params
    );
    return response.data.data;
  }

  /**
   * Start an agent
   */
  async startAgent(agentId: string): Promise<TradingAgent> {
    const response = await this.http.post<ApiResponse<TradingAgent>>(
      `/trading/agents/${agentId}/start`
    );
    return response.data.data;
  }

  /**
   * Stop an agent
   */
  async stopAgent(agentId: string): Promise<TradingAgent> {
    const response = await this.http.post<ApiResponse<TradingAgent>>(
      `/trading/agents/${agentId}/stop`
    );
    return response.data.data;
  }

  /**
   * Get agent performance stats
   */
  async getAgentStats(agentId: string): Promise<{
    totalPnl: number;
    winRate: number;
    maxDrawdown: number;
    sharpeRatio: number;
    tradesCount: number;
    avgWin: number;
    avgLoss: number;
  }> {
    const response = await this.http.get<ApiResponse<any>>(
      `/trading/agents/${agentId}/stats`
    );
    return response.data.data;
  }

  /**
   * Get agent trade history
   */
  async getAgentTrades(
    agentId: string,
    filter?: { page?: number; limit?: number }
  ): Promise<PaginatedResponse<Trade>> {
    const response = await this.http.get<PaginatedResponse<Trade>>(
      `/trading/agents/${agentId}/trades`,
      { params: filter }
    );
    return response.data;
  }

  // ============================================================================
  // Account
  // ============================================================================

  /**
   * Get account balance and summary
   */
  async getAccountSummary(): Promise<{
    balance: number;
    equity: number;
    margin: number;
    freeMargin: number;
    marginLevel: number;
    unrealizedPnl: number;
    realizedPnl: number;
  }> {
    const response = await this.http.get<ApiResponse<any>>('/trading/account');
    return response.data.data;
  }
}
