/**
 * WebSocket 客户端工具
 *
 * @module utils/websocket
 * @author czj
 * @date 2026-07-09
 */

type MessageHandler = (data: any) => void

/**
 * WebSocket 客户端类
 *
 * 封装 WebSocket 连接，支持断线重连和事件回调。
 *
 * Example:
 * >>> const ws = new WebSocketClient("exec_001")
 * >>> ws.on("step_update", (data) => console.log(data))
 * >>> ws.on("execution_complete", (data) => console.log("done"))
 * >>> ws.connect()
 */
export class WebSocketClient {
  /** WebSocket 连接实例 */
  private ws: WebSocket | null = null

  /** 执行记录 ID */
  private executionId: string = ''

  /** 是否已连接 */
  private connected: boolean = false

  /** 重连尝试次数 */
  private retryCount: number = 0

  /** 最大重连次数 */
  private maxRetry: number = 3

  /** 重连间隔（毫秒） */
  private retryInterval: number = 3000

  /** 事件处理器映射 */
  private handlers: Map<string, MessageHandler[]> = new Map()

  constructor(executionId: string) {
    this.executionId = executionId
  }

  /**
   * 建立 WebSocket 连接
   */
  connect(): void {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
    const url = `${protocol}//${window.location.host}/api/executions/ws/${this.executionId}`

    try {
      this.ws = new WebSocket(url)

      this.ws.onopen = () => {
        this.connected = true
        this.retryCount = 0
        console.log(`[WebSocket] 已连接到执行 ${this.executionId}`)
        this.trigger('connected', { executionId: this.executionId })
      }

      this.ws.onmessage = (event) => {
        try {
          const message = JSON.parse(event.data)
          const type = message.type || 'unknown'

          // 触发对应类型的处理器
          this.trigger(type, message.data || message)

          // 也触发通配处理器
          this.trigger('*', message)
        } catch (e) {
          console.error('[WebSocket] 消息解析失败:', e)
        }
      }

      this.ws.onclose = (event) => {
        this.connected = false
        console.log(`[WebSocket] 连接已断开: code=${event.code}`)

        // 非正常关闭时自动重连
        if (event.code !== 1000 && this.retryCount < this.maxRetry) {
          this.retryCount++
          console.log(`[WebSocket] 第 ${this.retryCount} 次重连...`)
          setTimeout(() => this.connect(), this.retryInterval)
        }
      }

      this.ws.onerror = (error) => {
        console.error('[WebSocket] 连接错误:', error)
      }
    } catch (error) {
      console.error('[WebSocket] 创建连接失败:', error)
    }
  }

  /**
   * 注册事件处理器
   *
   * @param event 事件类型
   * @param handler 处理器函数
   */
  on(event: string, handler: MessageHandler): void {
    if (!this.handlers.has(event)) {
      this.handlers.set(event, [])
    }
    this.handlers.get(event)!.push(handler)
  }

  /**
   * 移除事件处理器
   *
   * @param event 事件类型
   * @param handler 处理器函数
   */
  off(event: string, handler: MessageHandler): void {
    const handlers = this.handlers.get(event)
    if (handlers) {
      const idx = handlers.indexOf(handler)
      if (idx >= 0) handlers.splice(idx, 1)
    }
  }

  /**
   * 触发事件
   *
   * @param event 事件类型
   * @param data 数据
   */
  private trigger(event: string, data: any): void {
    const handlers = this.handlers.get(event)
    if (handlers) {
      handlers.forEach((h) => {
        try {
          h(data)
        } catch (e) {
          console.error(`[WebSocket] ${event} 处理器执行失败:`, e)
        }
      })
    }
  }

  /**
   * 发送消息到服务端
   *
   * @param data 消息数据
   */
  send(data: any): void {
    if (this.ws && this.connected) {
      this.ws.send(JSON.stringify(data))
    }
  }

  /**
   * 断开连接
   */
  disconnect(): void {
    if (this.ws) {
      this.ws.close(1000, '手动断开')
      this.ws = null
      this.connected = false
    }
    this.handlers.clear()
  }

  /**
   * 获取连接状态
   */
  isConnected(): boolean {
    return this.connected
  }
}