/**
 * WebSocket连接池管理器 (修复版)
 * 
 * 核心功能：
 * 1. 限制同时存在的WebSocket连接数量（例如20个）
 * 2. 100个token排队创建自己的连接
 * 3. 每个token使用自己的连接（不复用给其他token）
 * 
 * 优势：
 * - 突破浏览器连接数限制（通过排队机制）
 * - 每个token使用自己的连接，避免账号混乱
 * - 内存占用低（最多20个并发连接）
 * - 精确的统计和监控
 * 
 * @version 3.13.3 - 修复连接复用导致的账号混乱问题
 * @date 2025-10-08
 */

// 日志控制辅助函数
const shouldLog = (type) => {
  try {
    const config = JSON.parse(localStorage.getItem('batchTaskLogConfig') || '{}')
    return config[type] === true
  } catch {
    return false
  }
}

export class WebSocketPool {
  constructor(options = {}) {
    // 配置参数
    this.poolSize = options.poolSize || 20  // 连接池大小（同时存在的最大连接数）
    this.reconnectWebSocket = options.reconnectWebSocket  // 连接函数
    this.closeConnection = options.closeConnection  // 关闭连接函数
    this.connectionInterval = options.connectionInterval || 300  // 连接间隔时间（ms）
    this.shouldContinue = options.shouldContinue || (() => true)  // 🔥 检查是否应该继续（用于停止检测）
    
    // 连接存储（每个token有自己的连接）
    this.connections = new Map()  // tokenId -> connection
    this.waitingQueue = []  // 等待创建连接的任务队列
    
    // 状态
    this.activeCount = 0  // 当前正在使用的连接数
    this.isShuttingDown = false  // 是否正在关闭
    this.lastConnectionTime = 0  // 上次建立连接的时间戳
    
    // 统计信息
    this.stats = {
      totalAcquired: 0,      // 总获取次数
      totalReleased: 0,      // 总释放次数
      totalWaiting: 0,       // 总等待次数
      totalCreated: 0,       // 总创建次数
      maxWaitTime: 0,        // 最大等待时间
      avgWaitTime: 0,        // 平均等待时间
      totalWaitTime: 0       // 总等待时间
    }
    
    if (shouldLog('websocket')) {
      console.log(`✨ [连接池v3.13.3] 初始化完成，大小: ${this.poolSize}，连接间隔: ${this.connectionInterval}ms`)
      console.log(`📌 [连接池v3.13.3] 每个token使用自己的连接，不会复用给其他token`)
    }
  }

  /**
   * 获取一个可用的WebSocket连接
   * @param {string} tokenId - Token ID
   * @returns {Promise<Object>} WebSocket客户端
   */
  async acquire(tokenId) {
    if (this.isShuttingDown) {
      throw new Error('连接池正在关闭，无法获取新连接')
    }
    
    const startTime = Date.now()
    
    if (shouldLog('websocket')) {
      console.log(`🎫 [连接池v3.13.3] Token ${tokenId} 请求连接 (活跃: ${this.activeCount}/${this.poolSize}, 等待: ${this.waitingQueue.length})`)
    }
    
    return new Promise((resolve, reject) => {
      // 尝试获取连接的函数
      const tryAcquire = async () => {
        try {
          // 🔹 检查此token是否已经有连接
          const existing = this.connections.get(tokenId)
          if (existing && existing.status === 'connected' && existing.client) {
            const waitTime = Date.now() - startTime
            if (shouldLog('websocket')) {
              console.log(`♻️ [连接池v3.13.3] Token ${tokenId} 使用已有连接 (等待 ${waitTime}ms)`)
            }
            this.updateStats('acquired', waitTime, false)
            return existing.client
          }
          
          // 🔹 检查是否达到上限
          if (this.connections.size >= this.poolSize) {
            // 达到上限，需要等待其他token释放
            if (shouldLog('websocket')) {
              console.log(`⏳ [连接池v3.13.3] 已达上限(${this.connections.size}/${this.poolSize})，Token ${tokenId} 需要等待`)
            }
            return null
          }
          
          // 🔹 创建新连接
          if (shouldLog('websocket')) {
            console.log(`🆕 [连接池v3.13.3] 为 Token ${tokenId} 创建新连接 (${this.connections.size + 1}/${this.poolSize})`)
          }
          
          // ⏱️ 连接间隔控制：避免同时创建太多连接
          const now = Date.now()
          const timeSinceLastConnection = now - this.lastConnectionTime
          if (timeSinceLastConnection < this.connectionInterval) {
            const waitTime = this.connectionInterval - timeSinceLastConnection
            if (shouldLog('websocket')) {
              console.log(`⏱️ [连接池v3.13.3] 等待 ${waitTime}ms 后创建连接（间隔: ${this.connectionInterval}ms）`)
            }
            await new Promise(resolve => setTimeout(resolve, waitTime))
            
            // 🔥 等待后检查是否应该继续（可能在等待期间被停止）
            if (!this.shouldContinue()) {
              if (shouldLog('websocket')) {
                console.log(`⚠️ [连接池v3.13.3] Token ${tokenId} 等待期间任务已停止，取消创建连接`)
              }
              throw new Error('任务已停止')
            }
          }
          this.lastConnectionTime = Date.now()
          
          // 🔥 创建连接前再次检查
          if (!this.shouldContinue()) {
            if (shouldLog('websocket')) {
              console.log(`⚠️ [连接池v3.13.3] Token ${tokenId} 任务已停止，取消创建连接`)
            }
            throw new Error('任务已停止')
          }
          
          const client = await this.reconnectWebSocket(tokenId)
          
          if (!client) {
            throw new Error('连接创建失败：返回null')
          }
          
          // 创建连接记录
          const connection = {
            tokenId: tokenId,
            client: client,
            status: 'connected',
            createdTime: Date.now(),
            lastUsedTime: Date.now()
          }
          
          this.connections.set(tokenId, connection)
          this.activeCount++
          
          const waitTime = Date.now() - startTime
          this.updateStats('acquired', waitTime, false)
          
          if (shouldLog('websocket')) {
            console.log(`✅ [连接池v3.13.3] Token ${tokenId} 创建连接成功 (等待 ${waitTime}ms)`)
          }
          return client
          
        } catch (error) {
          if (shouldLog('websocket')) {
            console.error(`❌ [连接池v3.13.3] Token ${tokenId} 获取连接失败:`, error)
          }
          throw error
        }
      }
      
      // 立即尝试获取
      tryAcquire()
        .then(client => {
          if (client) {
            // 成功获取，直接返回
            resolve(client)
          } else {
            // 需要等待，加入队列
            if (shouldLog('websocket')) {
              console.log(`⏳ [连接池v3.13.3] Token ${tokenId} 加入等待队列 (队列长度: ${this.waitingQueue.length + 1})`)
            }
            
            this.waitingQueue.push({
              tokenId,
              resolve,
              reject,
              startTime,
              tryAcquire
            })
            
            this.stats.totalWaiting++
          }
        })
        .catch(error => {
          reject(error)
        })
    })
  }

  /**
   * 释放连接（关闭此token的连接，并允许等待队列中的token创建连接）
   * @param {string} tokenId - Token ID
   */
  async release(tokenId) {
    const connection = this.connections.get(tokenId)
    
    if (!connection) {
      if (shouldLog('websocket')) {
        console.warn(`⚠️ [连接池v3.13.3] Token ${tokenId} 的连接不存在`)
      }
      return
    }
    
    if (shouldLog('websocket')) {
      console.log(`🔓 [连接池v3.13.3] Token ${tokenId} 释放连接 (活跃: ${this.activeCount - 1}/${this.poolSize}, 等待: ${this.waitingQueue.length})`)
    }
    
    // 🔹 关闭此token的连接
    try {
      if (this.closeConnection) {
        await this.closeConnection(tokenId)
      }
    } catch (error) {
      if (shouldLog('websocket')) {
        console.warn(`⚠️ [连接池v3.13.3] 关闭连接 ${tokenId} 失败:`, error)
      }
    }
    
    // 🔹 从连接池移除
    this.connections.delete(tokenId)
    this.activeCount--
    this.updateStats('released')
    
    // 🔹 如果有等待的token，允许它创建连接
    if (this.waitingQueue.length > 0) {
      const waiting = this.waitingQueue.shift()
      
      if (shouldLog('websocket')) {
        console.log(`🔄 [连接池v3.13.3] 释放名额，允许 Token ${waiting.tokenId} 创建连接`)
      }
      
      // 让等待的token尝试创建连接
      waiting.tryAcquire()
        .then(client => {
          if (client) {
            waiting.resolve(client)
          } else {
            // 如果还是无法创建（理论上不应该发生），重新加入队列
            if (shouldLog('websocket')) {
              console.warn(`⚠️ [连接池v3.13.3] Token ${waiting.tokenId} 仍无法创建连接，重新加入队列`)
            }
            this.waitingQueue.unshift(waiting)
          }
        })
        .catch(error => {
          waiting.reject(error)
        })
    }
  }

  /**
   * 清理所有连接
   */
  async cleanup() {
    this.isShuttingDown = true
    
    if (shouldLog('websocket')) {
      console.log(`🧹 [连接池] 开始清理，共 ${this.connections.size} 个连接`)
    }
    
    // 拒绝所有等待的任务
    while (this.waitingQueue.length > 0) {
      const waiting = this.waitingQueue.shift()
      waiting.reject(new Error('连接池已清理'))
    }
    
    // 关闭所有连接
    const closePromises = []
    for (const [tokenId, connection] of this.connections.entries()) {
      try {
        if (this.closeConnection) {
          closePromises.push(
            this.closeConnection(tokenId).catch(err => {
              if (shouldLog('websocket')) {
                console.warn(`⚠️ [连接池] 关闭连接 ${tokenId} 失败:`, err)
              }
            })
          )
        }
      } catch (error) {
        if (shouldLog('websocket')) {
          console.warn(`⚠️ [连接池] 关闭连接 ${tokenId} 失败:`, error)
        }
      }
    }
    
    // 等待所有连接关闭
    await Promise.all(closePromises)
    
    // 清空数据
    this.connections.clear()
    this.availableConnections = []
    this.activeCount = 0
    this.isShuttingDown = false
    
    if (shouldLog('websocket')) {
      console.log(`✅ [连接池] 清理完成`)
    }
  }

  /**
   * 更新统计信息
   */
  updateStats(type, waitTime = 0, isExisting = false) {
    if (type === 'acquired') {
      this.stats.totalAcquired++
      
      if (!isExisting) {
        this.stats.totalCreated++
      }
      
      // 更新等待时间统计
      this.stats.totalWaitTime += waitTime
      
      if (waitTime > this.stats.maxWaitTime) {
        this.stats.maxWaitTime = waitTime
      }
      
      this.stats.avgWaitTime = this.stats.totalWaitTime / this.stats.totalAcquired
      
    } else if (type === 'released') {
      this.stats.totalReleased++
    }
  }

  /**
   * 获取连接池状态
   */
  getStatus() {
    return {
      poolSize: this.poolSize,
      totalConnections: this.connections.size,
      activeConnections: this.activeCount,
      waitingTasks: this.waitingQueue.length,
      stats: {
        ...this.stats,
        maxWaitTime: `${this.stats.maxWaitTime.toFixed(0)}ms`,
        avgWaitTime: `${this.stats.avgWaitTime.toFixed(0)}ms`
      }
    }
  }

  /**
   * 打印连接池状态
   */
  printStatus() {
    if (!shouldLog('websocket')) return
    
    const status = this.getStatus()
    console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 [连接池状态 v3.13.3]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📏 连接池大小: ${status.poolSize} (同时存在的最大连接数)
📦 当前连接数: ${status.totalConnections}
🔥 活跃连接: ${status.activeConnections}
⏳ 等待任务: ${status.waitingTasks}

📈 统计信息:
   总获取次数: ${status.stats.totalAcquired}
   总释放次数: ${status.stats.totalReleased}
   总等待次数: ${status.stats.totalWaiting}
   总创建次数: ${status.stats.totalCreated}
   最大等待时间: ${status.stats.maxWaitTime}
   平均等待时间: ${status.stats.avgWaitTime}

💡 说明: 每个token使用自己的连接，不会复用给其他token
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    `)
  }

  /**
   * 获取连接详细信息
   */
  getConnectionDetails() {
    const details = []
    
    for (const [tokenId, connection] of this.connections.entries()) {
      details.push({
        tokenId,
        status: connection.status,
        age: `${((Date.now() - connection.createdTime) / 1000).toFixed(0)}s`,
        lastUsed: connection.lastUsedTime 
          ? `${((Date.now() - connection.lastUsedTime) / 1000).toFixed(0)}s前`
          : '从未使用'
      })
    }
    
    return details
  }

  /**
   * 打印连接详细信息
   */
  printConnectionDetails() {
    if (!shouldLog('websocket')) return
    
    const details = this.getConnectionDetails()
    
    console.log(`
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔍 [连接详情 v3.13.3] 共 ${details.length} 个连接
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`)
    
    details.forEach((conn, index) => {
      console.log(`${index + 1}. Token ${conn.tokenId}:
   状态: ${conn.status}
   连接时长: ${conn.age}
   最后使用: ${conn.lastUsed}
`)
    })
    
    console.log('💡 每个连接专属于对应的token，不会复用给其他token')
    console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
  }
}

