/**
 * WebSocket 客户端封装
 * 基于 socket.io-client 实现
 */

import { io, Socket } from 'socket.io-client'

interface WebSocketConfig {
  url?: string
  reconnectionAttempts?: number
  reconnectionDelay?: number
  timeout?: number
}

interface RequestMessage {
  id: string
  action: string
  data: any
}

interface ResponseMessage {
  id: string
  status: 'success' | 'error' | 'streaming' | 'complete'
  data?: any
  error?: string
  stage?: string
  message?: string
  [key: string]: any
}

interface StreamProgressCallback {
  (data: any): void
}

type RequestHandler = {
  resolve: (value: any) => void
  reject: (error: Error) => void
  timer?: ReturnType<typeof setTimeout>
  onProgress?: StreamProgressCallback
}

class WebSocketClient {
  private socket: Socket | null = null
  private requestHandlers = new Map<string, RequestHandler>()
  private streamHandlers = new Map<string, StreamProgressCallback>()
  private config: Required<WebSocketConfig>
  private isConnected = false

  constructor() {
    this.config = {
      url: '',
      reconnectionAttempts: 5,
      reconnectionDelay: 1000,
      timeout: 300000, // 5分钟超时
    }
  }

  /**
   * 连接到WebSocket服务器
   */
  connect(url?: string): Promise<void> {
    return new Promise((resolve, reject) => {
      const wsUrl = url || this.config.url || window.location.origin

      this.socket = io(wsUrl, {
        transports: ['websocket', 'polling'],
        reconnection: true,
        reconnectionAttempts: this.config.reconnectionAttempts,
        reconnectionDelay: this.config.reconnectionDelay,
      })

      this.socket.on('connect', () => {
        this.isConnected = true
        resolve()
      })

      this.socket.on('connect_error', (error) => {
        reject(error)
      })

      this.socket.on('disconnect', () => {
        this.isConnected = false
      })

      this.socket.on('connected', () => {
        // Server connected message
      })

      // 监听响应消息
      this.socket.on('response', (response: ResponseMessage) => {
        const { id, status, data, error, generation_id, execution_id } = response
        const handler = this.requestHandlers.get(id)

        if (handler) {
          // 清除超时定时器
          if (handler.timer) {
            clearTimeout(handler.timer)
          }

          if (status === 'success') {
            // 返回完整响应，包含 data、generation_id、execution_id 等
            // 注意：需要检查 data 是否为 null，因为 typeof null === 'object'
            // generation_id/execution_id 可能放在 data 中，需要兼容处理
            // 注意：如果 data 是数组，不能展开，否则会破坏数组结构
            const resolvedGenerationId = generation_id || (data && typeof data === 'object' && !Array.isArray(data) && data.generation_id)
            const resolvedExecutionId = execution_id || (data && typeof data === 'object' && !Array.isArray(data) && data.execution_id)

            // 直接返回 data，保持原始数据结构（数组或对象）
            handler.resolve({
              data,
              generation_id: resolvedGenerationId,
              execution_id: resolvedExecutionId
            })
          } else {
            handler.reject(new Error(error || 'Unknown error'))
          }

          // 删除处理器
          this.requestHandlers.delete(id)
        }
      })

      // 监听流式进度消息
      this.socket.on('progress', (response: ResponseMessage) => {
        const { id, status, data, error } = response

        // 首先检查是否有对应的流式处理器
        const streamCallback = this.streamHandlers.get(id)
        if (streamCallback) {
          if (status === 'streaming') {
            // 解析 data 字段（JSON 字符串）并传递给回调
            try {
              const parsedData = typeof data === 'string' ? JSON.parse(data) : data
              streamCallback(parsedData)
            } catch (e) {
              // Failed to parse progress data
            }
          } else if (status === 'complete') {
            this.streamHandlers.delete(id)
            streamCallback({ type: 'complete' })
          } else if (status === 'error') {
            this.streamHandlers.delete(id)
            streamCallback({ type: 'error', error })
          }
          return
        }

        // 检查是否有对应的普通请求处理器（支持send()方法的进度回调）
        const requestHandler = this.requestHandlers.get(id)
        if (requestHandler && requestHandler.onProgress) {
          // 解析 data 字段并传递给进度回调
          try {
            const parsedData = typeof data === 'string' ? JSON.parse(data) : data
            requestHandler.onProgress(parsedData)
          } catch (e) {
            // Failed to parse progress data
          }
        }
      })

      // 心跳检测
      this.socket.on('pong', () => {
        // Pong received
      })
    })
  }

  /**
   * 发送请求（双向通信，支持可选的进度回调）
   */
  send(action: string, data: any, timeout?: number, onProgress?: StreamProgressCallback): Promise<any> {
    if (!this.socket || !this.isConnected) {
      return Promise.reject(new Error('WebSocket未连接'))
    }

    return new Promise((resolve, reject) => {
      const requestId = `${action}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`

      // 设置超时
      const timeoutMs = timeout || this.config.timeout
      const timer = setTimeout(() => {
        if (this.requestHandlers.has(requestId)) {
          this.requestHandlers.delete(requestId)
          reject(new Error(`Request timeout: ${action}`))
        }
      }, timeoutMs)

      // 保存处理器（包含可选的进度回调）
      this.requestHandlers.set(requestId, { resolve, reject, timer, onProgress })

      // 发送消息
      this.socket!.emit(action, {
        id: requestId,
        action,
        data,
      } as RequestMessage)
    })
  }

  /**
   * 订阅流式数据
   */
  subscribe(
    action: string,
    data: any,
    onProgress: StreamProgressCallback,
    onComplete?: () => void,
    onError?: (error: Error) => void,
  ): void {
    if (!this.socket || !this.isConnected) {
      onError?.(new Error('WebSocket未连接'))
      return
    }

    const requestId = `${action}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`

    // 保存流式处理器
    const wrappedCallback = (progressData: any) => {
      if (progressData?.type === 'complete') {
        this.streamHandlers.delete(requestId)
        onComplete?.()
      } else {
        onProgress(progressData)
      }
    }

    this.streamHandlers.set(requestId, wrappedCallback)

    // 发送订阅请求
    this.socket.emit(action, {
      id: requestId,
      action,
      data,
    } as RequestMessage)
  }

  /**
   * 发送心跳
   */
  ping(): void {
    if (this.socket && this.isConnected) {
      this.socket.emit('ping')
    }
  }

  /**
   * 断开连接
   */
  disconnect(): void {
    if (this.socket) {
      // 清理所有处理器
      this.requestHandlers.forEach((handler) => {
        if (handler.timer) {
          clearTimeout(handler.timer)
        }
      })
      this.requestHandlers.clear()
      this.streamHandlers.clear()

      this.socket.disconnect()
      this.socket = null
      this.isConnected = false
    }
  }

  /**
   * 获取连接状态
   */
  get connected(): boolean {
    return this.isConnected && this.socket?.connected === true
  }

  /**
   * 获取Socket ID
   */
  get id(): string | undefined {
    return this.socket?.id
  }

  /**
   * 监听事件
   */
  on(event: string, callback: (...args: any[]) => void): void {
    if (this.socket) {
      this.socket.on(event, callback)
    }
  }

  /**
   * 取消监听事件
   */
  off(event: string, callback?: (...args: any[]) => void): void {
    if (this.socket) {
      this.socket.off(event, callback)
    }
  }
}

// 导出单例
export default new WebSocketClient()
