/**
 * Pacifica综合客户端
 *
 * 整合数据接口和交易操作接口，提供完整的Pacifica DEX API访问能力
 */

import WebSocket from 'ws'

import {
  PacificaConfig,
  PacificaApiResponse,
  PacificaWebSocketMessage,
  PacificaWebSocketSubscription,
} from '@/types/pacifica'
import { UniversalHttpClient } from '@/utils/universalHttpClient'

import { PacificaDataClient } from './PacificaDataClient'
import { PacificaTradingClient } from './PacificaTradingClient'

export class PacificaClient {
  private httpClient: UniversalHttpClient
  private dataClient: PacificaDataClient
  private tradingClient: PacificaTradingClient
  private accountId: string
  private config: PacificaConfig
  private wsConnection?: WebSocket
  private wsSubscriptions: Map<string, string[]> = new Map()

  constructor(httpClient: UniversalHttpClient, accountId: string, config: PacificaConfig) {
    this.httpClient = httpClient
    this.accountId = accountId
    this.config = config

    // 初始化子客户端
    this.dataClient = new PacificaDataClient(httpClient, accountId)
    this.tradingClient = new PacificaTradingClient(httpClient, accountId)

    // 注册平台到HTTP客户端
    this.registerPlatform()
  }

  // ======================== 初始化和配置 ========================

  /**
   * 注册Pacifica平台到HTTP客户端
   */
  private async registerPlatform(): Promise<void> {
    await this.httpClient.registerPlatform({
      name: 'pacifica',
      baseUrl: this.config.baseUrl,
      defaultTimeout: {
        connect: 5000,
        read: this.config.timeout || 10000,
        write: 5000,
      },
      retryConfig: {
        maxAttempts: 3,
        delay: 1000,
        exponentialBackoff: true,
      },
      rateLimits: {
        enabled: true,
        maxRequests: 1200,
        windowMs: 60000,
      },
      authConfig: {
        type: 'signature',
        headerNames: {
          signature: 'X-Signature',
          timestamp: 'X-Timestamp',
        },
        requiresTimestamp: true,
      },
      healthCheck: {
        enabled: true,
        endpoint: '/api/v3/ping',
        interval: 30000,
        timeout: 5000,
      },
      endpoints: {
        account: '/api/v3/account',
        orders: '/api/v3/order',
        positions: '/api/v3/position',
        markets: '/api/v3/exchangeInfo',
        websocket: 'wss://stream.pacifica.exchange/ws',
      },
    })
  }

  // ======================== 数据接口访问器 ========================

  /**
   * 获取数据客户端实例
   */
  get data(): PacificaDataClient {
    return this.dataClient
  }

  /**
   * 获取交易客户端实例
   */
  get trading(): PacificaTradingClient {
    return this.tradingClient
  }

  // ======================== 快捷数据接口 ========================

  /**
   * 快速获取价格
   */
  async getPrice(symbol: string) {
    return this.dataClient.getPrice(symbol)
  }

  /**
   * 快速获取订单簿
   */
  async getOrderBook(symbol: string, limit?: number) {
    return this.dataClient.getOrderBook(symbol, limit)
  }

  /**
   * 快速获取24小时统计
   */
  async getTicker24hr(symbol?: string) {
    return this.dataClient.getTicker24hr(symbol)
  }

  /**
   * 快速获取K线数据
   */
  async getKlines(symbol: string, interval: string, limit?: number) {
    return this.dataClient.getKlines(symbol, interval, { limit })
  }

  // ======================== 快捷交易接口 ========================

  /**
   * 快速创建限价买单
   */
  async limitBuy(symbol: string, quantity: string, price: string) {
    return this.tradingClient.createLimitBuyOrder(symbol, quantity, price)
  }

  /**
   * 快速创建限价卖单
   */
  async limitSell(symbol: string, quantity: string, price: string) {
    return this.tradingClient.createLimitSellOrder(symbol, quantity, price)
  }

  /**
   * 快速创建市价买单
   */
  async marketBuy(symbol: string, quantity?: string, quoteOrderQty?: string) {
    return this.tradingClient.createMarketBuyOrder(symbol, quantity, quoteOrderQty)
  }

  /**
   * 快速创建市价卖单
   */
  async marketSell(symbol: string, quantity: string) {
    return this.tradingClient.createMarketSellOrder(symbol, quantity)
  }

  /**
   * 快速取消订单
   */
  async cancelOrder(symbol: string, orderId?: number, origClientOrderId?: string) {
    return this.tradingClient.cancelOrder({
      symbol,
      orderId,
      origClientOrderId,
    })
  }

  /**
   * 快速获取开放订单
   */
  async getOpenOrders(symbol?: string) {
    return this.tradingClient.getOpenOrders(symbol)
  }

  /**
   * 快速获取账户信息
   */
  async getAccount() {
    return this.tradingClient.getAccountInfo()
  }

  // ======================== WebSocket 功能 ========================

  /**
   * 建立WebSocket连接
   */
  async connectWebSocket(): Promise<void> {
    if (this.wsConnection && this.wsConnection.readyState === WebSocket.OPEN) {
      console.log('WebSocket already connected')
      return
    }

    return new Promise((resolve, reject) => {
      try {
        this.wsConnection = new WebSocket(this.config.wsUrl)

        this.wsConnection.onopen = () => {
          console.log('Pacifica WebSocket connected')
          resolve()
        }

        this.wsConnection.onmessage = event => {
          this.handleWebSocketMessage(event as unknown as MessageEvent)
        }

        this.wsConnection.onerror = error => {
          console.error('Pacifica WebSocket error:', error)
          reject(error)
        }

        this.wsConnection.onclose = event => {
          console.log('Pacifica WebSocket closed:', event.code, event.reason)
          this.handleWebSocketClose()
        }
      } catch (error) {
        reject(error)
      }
    })
  }

  /**
   * 断开WebSocket连接
   */
  disconnectWebSocket(): void {
    if (this.wsConnection) {
      this.wsConnection.close()
      this.wsConnection = undefined
      this.wsSubscriptions.clear()
    }
  }

  /**
   * 订阅价格流
   */
  async subscribePriceStream(symbol: string): Promise<void> {
    const stream = `${symbol.toLowerCase()}@ticker`
    await this.subscribeStream(stream)
  }

  /**
   * 订阅订单簿流
   */
  async subscribeOrderBookStream(symbol: string, level: number = 5): Promise<void> {
    const stream = `${symbol.toLowerCase()}@depth${level}@100ms`
    await this.subscribeStream(stream)
  }

  /**
   * 订阅交易流
   */
  async subscribeTradeStream(symbol: string): Promise<void> {
    const stream = `${symbol.toLowerCase()}@trade`
    await this.subscribeStream(stream)
  }

  /**
   * 订阅K线流
   */
  async subscribeKlineStream(symbol: string, interval: string): Promise<void> {
    const stream = `${symbol.toLowerCase()}@kline_${interval}`
    await this.subscribeStream(stream)
  }

  /**
   * 订阅用户数据流
   */
  async subscribeUserDataStream(): Promise<void> {
    // 获取监听密钥
    const listenKeyResponse = await this.dataClient.getListenKey()
    if (!listenKeyResponse.success) {
      throw new Error('Failed to get listen key')
    }

    const stream = listenKeyResponse.data.listenKey
    await this.subscribeStream(stream)

    // 设置定期续期监听密钥
    setInterval(
      async () => {
        try {
          await this.dataClient.keepAliveListenKey(stream)
        } catch (error) {
          console.error('Failed to keep alive listen key:', error)
        }
      },
      30 * 60 * 1000,
    ) // 每30分钟续期
  }

  /**
   * 通用流订阅方法
   */
  private async subscribeStream(stream: string): Promise<void> {
    if (!this.wsConnection || this.wsConnection.readyState !== WebSocket.OPEN) {
      await this.connectWebSocket()
    }

    const subscription: PacificaWebSocketSubscription = {
      method: 'SUBSCRIBE',
      params: [stream],
      id: Date.now(),
    }

    this.wsConnection!.send(JSON.stringify(subscription))

    // 记录订阅
    const accountSubscriptions = this.wsSubscriptions.get(this.accountId) || []
    accountSubscriptions.push(stream)
    this.wsSubscriptions.set(this.accountId, accountSubscriptions)
  }

  /**
   * 取消订阅流
   */
  async unsubscribeStream(stream: string): Promise<void> {
    if (!this.wsConnection || this.wsConnection.readyState !== WebSocket.OPEN) {
      return
    }

    const subscription: PacificaWebSocketSubscription = {
      method: 'UNSUBSCRIBE',
      params: [stream],
      id: Date.now(),
    }

    this.wsConnection.send(JSON.stringify(subscription))

    // 从记录中移除
    const accountSubscriptions = this.wsSubscriptions.get(this.accountId) || []
    const index = accountSubscriptions.indexOf(stream)
    if (index > -1) {
      accountSubscriptions.splice(index, 1)
      this.wsSubscriptions.set(this.accountId, accountSubscriptions)
    }
  }

  /**
   * 处理WebSocket消息
   */
  private handleWebSocketMessage(event: MessageEvent): void {
    try {
      const message: PacificaWebSocketMessage = JSON.parse(event.data)

      // 发出事件给外部监听器
      this.emit('message', message)

      // 根据流类型分发事件
      if (message.stream) {
        const streamType = this.getStreamType(message.stream)
        this.emit(streamType, message.data)
      }
    } catch (error) {
      console.error('Failed to parse WebSocket message:', error)
    }
  }

  /**
   * 处理WebSocket关闭
   */
  private handleWebSocketClose(): void {
    // 自动重连逻辑
    setTimeout(() => {
      console.log('Attempting to reconnect WebSocket...')
      this.reconnectWebSocket()
    }, 5000)
  }

  /**
   * 重连WebSocket
   */
  private async reconnectWebSocket(): Promise<void> {
    try {
      await this.connectWebSocket()

      // 重新订阅之前的流
      const accountSubscriptions = this.wsSubscriptions.get(this.accountId) || []
      for (const stream of accountSubscriptions) {
        await this.subscribeStream(stream)
      }
    } catch (error) {
      console.error('Failed to reconnect WebSocket:', error)
    }
  }

  /**
   * 获取流类型
   */
  private getStreamType(stream: string): string {
    if (stream.includes('@ticker')) return 'ticker'
    if (stream.includes('@depth')) return 'orderbook'
    if (stream.includes('@trade')) return 'trade'
    if (stream.includes('@kline')) return 'kline'
    if (stream.includes('@')) return 'userdata'
    return 'message'
  }

  // ======================== 事件系统 ========================

  private eventListeners: Map<string, ((...args: any[]) => void)[]> = new Map()

  /**
   * 监听事件
   */
  on(event: string, listener: (...args: any[]) => void): void {
    const listeners = this.eventListeners.get(event) || []
    listeners.push(listener)
    this.eventListeners.set(event, listeners)
  }

  /**
   * 移除事件监听器
   */
  off(event: string, listener: (...args: any[]) => void): void {
    const listeners = this.eventListeners.get(event) || []
    const index = listeners.indexOf(listener)
    if (index > -1) {
      listeners.splice(index, 1)
      this.eventListeners.set(event, listeners)
    }
  }

  /**
   * 发出事件
   */
  private emit(event: string, data: any): void {
    const listeners = this.eventListeners.get(event) || []
    listeners.forEach(listener => {
      try {
        listener(data)
      } catch (error) {
        console.error(`Error in event listener for ${event}:`, error)
      }
    })
  }

  // ======================== 工具方法 ========================

  /**
   * 健康检查
   */
  async healthCheck(): Promise<PacificaApiResponse<Record<string, any>>> {
    return this.dataClient.ping()
  }

  /**
   * 获取服务器时间
   */
  async getServerTime() {
    return this.dataClient.getServerTime()
  }

  /**
   * 获取交易所信息
   */
  async getExchangeInfo() {
    return this.dataClient.getExchangeInfo()
  }

  /**
   * 设置接收窗口
   */
  setRecvWindow(recvWindow: number): void {
    this.tradingClient.setRecvWindow(recvWindow)
  }

  /**
   * 获取客户端配置
   */
  getConfig(): {
    accountId: string
    platform: string
    baseUrl: string
    wsUrl: string
    dataClient: any
    tradingClient: any
  } {
    return {
      accountId: this.accountId,
      platform: 'pacifica',
      baseUrl: this.config.baseUrl,
      wsUrl: this.config.wsUrl,
      dataClient: this.dataClient.getClientConfig(),
      tradingClient: this.tradingClient.getClientConfig(),
    }
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus(): {
    http: boolean
    websocket: boolean
    subscriptions: string[]
  } {
    return {
      http: true, // HTTP客户端总是可用
      websocket: this.wsConnection?.readyState === WebSocket.OPEN,
      subscriptions: this.wsSubscriptions.get(this.accountId) || [],
    }
  }

  /**
   * 清理资源
   */
  destroy(): void {
    this.disconnectWebSocket()
    this.eventListeners.clear()
    this.wsSubscriptions.clear()
  }
}
