/**
 * Trading Service Interfaces
 * Abstraction for trading and market data operations following DIP
 */

import type { EventEmitter } from 'events';

/**
 * Intervals for candlestick data
 */
export type Interval =
  | '1m'
  | '3m'
  | '5m'
  | '15m'
  | '30m'
  | '1h'
  | '2h'
  | '4h'
  | '6h'
  | '8h'
  | '12h'
  | '1d'
  | '3d'
  | '1w'
  | '1M';

/**
 * Candlestick/Kline data structure
 */
export interface Kline {
  openTime: number;
  open: string;
  high: string;
  low: string;
  close: string;
  volume: string;
  closeTime: number;
  quoteVolume: string;
  trades: number;
  takerBuyBaseVolume: string;
  takerBuyQuoteVolume: string;
}

/**
 * 24h ticker data
 */
export interface Ticker24h {
  symbol: string;
  priceChange: string;
  priceChangePercent: string;
  weightedAvgPrice: string;
  prevClosePrice: string;
  lastPrice: string;
  lastQty: string;
  bidPrice: string;
  bidQty: string;
  askPrice: string;
  askQty: string;
  openPrice: string;
  highPrice: string;
  lowPrice: string;
  volume: string;
  quoteVolume: string;
  openTime: number;
  closeTime: number;
  firstId: number;
  lastId: number;
  count: number;
}

/**
 * Order book entry
 */
export interface OrderBookEntry {
  price: string;
  quantity: string;
}

/**
 * Order book data
 */
export interface OrderBook {
  lastUpdateId: number;
  bids: OrderBookEntry[];
  asks: OrderBookEntry[];
}

/**
 * Symbol information
 */
export interface SymbolInfo {
  symbol: string;
  status: string;
  baseAsset: string;
  baseAssetPrecision: number;
  quoteAsset: string;
  quotePrecision: number;
  quoteAssetPrecision: number;
  filters: SymbolFilter[];
}

/**
 * Symbol filter
 */
export interface SymbolFilter {
  filterType: string;
  minPrice?: string;
  maxPrice?: string;
  tickSize?: string;
  minQty?: string;
  maxQty?: string;
  stepSize?: string;
  minNotional?: string;
}

/**
 * Exchange information
 */
export interface ExchangeInfo {
  timezone: string;
  serverTime: number;
  symbols: SymbolInfo[];
}

/**
 * Market price data
 */
export interface MarketPrice {
  symbol: string;
  price: number;
  timestamp: number;
}

/**
 * Market ticker data
 */
export interface MarketTicker {
  symbol: string;
  lastPrice: number;
  priceChange: number;
  priceChangePercent: number;
  high24h: number;
  low24h: number;
  volume24h: number;
  quoteVolume24h: number;
}

/**
 * Candlestick data (transformed)
 */
export interface CandlestickData {
  time: number;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
}

/**
 * Market symbol details
 */
export interface MarketSymbol {
  symbol: string;
  baseAsset: string;
  quoteAsset: string;
  status: string;
  pricePrecision: number;
  quantityPrecision: number;
  minPrice: string;
  maxPrice: string;
  tickSize: string;
  minQty: string;
  maxQty: string;
  stepSize: string;
  minNotional: string;
}

/**
 * Watchlist item
 */
export interface WatchlistItem {
  symbol: string;
  price: number;
  change24h: number;
  changePercent24h: number;
  volume24h: number;
  high24h: number;
  low24h: number;
}

/**
 * Binance Service Interface (Exchange API Client)
 */
export interface IBinanceService {
  /**
   * Get server time
   */
  getServerTime(): Promise<number>;

  /**
   * Get exchange information
   */
  getExchangeInfo(symbols?: string[]): Promise<ExchangeInfo>;

  /**
   * Get klines/candlestick data
   */
  getKlines(
    symbol: string,
    interval: Interval,
    options?: {
      startTime?: number;
      endTime?: number;
      limit?: number;
    }
  ): Promise<Kline[]>;

  /**
   * Get 24h ticker
   */
  get24hrTicker(symbol?: string): Promise<Ticker24h | Ticker24h[]>;

  /**
   * Get current price
   */
  getPrice(symbol?: string): Promise<{ symbol: string; price: string } | { symbol: string; price: string }[]>;

  /**
   * Get order book
   */
  getOrderBook(symbol: string, limit?: number): Promise<OrderBook>;

  /**
   * Get recent trades
   */
  getRecentTrades(
    symbol: string,
    limit?: number
  ): Promise<
    {
      id: number;
      price: string;
      qty: string;
      quoteQty: string;
      time: number;
      isBuyerMaker: boolean;
    }[]
  >;

  /**
   * Subscribe to kline stream
   */
  subscribeKlines(symbol: string, interval: Interval): void;

  /**
   * Subscribe to ticker stream
   */
  subscribeTicker(symbol: string): void;

  /**
   * Subscribe to all mini tickers
   */
  subscribeAllMiniTickers(): void;

  /**
   * Subscribe to trade stream
   */
  subscribeTrades(symbol: string): void;

  /**
   * Subscribe to order book depth stream
   */
  subscribeDepth(symbol: string, levels?: 5 | 10 | 20): void;

  /**
   * Unsubscribe from stream
   */
  unsubscribe(streamName: string): void;

  /**
   * Unsubscribe from all streams
   */
  unsubscribeAll(): void;

  /**
   * Get remaining API requests
   */
  getRemainingRequests(): number;

  /**
   * Get active WebSocket streams
   */
  getActiveStreams(): string[];

  /**
   * Check if stream is active
   */
  isStreamActive(streamName: string): boolean;

  /**
   * Event emitter methods (inherited from EventEmitter)
   */
  on(event: string, listener: (...args: unknown[]) => void): EventEmitter;
  emit(event: string, ...args: unknown[]): boolean;
}

/**
 * Market Service Interface (Market Data Facade)
 */
export interface IMarketService {
  /**
   * Initialize the service
   */
  initialize(): Promise<void>;

  /**
   * Load exchange information
   */
  loadExchangeInfo(): Promise<void>;

  /**
   * Get candlestick/kline data
   */
  getKlines(
    symbol: string,
    interval: Interval,
    options?: { startTime?: number; endTime?: number; limit?: number }
  ): Promise<CandlestickData[]>;

  /**
   * Get current price for a symbol
   */
  getPrice(symbol: string): Promise<MarketPrice>;

  /**
   * Get prices for multiple symbols
   */
  getPrices(symbols?: string[]): Promise<MarketPrice[]>;

  /**
   * Get 24h ticker for a symbol
   */
  getTicker(symbol: string): Promise<MarketTicker>;

  /**
   * Get 24h tickers for multiple symbols
   */
  getTickers(symbols?: string[]): Promise<MarketTicker[]>;

  /**
   * Get order book for a symbol
   */
  getOrderBook(symbol: string, limit?: number): Promise<OrderBook>;

  /**
   * Get watchlist data
   */
  getWatchlist(symbols: string[]): Promise<WatchlistItem[]>;

  /**
   * Get symbol information
   */
  getSymbolInfo(symbol: string): MarketSymbol | undefined;

  /**
   * Get all available symbols
   */
  getAvailableSymbols(): string[];

  /**
   * Search symbols by query
   */
  searchSymbols(query: string, limit?: number): MarketSymbol[];

  /**
   * Get popular symbols
   */
  getPopularSymbols(): string[];

  /**
   * Subscribe to real-time kline updates
   */
  subscribeKlines(symbol: string, interval: Interval): void;

  /**
   * Subscribe to real-time ticker updates
   */
  subscribeTicker(symbol: string): void;

  /**
   * Subscribe to real-time trade updates
   */
  subscribeTrades(symbol: string): void;

  /**
   * Subscribe to order book depth updates
   */
  subscribeDepth(symbol: string, levels?: 5 | 10 | 20): void;

  /**
   * Unsubscribe from a stream
   */
  unsubscribe(streamName: string): void;

  /**
   * Unsubscribe from all streams
   */
  unsubscribeAll(): void;

  /**
   * Get active WebSocket streams
   */
  getActiveStreams(): string[];

  /**
   * Register kline event handler
   */
  onKline(
    handler: (data: { symbol: string; interval: string; kline: CandlestickData; isFinal: boolean }) => void
  ): void;

  /**
   * Register ticker event handler
   */
  onTicker(handler: (data: MarketTicker) => void): void;

  /**
   * Register trade event handler
   */
  onTrade(
    handler: (data: {
      symbol: string;
      tradeId: number;
      price: number;
      quantity: number;
      time: number;
      isBuyerMaker: boolean;
    }) => void
  ): void;
}
