/**
 * 市场数据失效回退服务
 * 基于 contracts/market-data-failover.md 的规范实现
 * 集成现有的价格管理器和 WebSocket 服务
 */
import { 
  MarketDataFeedManager,
  MarketDataFeed,
  FeedStatus 
} from '../models/MarketDataFeed.js'
import { SynthPriceSnapshotManager, SynthPriceSnapshot } from '../models/SynthPriceSnapshot.js'
import { MonitoringEventManager } from '../models/MonitoringEvent.js'
import { globalPriceManager } from '../modules/price/PriceManager.js' // 集成现有的价格管理器
import { logger } from '../utils/logger.js'

export interface PriceDataProvider {
  getPrice(symbol: string): Promise<{
    price: number
    timestamp: number
    source: string
  }>
}

export class MarketDataFailoverService {
  private feedManager: MarketDataFeedManager
  private snapshotManager: SynthPriceSnapshotManager
  private monitoringManager: MonitoringEventManager
  private priceProviders: Map<string, PriceDataProvider> = new Map()
  private failoverTimeout = 10000 // 10 秒超时

  constructor(
    feedManager: MarketDataFeedManager,
    snapshotManager: SynthPriceSnapshotManager,
    monitoringManager: MonitoringEventManager
  ) {
    this.feedManager = feedManager
    this.snapshotManager = snapshotManager
    this.monitoringManager = monitoringManager
  }

  /**
   * 注册价格数据提供者
   */
  registerPriceProvider(exchange: string, provider: PriceDataProvider): void {
    this.priceProviders.set(exchange, provider)
    logger.info(`注册价格数据提供者: ${exchange}`)
  }

  /**
   * 处理市场数据失效事件
   */
  async handleFeedFailure(feedId: string, reason: string): Promise<void> {
    logger.warn(`市场数据源失效: ${feedId}, 原因: ${reason}`)

    try {
      // 获取失效的 Feed 信息
      const failedFeed = this.feedManager.getFeed(feedId)
      if (!failedFeed) {
        logger.error(`未找到失效的 Feed: ${feedId}`)
        return
      }

      // 更新 Feed 状态
      this.feedManager.updateFeedStatus(feedId, 'failed')
      
      // 查找备用数据源
      const backupFeeds = this.feedManager.getFeedsBySymbol(failedFeed.symbol)
        .filter(feed => feed.feedId !== feedId && feed.status === 'active')

      if (backupFeeds.length === 0) {
        logger.warn(`没有可用的备用数据源: ${failedFeed.symbol}`)
        await this.createSyntheticPrice(failedFeed.symbol, 'no-backup-feeds')
        return
      }

      // 尝试切换到备用数据源
      const switchResult = await this.switchToBackupFeed(failedFeed, backupFeeds)
      
      if (switchResult.success) {
        logger.info(`成功切换到备用数据源: ${switchResult.backupFeedId}`)
        
        // 生成监控事件
        this.monitoringManager.addEvent({
          eventId: `feed-switch-${Date.now()}`,
          type: 'failover-alert',
          payload: {
            failedFeedId: feedId,
            backupFeedId: switchResult.backupFeedId,
            symbol: failedFeed.symbol,
            reason: reason,
            switchTime: switchResult.switchTime
          },
          severity: 'INFO',
          createdAt: new Date()
        })
      } else {
        logger.error(`切换到备用数据源失败: ${switchResult.error}`)
        await this.createSyntheticPrice(failedFeed.symbol, 'backup-switch-failed')
      }

    } catch (error: any) {
      logger.error(`处理市场数据失效失败: ${error.message}`)
      
      // 生成监控事件
      this.monitoringManager.addEvent({
        eventId: `feed-failure-${Date.now()}`,
        type: 'failover-alert',
        payload: {
          failedFeedId: feedId,
          reason: reason,
          error: error.message
        },
        severity: 'CRITICAL',
        createdAt: new Date()
      })
    }
  }

  /**
   * 切换到备用数据源
   */
  private async switchToBackupFeed(
    failedFeed: MarketDataFeed,
    backupFeeds: MarketDataFeed[]
  ): Promise<{ success: boolean; backupFeedId?: string; switchTime?: number; error?: string }> {
    const startTime = Date.now()

    for (const backupFeed of backupFeeds) {
      try {
        logger.info(`尝试切换到备用数据源: ${backupFeed.feedId}`)

        // 验证备用数据源
        const isValid = await this.validateBackupFeed(backupFeed)
        if (!isValid) {
          logger.warn(`备用数据源无效: ${backupFeed.feedId}`)
          continue
        }

        // 更新备用数据源状态
        this.feedManager.updateFeedStatus(backupFeed.feedId, 'active')

        // 更新全局价格管理器
        await this.updateGlobalPriceManager(backupFeed)

        const switchTime = Date.now() - startTime
        
        if (switchTime <= this.failoverTimeout) {
          return {
            success: true,
            backupFeedId: backupFeed.feedId,
            switchTime
          }
        } else {
          logger.warn(`备用数据源切换超时: ${backupFeed.feedId}`)
        }

      } catch (error: any) {
        logger.warn(`备用数据源切换失败: ${backupFeed.feedId}, ${error.message}`)
      }
    }

    return {
      success: false,
      error: 'No valid backup feeds available within timeout'
    }
  }

  /**
   * 验证备用数据源
   */
  private async validateBackupFeed(feed: MarketDataFeed): Promise<boolean> {
    try {
      // 检查数据源是否可达
      const provider = this.priceProviders.get(feed.exchange)
      if (!provider) {
        logger.warn(`没有价格提供者: ${feed.exchange}`)
        return false
      }

      // 尝试获取价格数据
      const priceData = await Promise.race([
        provider.getPrice(feed.symbol),
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('Timeout')), 5000)
        )
      ]) as any

      if (!priceData || priceData.price <= 0) {
        logger.warn(`备用数据源价格无效: ${feed.feedId}`)
        return false
      }

      // 检查数据新鲜度
      const dataAge = Date.now() - priceData.timestamp
      if (dataAge > 30000) { // 30 秒
        logger.warn(`备用数据源数据过时: ${feed.feedId}, 年龄: ${dataAge}ms`)
        return false
      }

      return true

    } catch (error: any) {
      logger.warn(`验证备用数据源失败: ${feed.feedId}, ${error.message}`)
      return false
    }
  }

  /**
   * 更新全局价格管理器
   */
  private async updateGlobalPriceManager(activeFeed: MarketDataFeed): Promise<void> {
    try {
      const provider = this.priceProviders.get(activeFeed.exchange)
      if (!provider) return

      const priceData = await provider.getPrice(activeFeed.symbol)
      
      // 更新全局价格管理器
      globalPriceManager.updatePrice(
        activeFeed.symbol,
        priceData.price,
        priceData.timestamp
      )

      logger.info(`更新全局价格管理器: ${activeFeed.symbol} = ${priceData.price}`)

    } catch (error: any) {
      logger.warn(`更新全局价格管理器失败: ${error.message}`)
    }
  }

  /**
   * 创建合成价格
   */
  private async createSyntheticPrice(symbol: string, reason: string): Promise<void> {
    try {
      logger.warn(`创建合成价格: ${symbol}, 原因: ${reason}`)

      // 获取所有可用的价格数据源
      const availableFeeds = this.feedManager.getFeedsBySymbol(symbol)
        .filter(feed => feed.status === 'active')

      if (availableFeeds.length === 0) {
        logger.error(`没有可用的数据源创建合成价格: ${symbol}`)
        return
      }

      // 收集价格数据
      const priceData: Array<{ price: number; source: string; weight: number }> = []
      
      for (const feed of availableFeeds) {
        try {
          const provider = this.priceProviders.get(feed.exchange)
          if (provider) {
            const data = await provider.getPrice(symbol)
            priceData.push({
              price: data.price,
              source: feed.exchange,
              weight: this.getFeedWeight(feed)
            })
          }
        } catch (error: any) {
          logger.warn(`获取价格数据失败: ${feed.exchange}, ${error.message}`)
        }
      }

      if (priceData.length === 0) {
        logger.error(`无法获取任何价格数据: ${symbol}`)
        return
      }

      // 计算加权平均价格
      const totalWeight = priceData.reduce((sum, data) => sum + data.weight, 0)
      const weightedPrice = priceData.reduce(
        (sum, data) => sum + (data.price * data.weight), 0
      ) / totalWeight

      // 计算买卖价差（简化版本）
      const spread = weightedPrice * 0.001 // 0.1% 价差
      const bid = weightedPrice - spread / 2
      const ask = weightedPrice + spread / 2

      // 创建合成价格快照
      const snapshot: SynthPriceSnapshot = {
        snapshotId: `synth-${Date.now()}`,
        symbol,
        sourceFeeds: priceData.map(d => d.source),
        midPrice: weightedPrice,
        bid,
        ask,
        timestamp: new Date(),
        reason: reason as any
      }

      this.snapshotManager.addSnapshot(snapshot)

      // 更新全局价格管理器
      globalPriceManager.updatePrice(symbol, weightedPrice, Date.now())

      logger.info(`合成价格创建成功: ${symbol} = ${weightedPrice}`, {
        sourceFeeds: snapshot.sourceFeeds,
        reason
      })

      // 生成监控事件
      this.monitoringManager.addEvent({
        eventId: `synth-price-${Date.now()}`,
        type: 'failover-alert',
        payload: {
          symbol,
          syntheticPrice: weightedPrice,
          sourceFeeds: snapshot.sourceFeeds,
          reason
        },
        severity: 'WARN',
        createdAt: new Date()
      })

    } catch (error: any) {
      logger.error(`创建合成价格失败: ${error.message}`)
    }
  }

  /**
   * 获取 Feed 权重
   */
  private getFeedWeight(feed: MarketDataFeed): number {
    // 基于 Feed 类型和状态分配权重
    switch (feed.type) {
      case 'websocket':
        return 1.0 // WebSocket 权重最高
      case 'rest':
        return 0.8
      case 'grpc':
        return 0.9
      default:
        return 0.5
    }
  }

  /**
   * 监控数据源健康状态
   */
  async monitorFeedHealth(): Promise<void> {
    const feeds = this.feedManager.getAllFeeds()
    
    for (const feed of feeds) {
      if (feed.status === 'active') {
        try {
          const provider = this.priceProviders.get(feed.exchange)
          if (provider) {
            const priceData = await Promise.race([
              provider.getPrice(feed.symbol),
              new Promise((_, reject) => 
                setTimeout(() => reject(new Error('Health check timeout')), 5000)
              )
            ]) as any

            const dataAge = Date.now() - priceData.timestamp
            if (dataAge > 60000) { // 1 分钟
              logger.warn(`数据源健康检查失败: ${feed.feedId}, 数据年龄: ${dataAge}ms`)
              await this.handleFeedFailure(feed.feedId, 'stale-data')
            }
          }
        } catch (error: any) {
          logger.warn(`数据源健康检查失败: ${feed.feedId}, ${error.message}`)
          await this.handleFeedFailure(feed.feedId, 'health-check-failed')
        }
      }
    }
  }

  /**
   * 获取失效回退统计
   */
  getFailoverStats(): {
    totalFeeds: number
    activeFeeds: number
    failedFeeds: number
    syntheticPrices: number
    lastFailoverTime: Date | null
  } {
    const feeds = this.feedManager.getAllFeeds()
    const totalFeeds = feeds.length
    const activeFeeds = feeds.filter(f => f.status === 'active').length
    const failedFeeds = feeds.filter(f => f.status === 'failed').length
    const syntheticPrices = this.snapshotManager.getAllSnapshots().length
    
    // 简化：返回当前时间作为最后失效时间
    return {
      totalFeeds,
      activeFeeds,
      failedFeeds,
      syntheticPrices,
      lastFailoverTime: new Date()
    }
  }
}
