/**
 * Trading Service
 * API client for trading and market data endpoints
 */

import { apiClient } from '../lib/apiClient';
import type {
  Candle,
  Ticker,
  OrderBook,
  TradingSymbol,
  Interval,
  SMAData,
  EMAData,
  RSIData,
  MACDData,
  BollingerBandsData,
  Watchlist,
  WatchlistSymbolData,
  PaperAccount,
  PaperBalance,
  PaperPosition,
  PaperOrder,
  PaperTrade,
  CreateOrderInput,
  AccountSummary,
} from '../types/trading.types';

// Uses centralized apiClient from lib/apiClient.ts (auto-refresh, multi-tab sync)
const api = apiClient;

// ============================================================================
// Market Data API
// ============================================================================

/**
 * Get candlestick data (OHLCV)
 */
export async function getKlines(
  symbol: string,
  interval: Interval = '1h',
  limit: number = 500
): Promise<Candle[]> {
  try {
    const response = await api.get(`/trading/market/klines/${symbol}`, {
      params: { interval, limit },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch klines:', error);
    throw new Error('Failed to fetch chart data');
  }
}

/**
 * Get current price for a symbol
 */
export async function getPrice(symbol: string): Promise<number> {
  try {
    const response = await api.get(`/trading/market/price/${symbol}`);
    return response.data.data.price || response.data.price;
  } catch (error) {
    console.error('Failed to fetch price:', error);
    throw new Error('Failed to fetch price');
  }
}

/**
 * Get 24h ticker data
 */
export async function getTicker(symbol: string): Promise<Ticker> {
  try {
    const response = await api.get(`/trading/market/ticker/${symbol}`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch ticker:', error);
    throw new Error('Failed to fetch ticker data');
  }
}

/**
 * Get all tickers
 */
export async function getAllTickers(): Promise<Ticker[]> {
  try {
    const response = await api.get('/trading/market/tickers');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch tickers:', error);
    throw new Error('Failed to fetch tickers');
  }
}

/**
 * Get order book
 */
export async function getOrderBook(symbol: string, limit: number = 20): Promise<OrderBook> {
  try {
    const response = await api.get(`/trading/market/orderbook/${symbol}`, {
      params: { limit },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch order book:', error);
    throw new Error('Failed to fetch order book');
  }
}

/**
 * Search for symbols
 */
export async function searchSymbols(query: string): Promise<TradingSymbol[]> {
  try {
    const response = await api.get('/trading/market/search', {
      params: { query },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to search symbols:', error);
    throw new Error('Failed to search symbols');
  }
}

/**
 * Get popular symbols
 */
export async function getPopularSymbols(): Promise<TradingSymbol[]> {
  try {
    const response = await api.get('/trading/market/popular');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch popular symbols:', error);
    throw new Error('Failed to fetch popular symbols');
  }
}

// ============================================================================
// Technical Indicators API
// ============================================================================

/**
 * Get Simple Moving Average (SMA)
 */
export async function getSMA(
  symbol: string,
  interval: Interval = '1h',
  period: number = 20
): Promise<SMAData[]> {
  try {
    const response = await api.get(`/trading/indicators/${symbol}/sma`, {
      params: { interval, period },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch SMA:', error);
    throw new Error('Failed to fetch SMA');
  }
}

/**
 * Get Exponential Moving Average (EMA)
 */
export async function getEMA(
  symbol: string,
  interval: Interval = '1h',
  period: number = 20
): Promise<EMAData[]> {
  try {
    const response = await api.get(`/trading/indicators/${symbol}/ema`, {
      params: { interval, period },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch EMA:', error);
    throw new Error('Failed to fetch EMA');
  }
}

/**
 * Get Relative Strength Index (RSI)
 */
export async function getRSI(
  symbol: string,
  interval: Interval = '1h',
  period: number = 14
): Promise<RSIData[]> {
  try {
    const response = await api.get(`/trading/indicators/${symbol}/rsi`, {
      params: { interval, period },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch RSI:', error);
    throw new Error('Failed to fetch RSI');
  }
}

/**
 * Get MACD
 */
export async function getMACD(
  symbol: string,
  interval: Interval = '1h',
  fastPeriod: number = 12,
  slowPeriod: number = 26,
  signalPeriod: number = 9
): Promise<MACDData[]> {
  try {
    const response = await api.get(`/trading/indicators/${symbol}/macd`, {
      params: { interval, fastPeriod, slowPeriod, signalPeriod },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch MACD:', error);
    throw new Error('Failed to fetch MACD');
  }
}

/**
 * Get Bollinger Bands
 */
export async function getBollingerBands(
  symbol: string,
  interval: Interval = '1h',
  period: number = 20,
  stdDev: number = 2
): Promise<BollingerBandsData[]> {
  try {
    const response = await api.get(`/trading/indicators/${symbol}/bollinger`, {
      params: { interval, period, stdDev },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch Bollinger Bands:', error);
    throw new Error('Failed to fetch Bollinger Bands');
  }
}

// ============================================================================
// Watchlist API
// ============================================================================

/**
 * Get all user watchlists
 */
export async function getWatchlists(): Promise<Watchlist[]> {
  try {
    const response = await api.get('/trading/watchlists');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch watchlists:', error);
    throw new Error('Failed to fetch watchlists');
  }
}

/**
 * Get default watchlist
 */
export async function getDefaultWatchlist(): Promise<Watchlist> {
  try {
    const response = await api.get('/trading/watchlists/default');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch default watchlist:', error);
    throw new Error('Failed to fetch default watchlist');
  }
}

/**
 * Get watchlist by ID
 */
export async function getWatchlist(id: string): Promise<Watchlist> {
  try {
    const response = await api.get(`/trading/watchlists/${id}`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch watchlist:', error);
    throw new Error('Failed to fetch watchlist');
  }
}

/**
 * Create new watchlist
 */
export async function createWatchlist(name: string): Promise<Watchlist> {
  try {
    const response = await api.post('/trading/watchlists', { name });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to create watchlist:', error);
    throw new Error('Failed to create watchlist');
  }
}

/**
 * Update watchlist
 */
export async function updateWatchlist(id: string, name: string): Promise<Watchlist> {
  try {
    const response = await api.patch(`/trading/watchlists/${id}`, { name });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to update watchlist:', error);
    throw new Error('Failed to update watchlist');
  }
}

/**
 * Delete watchlist
 */
export async function deleteWatchlist(id: string): Promise<void> {
  try {
    await api.delete(`/trading/watchlists/${id}`);
  } catch (error) {
    console.error('Failed to delete watchlist:', error);
    throw new Error('Failed to delete watchlist');
  }
}

/**
 * Add symbol to watchlist
 */
export async function addSymbolToWatchlist(watchlistId: string, symbol: string): Promise<void> {
  try {
    await api.post(`/trading/watchlists/${watchlistId}/symbols`, { symbol });
  } catch (error) {
    console.error('Failed to add symbol to watchlist:', error);
    throw new Error('Failed to add symbol to watchlist');
  }
}

/**
 * Remove symbol from watchlist
 */
export async function removeSymbolFromWatchlist(watchlistId: string, symbol: string): Promise<void> {
  try {
    await api.delete(`/trading/watchlists/${watchlistId}/symbols/${symbol}`);
  } catch (error) {
    console.error('Failed to remove symbol from watchlist:', error);
    throw new Error('Failed to remove symbol from watchlist');
  }
}

/**
 * Get watchlist data with prices
 */
export async function getWatchlistData(symbols: string[]): Promise<WatchlistSymbolData[]> {
  try {
    const symbolsParam = symbols.join(',');
    const response = await api.get('/trading/market/watchlist', {
      params: { symbols: symbolsParam },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch watchlist data:', error);
    throw new Error('Failed to fetch watchlist data');
  }
}

// ============================================================================
// Paper Trading API
// ============================================================================

/**
 * Initialize paper trading account
 */
export async function initializePaperAccount(
  initialBalance: number = 100000,
  name: string = 'Default Paper Account'
): Promise<PaperAccount> {
  try {
    const response = await api.post('/trading/paper/initialize', {
      initialBalance,
      name,
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to initialize paper account:', error);
    throw new Error('Failed to initialize paper account');
  }
}

/**
 * Get paper trading balances
 */
export async function getPaperBalances(): Promise<PaperBalance> {
  try {
    const response = await api.get('/trading/paper/balances');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper balances:', error);
    throw new Error('Failed to fetch paper balances');
  }
}

/**
 * Create paper trading order
 */
export async function createPaperOrder(orderData: CreateOrderInput): Promise<PaperOrder> {
  try {
    const response = await api.post('/trading/paper/orders', orderData);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to create paper order:', error);
    throw new Error('Failed to create paper order');
  }
}

/**
 * Cancel paper trading order
 */
export async function cancelPaperOrder(orderId: string): Promise<void> {
  try {
    await api.delete(`/trading/paper/orders/${orderId}`);
  } catch (error) {
    console.error('Failed to cancel paper order:', error);
    throw new Error('Failed to cancel paper order');
  }
}

/**
 * Get paper trading orders
 */
export async function getPaperOrders(status?: string): Promise<PaperOrder[]> {
  try {
    const response = await api.get('/trading/paper/orders', {
      params: status ? { status } : undefined,
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper orders:', error);
    throw new Error('Failed to fetch paper orders');
  }
}

/**
 * Get paper trading positions
 */
export async function getPaperPositions(status: string = 'open'): Promise<PaperPosition[]> {
  try {
    const response = await api.get('/trading/paper/positions', {
      params: { status },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper positions:', error);
    throw new Error('Failed to fetch paper positions');
  }
}

/**
 * Close paper trading position
 */
export async function closePaperPosition(positionId: string): Promise<PaperPosition> {
  try {
    const response = await api.post(`/trading/paper/positions/${positionId}/close`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to close paper position:', error);
    throw new Error('Failed to close paper position');
  }
}

/**
 * Get paper trading trades history
 */
export async function getPaperTrades(limit: number = 50): Promise<PaperTrade[]> {
  try {
    const response = await api.get('/trading/paper/trades', {
      params: { limit },
    });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper trades:', error);
    throw new Error('Failed to fetch paper trades');
  }
}

/**
 * Get paper trading portfolio summary
 */
export async function getPaperPortfolio(): Promise<AccountSummary> {
  try {
    const response = await api.get('/trading/paper/portfolio');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper portfolio:', error);
    throw new Error('Failed to fetch paper portfolio');
  }
}

/**
 * Reset paper trading account
 */
export async function resetPaperAccount(): Promise<PaperAccount> {
  try {
    const response = await api.post('/trading/paper/reset');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to reset paper account:', error);
    throw new Error('Failed to reset paper account');
  }
}

/**
 * Get paper trading statistics
 */
export async function getPaperStats(): Promise<AccountSummary> {
  try {
    const response = await api.get('/trading/paper/stats');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch paper stats:', error);
    throw new Error('Failed to fetch paper stats');
  }
}

// ============================================================================
// ML-Powered Trade Execution
// ============================================================================

export interface MLTradeRequest {
  symbol: string;
  direction: 'buy' | 'sell';
  source: 'ict' | 'ensemble' | 'manual';
  entry_price?: number;
  stop_loss?: number;
  take_profit?: number;
  risk_percent?: number;
  lot_size?: number;
  analysis_data?: Record<string, unknown>;
}

export interface MLTradeResult {
  success: boolean;
  trade_id?: string;
  order_id?: string;
  executed_price?: number;
  lot_size?: number;
  message: string;
  error?: string;
}

export interface MT4Account {
  account_id: string;
  broker: string;
  balance: number;
  equity: number;
  margin: number;
  free_margin: number;
  leverage: number;
  currency: string;
  connected: boolean;
}

export interface MT4Position {
  ticket: number;
  symbol: string;
  type: 'buy' | 'sell';
  volume: number;
  open_price: number;
  current_price: number;
  stop_loss: number;
  take_profit: number;
  profit: number;
  open_time: string;
  comment?: string;
}

const LLM_AGENT_URL = import.meta.env.VITE_LLM_AGENT_URL || 'http://localhost:3085';

/**
 * Execute a trade based on ML signal via LLM Agent
 */
export async function executeMLTrade(request: MLTradeRequest): Promise<MLTradeResult> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/trade/execute`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
      body: JSON.stringify(request),
    });

    if (!response.ok) {
      const error = await response.json();
      return {
        success: false,
        message: 'Trade execution failed',
        error: error.detail || error.message || 'Unknown error',
      };
    }

    return await response.json();
  } catch (error) {
    console.error('Failed to execute ML trade:', error);
    return {
      success: false,
      message: 'Trade execution failed',
      error: error instanceof Error ? error.message : 'Network error',
    };
  }
}

/**
 * Get MT4 account information
 */
export async function getMT4Account(): Promise<MT4Account | null> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/mt4/account`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
    });

    if (!response.ok) return null;
    return await response.json();
  } catch (error) {
    console.error('Failed to get MT4 account:', error);
    return null;
  }
}

/**
 * Get MT4 open positions
 */
export async function getMT4Positions(): Promise<MT4Position[]> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/mt4/positions`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
    });

    if (!response.ok) return [];
    const data = await response.json();
    return data.positions || [];
  } catch (error) {
    console.error('Failed to get MT4 positions:', error);
    return [];
  }
}

/**
 * Close MT4 position
 */
export async function closeMT4Position(ticket: number): Promise<MLTradeResult> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/mt4/positions/${ticket}/close`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
    });

    if (!response.ok) {
      const error = await response.json();
      return {
        success: false,
        message: 'Failed to close position',
        error: error.detail || error.message,
      };
    }

    return await response.json();
  } catch (error) {
    console.error('Failed to close MT4 position:', error);
    return {
      success: false,
      message: 'Failed to close position',
      error: error instanceof Error ? error.message : 'Network error',
    };
  }
}

/**
 * Modify MT4 position (SL/TP)
 */
export async function modifyMT4Position(
  ticket: number,
  stopLoss?: number,
  takeProfit?: number
): Promise<MLTradeResult> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/mt4/positions/${ticket}/modify`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
      body: JSON.stringify({ stop_loss: stopLoss, take_profit: takeProfit }),
    });

    if (!response.ok) {
      const error = await response.json();
      return {
        success: false,
        message: 'Failed to modify position',
        error: error.detail || error.message,
      };
    }

    return await response.json();
  } catch (error) {
    console.error('Failed to modify MT4 position:', error);
    return {
      success: false,
      message: 'Failed to modify position',
      error: error instanceof Error ? error.message : 'Network error',
    };
  }
}

/**
 * Calculate position size based on risk
 */
export async function calculatePositionSize(
  symbol: string,
  stopLossPips: number,
  riskPercent: number = 1
): Promise<{ lot_size: number; risk_amount: number } | null> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/api/mt4/calculate-size`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${localStorage.getItem('token')}`,
      },
      body: JSON.stringify({
        symbol,
        stop_loss_pips: stopLossPips,
        risk_percent: riskPercent,
      }),
    });

    if (!response.ok) return null;
    return await response.json();
  } catch (error) {
    console.error('Failed to calculate position size:', error);
    return null;
  }
}

/**
 * Get LLM Agent health status
 */
export async function getLLMAgentHealth(): Promise<boolean> {
  try {
    const response = await fetch(`${LLM_AGENT_URL}/health`);
    return response.ok;
  } catch {
    return false;
  }
}

// ============================================================================
// Price Alerts API
// ============================================================================

export type AlertCondition = 'above' | 'below' | 'crosses_above' | 'crosses_below';

export interface PriceAlert {
  id: string;
  userId: string;
  symbol: string;
  condition: AlertCondition;
  price: number;
  note?: string;
  isActive: boolean;
  triggeredAt?: string;
  triggeredPrice?: number;
  notifyEmail: boolean;
  notifyPush: boolean;
  isRecurring: boolean;
  createdAt: string;
}

export interface CreateAlertInput {
  symbol: string;
  condition: AlertCondition;
  price: number;
  note?: string;
  notifyEmail?: boolean;
  notifyPush?: boolean;
  isRecurring?: boolean;
}

export interface UpdateAlertInput {
  price?: number;
  note?: string;
  notifyEmail?: boolean;
  notifyPush?: boolean;
  isRecurring?: boolean;
  isActive?: boolean;
}

export interface AlertsFilter {
  isActive?: boolean;
  symbol?: string;
  condition?: AlertCondition;
}

export interface AlertStats {
  total: number;
  active: number;
  triggered: number;
}

/**
 * Get user's price alerts
 */
export async function getAlerts(filter: AlertsFilter = {}): Promise<PriceAlert[]> {
  try {
    const params: Record<string, string> = {};
    if (filter.isActive !== undefined) params.isActive = String(filter.isActive);
    if (filter.symbol) params.symbol = filter.symbol;
    if (filter.condition) params.condition = filter.condition;

    const response = await api.get('/trading/alerts', { params });
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch alerts:', error);
    throw new Error('Failed to fetch alerts');
  }
}

/**
 * Get alert by ID
 */
export async function getAlertById(alertId: string): Promise<PriceAlert> {
  try {
    const response = await api.get(`/trading/alerts/${alertId}`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch alert:', error);
    throw new Error('Failed to fetch alert');
  }
}

/**
 * Create a new price alert
 */
export async function createAlert(input: CreateAlertInput): Promise<PriceAlert> {
  try {
    const response = await api.post('/trading/alerts', input);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to create alert:', error);
    throw new Error('Failed to create alert');
  }
}

/**
 * Update an alert
 */
export async function updateAlert(alertId: string, updates: UpdateAlertInput): Promise<PriceAlert> {
  try {
    const response = await api.patch(`/trading/alerts/${alertId}`, updates);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to update alert:', error);
    throw new Error('Failed to update alert');
  }
}

/**
 * Delete an alert
 */
export async function deleteAlert(alertId: string): Promise<void> {
  try {
    await api.delete(`/trading/alerts/${alertId}`);
  } catch (error) {
    console.error('Failed to delete alert:', error);
    throw new Error('Failed to delete alert');
  }
}

/**
 * Enable an alert
 */
export async function enableAlert(alertId: string): Promise<PriceAlert> {
  try {
    const response = await api.post(`/trading/alerts/${alertId}/enable`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to enable alert:', error);
    throw new Error('Failed to enable alert');
  }
}

/**
 * Disable an alert
 */
export async function disableAlert(alertId: string): Promise<PriceAlert> {
  try {
    const response = await api.post(`/trading/alerts/${alertId}/disable`);
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to disable alert:', error);
    throw new Error('Failed to disable alert');
  }
}

/**
 * Get alert statistics
 */
export async function getAlertStats(): Promise<AlertStats> {
  try {
    const response = await api.get('/trading/alerts/stats');
    return response.data.data || response.data;
  } catch (error) {
    console.error('Failed to fetch alert stats:', error);
    throw new Error('Failed to fetch alert stats');
  }
}

// ============================================================================
// Export
// ============================================================================

export const tradingService = {
  // Market data
  getKlines,
  getPrice,
  getTicker,
  getAllTickers,
  getOrderBook,
  searchSymbols,
  getPopularSymbols,

  // Indicators
  getSMA,
  getEMA,
  getRSI,
  getMACD,
  getBollingerBands,

  // Watchlist
  getWatchlists,
  getDefaultWatchlist,
  getWatchlist,
  createWatchlist,
  updateWatchlist,
  deleteWatchlist,
  addSymbolToWatchlist,
  removeSymbolFromWatchlist,
  getWatchlistData,

  // Paper Trading
  initializePaperAccount,
  getPaperBalances,
  createPaperOrder,
  cancelPaperOrder,
  getPaperOrders,
  getPaperPositions,
  closePaperPosition,
  getPaperTrades,
  getPaperPortfolio,
  resetPaperAccount,
  getPaperStats,

  // ML-Powered Trading & MT4
  executeMLTrade,
  getMT4Account,
  getMT4Positions,
  closeMT4Position,
  modifyMT4Position,
  calculatePositionSize,
  getLLMAgentHealth,

  // Price Alerts
  getAlerts,
  getAlertById,
  createAlert,
  updateAlert,
  deleteAlert,
  enableAlert,
  disableAlert,
  getAlertStats,
};

export default tradingService;
