/**
 * 创作进度追踪器
 *
 * 三级通信策略：
 *   Level 1: WebSocket (STOMP) — 首选，实时推送，自动重连
 *   Level 2: B2 HTTP 轮询 — WebSocket 断连期间临时补位
 *   Level 3: Redis 进度数据 — 断连期间进度不丢失，重连后立刻获取最新状态
 *
 * 使用示例：
 *   const tracker = new CreationProgressTracker({
 *     serverUrl: 'https://your-server.com',
 *     orgId: 'ORG001',
 *     appKey: 'ORG001',
 *     appSecret: 'your-secret',
 *     workId: '2034987994917769216',
 *     onProgress: (progress, message) => {
 *       console.log(`${progress}% - ${message}`)
 *     },
 *     onComplete: (result) => {
 *       // result.status === 'COMPLETED' => result.pageList 包含完整作品
 *       // result.status === 'FAILED' => result.failReason 包含失败原因
 *     },
 *     onError: (error) => {
 *       console.error('Tracker error:', error)
 *     }
 *   })
 *   tracker.start()
 *
 *   // 用户退出页面时
 *   tracker.stop()
 */

import SockJS from 'sockjs-client/dist/sockjs.min.js'
import { Client } from '@stomp/stompjs'
import { generateSignHeaders } from './HmacSigner.js'

export default class CreationProgressTracker {
  /**
   * @param {Object} options
   * @param {string} options.serverUrl - 服务器地址 (如 https://your-server.com)
   * @param {string} options.orgId - 机构ID
   * @param {string} options.appKey - HMAC 签名 App Key (通常等于 orgId)
   * @param {string} options.appSecret - HMAC 签名密钥
   * @param {string} options.workId - 作品ID
   * @param {Function} options.onProgress - 进度回调 (progress: number, message: string)
   * @param {Function} options.onComplete - 完成回调 (result: CreationResultVO)
   * @param {Function} [options.onError] - 错误回调 (error: Error)
   * @param {number} [options.pollInterval=5000] - B2 轮询间隔 (ms)
   * @param {number} [options.reconnectDelay=3000] - WebSocket 重连延迟 (ms)
   * @param {number} [options.maxPollTimeout=600000] - 最大轮询时间 (ms)，默认10分钟
   */
  constructor(options) {
    this.serverUrl = options.serverUrl
    this.orgId = options.orgId
    this.appKey = options.appKey
    this.appSecret = options.appSecret
    this.workId = options.workId
    this.onProgress = options.onProgress || (() => {})
    this.onComplete = options.onComplete || (() => {})
    this.onError = options.onError || (() => {})
    this.pollInterval = options.pollInterval || 5000
    this.reconnectDelay = options.reconnectDelay || 3000
    this.maxPollTimeout = options.maxPollTimeout || 600000

    this._stompClient = null
    this._pollTimer = null
    this._wsConnected = false
    this._stopped = false
    this._startTime = 0
    this._lastProgress = -1
  }

  /**
   * 启动进度追踪
   */
  start() {
    this._stopped = false
    this._startTime = Date.now()

    // 尝试 WebSocket 连接
    this._connectWebSocket()

    // 安全网：5秒内 WS 未连上则启动轮询
    setTimeout(() => {
      if (!this._wsConnected && !this._stopped) {
        this._startPolling()
      }
    }, 5000)
  }

  /**
   * 停止追踪（用户离开页面时调用）
   */
  stop() {
    this._stopped = true
    this._stopPolling()
    this._disconnectWebSocket()
  }

  // ─── WebSocket (Level 1) ──────────────────────────────────────────

  _connectWebSocket() {
    if (this._stopped) return

    try {
      const wsUrl = `${this.serverUrl}/ws?orgId=${this.orgId}`

      this._stompClient = new Client({
        webSocketFactory: () => new SockJS(wsUrl),
        reconnectDelay: this.reconnectDelay,
        heartbeatIncoming: 10000,
        heartbeatOutgoing: 10000,

        onConnect: () => {
          this._wsConnected = true
          this._stopPolling()  // WS 连上了，停止轮询

          // 订阅进度 topic
          this._stompClient.subscribe(
            `/topic/progress/${this.workId}`,
            (msg) => {
              try {
                const data = JSON.parse(msg.body)
                this._handleProgressData(data)
              } catch (e) {
                // ignore parse errors
              }
            }
          )

          // 重连成功后，立即查一次 B2 获取断连期间可能错过的最终状态
          this._pollOnce()
        },

        onDisconnect: () => {
          this._wsConnected = false
          if (!this._stopped) {
            this._startPolling()  // WS 断了，启动轮询补位
          }
        },

        onStompError: (frame) => {
          this._wsConnected = false
          if (!this._stopped) {
            this._startPolling()
          }
        },

        onWebSocketError: () => {
          this._wsConnected = false
          if (!this._stopped) {
            this._startPolling()
          }
        }
      })

      this._stompClient.activate()
    } catch (e) {
      // WebSocket 不可用（如被防火墙阻断），降级为纯轮询
      this._startPolling()
    }
  }

  _disconnectWebSocket() {
    if (this._stompClient) {
      try {
        this._stompClient.deactivate()
      } catch (e) {
        // ignore
      }
      this._stompClient = null
    }
    this._wsConnected = false
  }

  // ─── B2 HTTP 轮询 (Level 2) ───────────────────────────────────────

  _startPolling() {
    if (this._pollTimer || this._stopped) return
    this._pollTimer = setInterval(() => this._pollOnce(), this.pollInterval)
  }

  _stopPolling() {
    if (this._pollTimer) {
      clearInterval(this._pollTimer)
      this._pollTimer = null
    }
  }

  async _pollOnce() {
    if (this._stopped) return

    // 超时保护
    if (Date.now() - this._startTime > this.maxPollTimeout) {
      this.stop()
      this.onError(new Error('进度查询超时'))
      return
    }

    try {
      const queryParams = { orgId: this.orgId }
      const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams)

      const res = await fetch(
        `${this.serverUrl}/api/v1/query/work/${this.workId}?orgId=${this.orgId}`,
        { headers: { ...signHeaders, 'Content-Type': 'application/json' } }
      )

      if (!res.ok) return

      const json = await res.json()
      if (json.code !== 200 || !json.data) return

      const data = json.data

      // 推送进度
      if (data.progress != null && data.progress !== this._lastProgress) {
        this._handleProgressData({
          progress: data.progress,
          message: data.progressMessage || ''
        })
      }

      // 检查是否终态
      if (data.status === 'COMPLETED' || data.status === 'FAILED') {
        this.stop()
        this.onComplete(data)
      }
    } catch (e) {
      // 网络错误，不中断轮询
    }
  }

  // ─── 进度处理 ─────────────────────────────────────────────────────

  _handleProgressData(data) {
    if (this._stopped) return

    const progress = data.progress != null ? data.progress : 0
    const message = data.message || ''

    // 去重：相同进度不重复回调
    if (progress === this._lastProgress) return
    this._lastProgress = progress

    // 回调
    this.onProgress(progress, message)

    // 终态检测（WebSocket 推送的 progress=100 或 -1）
    if (progress === 100) {
      // 完成，再查一次 B2 获取完整数据（含 pageList）
      setTimeout(() => this._fetchFinalResult(), 1000)
    } else if (progress === -1) {
      // 失败，查一次 B2 获取 failReason
      setTimeout(() => this._fetchFinalResult(), 1000)
    }
  }

  async _fetchFinalResult() {
    try {
      const queryParams = { orgId: this.orgId }
      const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams)

      const res = await fetch(
        `${this.serverUrl}/api/v1/query/work/${this.workId}?orgId=${this.orgId}`,
        { headers: { ...signHeaders, 'Content-Type': 'application/json' } }
      )

      if (!res.ok) return

      const json = await res.json()
      if (json.code === 200 && json.data) {
        this.stop()
        this.onComplete(json.data)
      }
    } catch (e) {
      this.onError(e)
    }
  }
}
