import { EventEmitter } from 'events'
import { TradingService, ServiceStatus } from '../types.js'
import { logger } from '../../utils/logger.js'
import { PacificaWebSocketOrderbookService, PacificaWebSocketOrderbookConfig } from './PacificaWebSocketOrderbookService.js'

interface OrderbookEntry {
  price: number
  size: number
}

interface CachedOrderbook {
  symbol: string
  bids: OrderbookEntry[]
  asks: OrderbookEntry[]
  timestamp: number
  isValid: boolean
  lastRefresh: number
}

interface OrderbookStats {
  symbol: string
  spread: number
  spreadPercent: number
  midPrice: number
  bestBid: number
  bestAsk: number
  totalBidSize: number
  totalAskSize: number
  depthLevels: number
  updateFrequency: number
  lastUpdate: number
}

export interface PacificaOrderbookManagerConfig {
  wsUrl?: string
  symbols?: string[]
  aggLevel?: number
  cacheExpiryMs?: number
  minDepthLevels?: number
  statsWindowMs?: number
  autoRefreshInterval?: number
}

/**
 * Pacifica订单簿管理器
 * 集成到SystemOrchestrator的TradingService接口
 * 提供实时Pacifica订单簿数据和缓存管理
 */
export class PacificaOrderbookManager extends EventEmitter implements TradingService {
  private wsService: PacificaWebSocketOrderbookService
  private cache: Map<string, CachedOrderbook> = new Map()
  private stats: Map<string, OrderbookStats> = new Map()
  private updateCounts: Map<string, number[]> = new Map()
  private config: Required<PacificaOrderbookManagerConfig>
  private refreshTimer: NodeJS.Timeout | null = null
  private isInitialized = false
  private status: 'stopped' | 'initializing' | 'initialized' | 'starting' | 'running' | 'stopping' | 'error' = 'stopped'
  private lastStatusChange = Date.now()

  constructor(config: PacificaOrderbookManagerConfig = {}) {
    super()

    this.config = {
      wsUrl: config.wsUrl || process.env.PACIFICA_WS_URL || 'wss://ws.pacifica.fi/ws',
      symbols: config.symbols || ['BTC', 'SOL', 'ETH'],
      aggLevel: config.aggLevel || 1,
      cacheExpiryMs: config.cacheExpiryMs || 60000,
      minDepthLevels: config.minDepthLevels || 5,
      statsWindowMs: config.statsWindowMs || 60000,
      autoRefreshInterval: config.autoRefreshInterval || 5000
    }

    // 创建WebSocket服务
    this.wsService = new PacificaWebSocketOrderbookService({
      wsUrl: this.config.wsUrl,
      symbols: this.config.symbols,
      aggLevel: this.config.aggLevel,
      reconnectInterval: 5000,
      maxReconnectAttempts: 10,
      heartbeatInterval: 30000
    })

    // 监听orderbook更新
    this.wsService.on('orderbook', (orderbook) => {
      this.updateCache(orderbook)
    })

    this.wsService.on('error', (error) => {
      logger.error('Pacifica WebSocket orderbook服务错误:', error)
      this.updateStatus('error')
      this.emit('error', error)
    })

    this.updateStatus('stopped')

    logger.info('🌊 PacificaOrderbookManager 已创建', {
      wsUrl: this.config.wsUrl,
      symbols: this.config.symbols,
      aggLevel: this.config.aggLevel
    })
  }

  /**
   * TradingService接口: 初始化服务
   */
  async initialize(): Promise<void> {
    if (this.isInitialized) {
      logger.warn('PacificaOrderbookManager 已经初始化')
      return
    }

    logger.info('🚀 初始化 PacificaOrderbookManager...')
    this.updateStatus('initializing')

    try {
      // WebSocket服务在start中初始化
      this.isInitialized = true
      this.updateStatus('initialized')
      logger.info('✅ PacificaOrderbookManager 初始化完成')
    } catch (error: any) {
      this.updateStatus('error')
      logger.error('❌ PacificaOrderbookManager 初始化失败:', error)
      throw error
    }
  }

  /**
   * TradingService接口: 启动服务
   */
  async start(): Promise<void> {
    if (!this.isInitialized) {
      throw new Error('PacificaOrderbookManager 尚未初始化')
    }

    if (this.status === 'running') {
      logger.warn('PacificaOrderbookManager 已经在运行')
      return
    }

    logger.info('🚀 启动 PacificaOrderbookManager...')
    this.updateStatus('starting')

    try {
      await this.wsService.start()
      this.startAutoRefresh()
      this.updateStatus('running')
      logger.info('✅ PacificaOrderbookManager 启动成功')
    } catch (error: any) {
      this.updateStatus('error')
      logger.error('❌ PacificaOrderbookManager 启动失败:', error)
      throw error
    }
  }

  /**
   * TradingService接口: 停止服务
   */
  async stop(): Promise<void> {
    logger.info('🛑 停止 PacificaOrderbookManager...')
    this.updateStatus('stopping')

    this.stopAutoRefresh()
    await this.wsService.stop()

    this.cache.clear()
    this.stats.clear()
    this.updateCounts.clear()
    this.isInitialized = false
    this.updateStatus('stopped')

    logger.info('✅ PacificaOrderbookManager 已停止')
  }

  /**
   * TradingService接口: 获取服务状态
   */
  getStatus(): ServiceStatus {
    return {
      name: 'PacificaOrderbookManager',
      status: this.status === 'running' ? 'running' : this.status === 'error' ? 'error' : 'stopped',
      lastUpdate: this.lastStatusChange,
      details: {
        internalStatus: this.status,
        isInitialized: this.isInitialized,
        cacheSize: this.cache.size,
        wsConnected: this.wsService.isServiceConnected(),
      },
    }
  }

  private updateStatus(status: 'stopped' | 'initializing' | 'initialized' | 'starting' | 'running' | 'stopping' | 'error') {
    this.status = status
    this.lastStatusChange = Date.now()
  }

  /**
   * TradingService接口: 获取服务健康状态
   */
  getHealth(): { status: string; details: any } {
    return {
      status: this.status,
      details: {
        isConnected: this.wsService.isServiceConnected(),
        cachedSymbols: Array.from(this.cache.keys()),
        totalCacheSize: this.cache.size,
        wsStats: this.wsService.getStats(),
        config: this.config
      }
    }
  }

  /**
   * 更新缓存
   */
  private updateCache(orderbook: any): void {
    try {
      const symbol = orderbook.symbol.toUpperCase()
      const now = Date.now()

      // 转换Pacifica格式到标准格式
      const standardOrderbook = this.wsService.getStandardOrderbook(symbol)
      if (!standardOrderbook) {
        logger.warn('无法转换Pacifica orderbook格式:', { symbol })
        return
      }

      // 验证orderbook数据质量
      const isValid = this.validateOrderbook(standardOrderbook)

      const cachedOrderbook: CachedOrderbook = {
        symbol,
        bids: standardOrderbook.bids,
        asks: standardOrderbook.asks,
        timestamp: standardOrderbook.timestamp,
        isValid,
        lastRefresh: now
      }

      this.cache.set(symbol, cachedOrderbook)

      // 更新统计信息
      this.updateStats(symbol, cachedOrderbook)

      // 记录更新频率
      this.recordUpdate(symbol, now)

      // 发出缓存更新事件
      this.emit('cacheUpdated', symbol, cachedOrderbook)

      logger.debug('📊 Pacifica orderbook缓存已更新:', {
        symbol,
        bidsCount: cachedOrderbook.bids.length,
        asksCount: cachedOrderbook.asks.length,
        isValid,
        bestBid: cachedOrderbook.bids[0]?.price,
        bestAsk: cachedOrderbook.asks[0]?.price
      })

    } catch (error: any) {
      logger.error('更新Pacifica orderbook缓存失败:', error)
    }
  }

  /**
   * 验证orderbook数据质量
   */
  private validateOrderbook(orderbook: any): boolean {
    try {
      if (!orderbook.bids || !orderbook.asks ||
          !Array.isArray(orderbook.bids) || !Array.isArray(orderbook.asks)) {
        return false
      }

      if (orderbook.bids.length < this.config.minDepthLevels ||
          orderbook.asks.length < this.config.minDepthLevels) {
        return false
      }

      // 检查价格单调性
      for (let i = 1; i < orderbook.bids.length; i++) {
        if (orderbook.bids[i].price >= orderbook.bids[i-1].price) {
          return false
        }
      }

      for (let i = 1; i < orderbook.asks.length; i++) {
        if (orderbook.asks[i].price <= orderbook.asks[i-1].price) {
          return false
        }
      }

      // 检查价差是否合理
      const bestBid = orderbook.bids[0].price
      const bestAsk = orderbook.asks[0].price
      if (bestAsk <= bestBid) {
        return false
      }

      const spreadPercent = (bestAsk - bestBid) / bestBid
      if (spreadPercent > 0.1) {
        return false
      }

      return true

    } catch (error) {
      return false
    }
  }

  /**
   * 更新统计信息
   */
  private updateStats(symbol: string, orderbook: CachedOrderbook): void {
    try {
      if (!orderbook.isValid || orderbook.bids.length === 0 || orderbook.asks.length === 0) {
        return
      }

      const bestBid = orderbook.bids[0].price
      const bestAsk = orderbook.asks[0].price
      const spread = bestAsk - bestBid
      const spreadPercent = spread / bestBid
      const midPrice = (bestBid + bestAsk) / 2

      const totalBidSize = orderbook.bids.reduce((sum, entry) => sum + entry.size, 0)
      const totalAskSize = orderbook.asks.reduce((sum, entry) => sum + entry.size, 0)

      const updateFrequency = this.calculateUpdateFrequency(symbol)

      const stats: OrderbookStats = {
        symbol,
        spread,
        spreadPercent,
        midPrice,
        bestBid,
        bestAsk,
        totalBidSize,
        totalAskSize,
        depthLevels: Math.min(orderbook.bids.length, orderbook.asks.length),
        updateFrequency,
        lastUpdate: orderbook.timestamp
      }

      this.stats.set(symbol, stats)

    } catch (error: any) {
      logger.error('更新Pacifica orderbook统计失败:', error)
    }
  }

  /**
   * 记录更新时间点
   */
  private recordUpdate(symbol: string, timestamp: number): void {
    if (!this.updateCounts.has(symbol)) {
      this.updateCounts.set(symbol, [])
    }

    const updates = this.updateCounts.get(symbol)!
    updates.push(timestamp)

    const cutoff = timestamp - this.config.statsWindowMs
    while (updates.length > 0 && updates[0] < cutoff) {
      updates.shift()
    }
  }

  /**
   * 计算更新频率
   */
  private calculateUpdateFrequency(symbol: string): number {
    const updates = this.updateCounts.get(symbol) || []
    if (updates.length < 2) return 0

    const windowSizeMinutes = this.config.statsWindowMs / 60000
    return updates.length / windowSizeMinutes
  }

  /**
   * 获取orderbook（带缓存验证）
   */
  getOrderbook(symbol: string): CachedOrderbook | null {
    const cached = this.cache.get(symbol.toUpperCase())
    if (!cached) return null

    const now = Date.now()
    if (now - cached.lastRefresh > this.config.cacheExpiryMs) {
      logger.warn('Pacifica orderbook缓存已过期:', {
        symbol,
        age: now - cached.lastRefresh,
        expiry: this.config.cacheExpiryMs
      })
      return null
    }

    if (!cached.isValid) {
      logger.warn('Pacifica orderbook缓存数据无效:', { symbol })
      return null
    }

    return cached
  }

  /**
   * 获取最佳买卖价
   */
  getBestPrices(symbol: string): { bestBid: number; bestAsk: number; spread: number; midPrice: number } | null {
    const orderbook = this.getOrderbook(symbol)
    if (!orderbook || orderbook.bids.length === 0 || orderbook.asks.length === 0) {
      return null
    }

    const bestBid = orderbook.bids[0].price
    const bestAsk = orderbook.asks[0].price
    const spread = bestAsk - bestBid
    const midPrice = (bestBid + bestAsk) / 2

    return { bestBid, bestAsk, spread, midPrice }
  }

  /**
   * 计算市场影响
   */
  calculateMarketImpact(symbol: string, side: 'bid' | 'ask', usdAmount: number): {
    averagePrice: number
    totalSize: number
    priceImpact: number
    slippage: number
  } | null {
    const orderbook = this.getOrderbook(symbol)
    if (!orderbook) return null

    const entries = side === 'bid' ? orderbook.bids : orderbook.asks
    const midPrice = this.getBestPrices(symbol)?.midPrice || 0

    let totalValue = 0
    let totalSize = 0
    let remainingUsd = usdAmount

    for (const entry of entries) {
      if (remainingUsd <= 0) break

      const entryUsdValue = entry.price * entry.size
      const usedUsdValue = Math.min(entryUsdValue, remainingUsd)
      const usedSize = usedUsdValue / entry.price

      totalValue += usedUsdValue
      totalSize += usedSize
      remainingUsd -= usedUsdValue
    }

    if (totalSize === 0) return null

    const averagePrice = totalValue / totalSize
    const priceImpact = (averagePrice - midPrice) / midPrice
    const slippage = Math.abs(priceImpact)

    return {
      averagePrice,
      totalSize,
      priceImpact,
      slippage
    }
  }

  /**
   * 获取orderbook统计信息
   */
  getStats(symbol: string): OrderbookStats | null {
    return this.stats.get(symbol.toUpperCase()) || null
  }

  /**
   * 获取所有统计信息
   */
  getAllStats(): Map<string, OrderbookStats> {
    return new Map(this.stats)
  }

  /**
   * 启动自动刷新
   */
  private startAutoRefresh(): void {
    this.refreshTimer = setInterval(() => {
      this.cleanupExpiredCache()
      this.emitHealthCheck()
    }, this.config.autoRefreshInterval)
  }

  /**
   * 停止自动刷新
   */
  private stopAutoRefresh(): void {
    if (this.refreshTimer) {
      clearInterval(this.refreshTimer)
      this.refreshTimer = null
    }
  }

  /**
   * 清理过期缓存
   */
  private cleanupExpiredCache(): void {
    const now = Date.now()
    const expired: string[] = []

    for (const [symbol, cached] of this.cache.entries()) {
      if (now - cached.lastRefresh > this.config.cacheExpiryMs) {
        expired.push(symbol)
      }
    }

    for (const symbol of expired) {
      this.cache.delete(symbol)
      this.stats.delete(symbol)
      this.updateCounts.delete(symbol)
      logger.debug('清理过期Pacifica orderbook缓存:', { symbol })
    }
  }

  /**
   * 发出健康检查事件
   */
  private emitHealthCheck(): void {
    const healthStatus = {
      isConnected: this.wsService.isServiceConnected(),
      cachedSymbols: Array.from(this.cache.keys()),
      totalCacheSize: this.cache.size,
      wsStats: this.wsService.getStats()
    }

    this.emit('healthCheck', healthStatus)
  }

  /**
   * 强制刷新指定symbol的orderbook
   */
  async forceRefresh(symbol: string): Promise<void> {
    this.cache.delete(symbol.toUpperCase())
    this.stats.delete(symbol.toUpperCase())
    this.updateCounts.delete(symbol.toUpperCase())

    logger.info('强制刷新Pacifica orderbook缓存:', { symbol })
  }
}