/**
 * Admin 端 WebSocket 客户端封装
 *
 * 协议约定（与服务端对应）：
 *   发送 → JSON.stringify({ event: string, data: any })
 *   接收 ← JSON.stringify({ event: string, data: any })
 *
 * 用法：
 *   import { connectSocket, getSocket } from './socket';
 *   connectSocket();  // 在应用初始化时调用
 */

// ─── 配置 ──────────────────────────────────────────────────────────────────
/**
 * 线上部署说明：
 * - nginx: https://paopao.wxl66.cn/api/* → 转发到 http://localhost:3000/*
 *   注意：nginx 保留 /api 前缀
 * - 后端 WebSocket 路径: /ws
 *
 * 所以 WebSocket 连接地址为: wss://paopao.wxl66.cn/api/ws
 */

// 环境切换：true=本地开发，false=线上生产
const isDev = import.meta.env.DEV || window.location.hostname === 'localhost'

// WebSocket URL
const WS_URL = isDev
  ? 'ws://localhost:3000/ws'              // 开发环境
  : 'wss://paopao.wxl66.cn/api/ws';       // 生产环境：/api(nginx入口) + /ws(后端路由)

const RECONNECT_DELAY = 3000
const MAX_RECONNECT_COUNT = 5

// ─── Socket 实例 ───────────────────────────────────────────────────────────

class AdminSocket {
  constructor() {
    this._ws = null
    this._connected = false
    this._connecting = false
    this._url = WS_URL
    this._reconnectCount = 0
    this._reconnectTimer = null
    this._queue = []
    this._listeners = {}
  }

  /**
   * 连接到服务器
   * @param {string} [url] 可选，自定义 WebSocket 地址
   */
  connect(url) {
    if (url) this._url = url
    if (this._connected || this._connecting) return
    this._doConnect()
  }

  /**
   * 发送自定义事件
   * @param {string} event 事件名
   * @param {*} data 携带的数据
   */
  emit(event, data) {
    const raw = JSON.stringify({ event, data })
    if (!this._connected) {
      this._queue.push(raw)
      return
    }
    this._sendRaw(raw)
  }

  /**
   * 监听服务端推送的事件
   * @param {string} event 事件名
   * @param {Function} handler 回调
   */
  on(event, handler) {
    if (!this._listeners[event]) this._listeners[event] = []
    this._listeners[event].push(handler)
  }

  /**
   * 移除事件监听
   * @param {string} event
   * @param {Function} [handler] 不传则移除该事件所有监听
   */
  off(event, handler) {
    if (!this._listeners[event]) return
    if (!handler) {
      delete this._listeners[event]
    } else {
      this._listeners[event] = this._listeners[event].filter(fn => fn !== handler)
    }
  }

  /**
   * 主动断开连接
   */
  disconnect() {
    this._stopReconnect()
    this._reconnectCount = MAX_RECONNECT_COUNT
    if (this._ws) {
      try { this._ws.close() } catch (_) {}
    }
    this._ws = null
    this._connected = false
    this._connecting = false
  }

  /**
   * 获取连接状态
   */
  get connected() {
    return this._connected
  }

  // ─── 内部实现 ─────────────────────────────────────────────────────────────

  _doConnect() {
    this._connecting = true

    const ws = new WebSocket(this._url)

    ws.addEventListener('open', () => {
      this._ws = ws
      this._connected = true
      this._connecting = false
      this._reconnectCount = 0
      console.log('[AdminSocket] 已连接')

      // 发送积压的消息
      while (this._queue.length > 0) {
        this._sendRaw(this._queue.shift())
      }
    })

    ws.addEventListener('message', (evt) => {
      try {
        const msg = JSON.parse(evt.data)
        const handlers = this._listeners[msg.event]
        if (handlers) {
          handlers.forEach(fn => {
            try { fn(msg.data) } catch (_) {}
          })
        }
      } catch (_) {}
    })

    ws.addEventListener('close', () => {
      this._onDisconnected()
    })

    ws.addEventListener('error', (err) => {
      console.error('[AdminSocket] 连接错误:', err)
      this._onDisconnected()
    })
  }

  _onDisconnected() {
    this._connected = false
    this._connecting = false
    this._ws = null
    this._scheduleReconnect()
  }

  _scheduleReconnect() {
    if (this._reconnectCount >= MAX_RECONNECT_COUNT) return
    this._stopReconnect()
    this._reconnectTimer = setTimeout(() => {
      this._reconnectCount++
      console.log(`[AdminSocket] 第 ${this._reconnectCount} 次重连...`)
      this._doConnect()
    }, RECONNECT_DELAY)
  }

  _stopReconnect() {
    if (this._reconnectTimer) {
      clearTimeout(this._reconnectTimer)
      this._reconnectTimer = null
    }
  }

  _sendRaw(raw) {
    if (!this._connected || !this._ws) return
    try {
      this._ws.send(raw)
    } catch (_) {}
  }
}

// 单例实例
const adminSocket = new AdminSocket()

// ─── 导出兼容接口 ──────────────────────────────────────────────────────────

export function connectSocket(url) {
  adminSocket.connect(url)
  return adminSocket
}

export function getSocket() {
  return adminSocket
}

export function disconnectSocket() {
  adminSocket.disconnect()
}

export function onRoomState(cb) {
  adminSocket.on('room:state', cb)
}

export function offRoomState(cb) {
  adminSocket.off('room:state', cb)
}

export function onScreenRoomChanged(cb) {
  adminSocket.on('screen:roomChanged', cb)
}

export function offScreenRoomChanged(cb) {
  adminSocket.off('screen:roomChanged', cb)
}

export default adminSocket
