import WebSocket from 'ws'
import { HttpsProxyAgent } from 'https-proxy-agent'
import { SocksProxyAgent } from 'socks-proxy-agent'
import { EventEmitter } from 'events'
import { logger } from '../../utils/logger.js'
import { Config } from '../../config/simpleEnv.js'

/**
 * Pacifica WebSocket 订阅消息格式
 */
interface PacificaSubscribeMessage {
  method: 'SUBSCRIBE' | 'UNSUBSCRIBE'
  params: string[]
  id: number
}

/**
 * Pacifica WebSocket 数据流消息格式
 */
interface PacificaStreamMessage {
  stream: string
  data: any
}

/**
 * 订阅状态管理
 */
interface SubscriptionState {
  id: number
  stream: string
  account?: string
  active: boolean
}

/**
 * Pacifica WebSocket 客户端 - 支持实时数据订阅
 * 基于 Pacifica 官方 WebSocket API 实现
 * 支持：价格订阅、订单簿订阅、账户余额订阅、仓位订阅等
 */
export class PacificaWebSocketClient extends EventEmitter {
  private ws: WebSocket | null = null
  private proxyAgent: HttpsProxyAgent<string> | SocksProxyAgent | null = null
  private isConnected = false
  private reconnectAttempts = 0
  private maxReconnectAttempts = 10
  private reconnectDelay = 1000
  private subscriptions = new Map<string, SubscriptionState>()
  private subscriptionId = 1
  private pingInterval: NodeJS.Timeout | null = null

  constructor(
    private wsUrl: string = 'wss://ws.pacifica.fi/ws',
    private accountId?: string,
    private privateKey?: string,
  ) {
    super()
    this.initializeProxy()
  }

  /**
   * 初始化代理配置
   */
  private initializeProxy(): void {
    if (!Config.proxy.enabled()) {
      return
    }

    try {
      // 构建代理配置
      const protocol = Config.proxy.protocol() || 'http'
      const host = Config.proxy.host()
      const port = Config.proxy.port()
      const username = Config.proxy.username()
      const password = Config.proxy.buildPassword('pacifica') || Config.proxy.buildPassword()

      if (host && port) {
        let proxyUrl = `${protocol}://`
        if (username && password) {
          proxyUrl += `${encodeURIComponent(username)}:${encodeURIComponent(password)}@`
        }
        proxyUrl += `${host}:${port}`

        if (protocol === 'socks5') {
          this.proxyAgent = new SocksProxyAgent(proxyUrl)
        } else {
          this.proxyAgent = new HttpsProxyAgent(proxyUrl)
        }

        logger.info('Pacifica WebSocket代理已配置', {
          protocol,
          host,
          port,
          hasAuth: !!(username && password),
        })
      } else {
        logger.warn('代理配置不完整，跳过代理设置')
      }
    } catch (error: any) {
      logger.error('代理配置失败', { error: error.message })
    }
  }

  /**
   * 连接 WebSocket
   */
  async connect(): Promise<void> {
    return new Promise((resolve, reject) => {
      try {
        const wsOptions: any = {}

        if (this.proxyAgent) {
          // 检测IPRoyal代理，强制使用HTTP协议
          const proxyHost = Config.proxy.host() || ''
          if (proxyHost.includes('iproyal.com')) {
            logger.info('检测到IPRoyal代理，使用HTTP协议进行WebSocket连接')
            wsOptions.agent = this.proxyAgent
          } else {
            wsOptions.agent = this.proxyAgent
          }
        }

        this.ws = new WebSocket(this.wsUrl, wsOptions)

        this.ws.on('open', () => {
          this.isConnected = true
          this.reconnectAttempts = 0
          logger.info('✅ Pacifica WebSocket连接成功')
          this.startPingPong()
          resolve()
        })

        this.ws.on('message', (data: WebSocket.Data) => {
          try {
            const message = JSON.parse(data.toString())
            this.handleMessage(message)
          } catch (error: any) {
            logger.error('解析WebSocket消息失败', { error: error.message })
          }
        })

        this.ws.on('close', (code: number, reason: Buffer) => {
          this.isConnected = false
          this.stopPingPong()
          logger.warn('Pacifica WebSocket连接关闭', { code, reason: reason.toString() })

          if (this.reconnectAttempts < this.maxReconnectAttempts) {
            this.scheduleReconnect()
          }
        })

        this.ws.on('error', (error: Error) => {
          logger.error('Pacifica WebSocket连接错误', { error: error.message })
          reject(error)
        })
      } catch (error: any) {
        logger.error('WebSocket连接失败', { error: error.message })
        reject(error)
      }
    })
  }

  /**
   * 处理接收到的消息
   */
  private handleMessage(message: any): void {
    // 处理订阅确认消息
    if (message.result && message.id) {
      logger.debug('订阅确认', { id: message.id, result: message.result })
      return
    }

    // 处理数据流消息
    if (message.stream && message.data) {
      const streamMessage = message as PacificaStreamMessage
      this.emit('data', streamMessage)

      // 根据流类型触发特定事件
      if (streamMessage.stream.startsWith('prices@')) {
        this.emit('prices', streamMessage.data)
      } else if (streamMessage.stream.startsWith('orderbook@')) {
        this.emit('orderbook', streamMessage.data)
      } else if (streamMessage.stream.startsWith('balance@')) {
        this.emit('balance', streamMessage.data)
      } else if (streamMessage.stream.startsWith('positions@')) {
        this.emit('positions', streamMessage.data)
      } else if (streamMessage.stream.startsWith('orders@')) {
        this.emit('orders', streamMessage.data)
      }
    }
  }

  /**
   * 订阅价格数据
   */
  async subscribePrices(symbols?: string[]): Promise<void> {
    const stream = symbols && symbols.length > 0 ? `prices@${symbols.join(',')}` : 'prices@all'
    await this.subscribe([stream])
  }

  /**
   * 订阅订单簿数据
   */
  async subscribeOrderBook(symbol: string): Promise<void> {
    await this.subscribe([`orderbook@${symbol}`])
  }

  /**
   * 订阅账户余额（需要认证）
   */
  async subscribeBalance(account?: string): Promise<void> {
    const targetAccount = account || this.accountId
    if (!targetAccount) {
      throw new Error('账户ID是订阅余额所必需的')
    }
    await this.subscribe([`balance@${targetAccount}`])
  }

  /**
   * 订阅账户仓位（需要认证）
   */
  async subscribePositions(account?: string): Promise<void> {
    const targetAccount = account || this.accountId
    if (!targetAccount) {
      throw new Error('账户ID是订阅仓位所必需的')
    }
    await this.subscribe([`positions@${targetAccount}`])
  }

  /**
   * 订阅订单更新（需要认证）
   */
  async subscribeOrders(account?: string): Promise<void> {
    const targetAccount = account || this.accountId
    if (!targetAccount) {
      throw new Error('账户ID是订阅订单所必需的')
    }
    await this.subscribe([`orders@${targetAccount}`])
  }

  /**
   * 通用订阅方法
   */
  private async subscribe(streams: string[]): Promise<void> {
    if (!this.isConnected) {
      throw new Error('WebSocket未连接')
    }

    const subscribeMessage: PacificaSubscribeMessage = {
      method: 'SUBSCRIBE',
      params: streams,
      id: this.subscriptionId++,
    }

    // 记录订阅状态
    streams.forEach(stream => {
      this.subscriptions.set(stream, {
        id: subscribeMessage.id,
        stream,
        active: true,
      })
    })

    this.ws?.send(JSON.stringify(subscribeMessage))
    logger.info('发送订阅请求', { streams, id: subscribeMessage.id })
  }

  /**
   * 取消订阅
   */
  async unsubscribe(streams: string[]): Promise<void> {
    if (!this.isConnected) {
      return
    }

    const unsubscribeMessage: PacificaSubscribeMessage = {
      method: 'UNSUBSCRIBE',
      params: streams,
      id: this.subscriptionId++,
    }

    // 更新订阅状态
    streams.forEach(stream => {
      this.subscriptions.delete(stream)
    })

    this.ws?.send(JSON.stringify(unsubscribeMessage))
    logger.info('发送取消订阅请求', { streams, id: unsubscribeMessage.id })
  }

  /**
   * 启动心跳检测
   */
  private startPingPong(): void {
    this.pingInterval = setInterval(() => {
      if (this.ws && this.isConnected) {
        this.ws.ping()
      }
    }, 30000) // 每30秒发送一次ping
  }

  /**
   * 停止心跳检测
   */
  private stopPingPong(): void {
    if (this.pingInterval) {
      clearInterval(this.pingInterval)
      this.pingInterval = null
    }
  }

  /**
   * 安排重连
   */
  private scheduleReconnect(): void {
    this.reconnectAttempts++
    const delay = Math.min(this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1), 30000)

    logger.info(`尝试重连Pacifica WebSocket (${this.reconnectAttempts}/${this.maxReconnectAttempts}) 延迟: ${delay}ms`)

    setTimeout(async () => {
      try {
        await this.connect()

        // 重新订阅之前的流
        const activeStreams = Array.from(this.subscriptions.keys())
        if (activeStreams.length > 0) {
          await this.subscribe(activeStreams)
        }
      } catch (error: any) {
        logger.error('重连失败', { error: error.message })
      }
    }, delay)
  }

  /**
   * 获取连接状态
   */
  isConnectionOpen(): boolean {
    return this.isConnected && this.ws?.readyState === WebSocket.OPEN
  }

  /**
   * 获取活跃订阅列表
   */
  getActiveSubscriptions(): string[] {
    return Array.from(this.subscriptions.keys())
  }

  /**
   * 关闭连接
   */
  async close(): Promise<void> {
    this.stopPingPong()
    this.subscriptions.clear()

    if (this.ws) {
      this.ws.close()
      this.ws = null
    }

    this.isConnected = false
    logger.info('Pacifica WebSocket连接已关闭')
  }
}