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

import axios from 'axios';
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';

// ============================================================================
// API Configuration
// ============================================================================

const API_BASE_URL = import.meta.env?.VITE_API_URL || '/api/v1';

const api = axios.create({
  baseURL: API_BASE_URL,
  headers: {
    'Content-Type': 'application/json',
  },
});

// Add request interceptor for auth token
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Add response interceptor for error handling
api.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error.response?.status === 401) {
      // Token expired or invalid
      localStorage.removeItem('token');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

// ============================================================================
// 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');
  }
}

// ============================================================================
// 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,
};

export default tradingService;
