import { ref, watch, onMounted, onUnmounted, type Ref } from 'vue'
import {
  listArticleSessionsByConfig,
  generateArticleClassSummary,
} from '@/views/Editor/EnglishSpeaking/services/articleReading'
import type { ArticleClassSessionSummary } from '@/types/articleReading'
import type { ArticleClassStudent } from './types'

const REFETCH_DEBOUNCE_MS = 800
const AUTO_SUMMARY_INTERVAL_MS = 60_000

/**
 * 班级状态指纹。与后端缓存键同口径（article_service.py `_summaries_hash` 取的正是
 * userId / status / overallScore），多带一个 configId —— 老师换配置时指纹自动失效。
 * 指纹相同 = 没有新东西可总结，定时刷新一律跳过（spec §8.2）。
 */
export function classStateKey(configId: string, rows: ArticleClassSessionSummary[]): string {
  const parts = rows
    .map(row => `${row.userId}:${row.status}:${row.overallScore ?? ''}`)
    .sort()
  return `${configId}|${parts.join(',')}`
}

export function useArticleClassSummary(options: {
  configId: Ref<string>
  studentArray: Ref<ArticleClassStudent[]>
}) {
  const summaries = ref<ArticleClassSessionSummary[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)

  const aiSummary = ref('')
  const aiLoading = ref(false)
  const aiError = ref<string | null>(null)
  const aiGeneratedAt = ref<string | null>(null)
  const aiFromCache = ref(false)
  const aiLlmStatus = ref<'ok' | 'fallback' | null>(null)

  // 单调递增令牌：慢响应回来时若已不是最新请求就丢弃
  let listToken = 0
  let summaryToken = 0
  let refetchTimer: ReturnType<typeof setTimeout> | null = null
  let autoTimer: ReturnType<typeof setInterval> | null = null
  // 上次成功生成总结时的班级状态指纹；失败不记，于是下次 tick 自动重试
  let lastSummarizedKey: string | null = null

  function currentUsers() {
    return options.studentArray.value
      .filter(student => student.userid)
      .map(student => ({ userId: student.userid, name: student.name }))
  }

  async function fetchClassSummary() {
    const configId = options.configId.value
    const users = currentUsers()
    if (!configId || users.length === 0) {
      summaries.value = []
      return
    }
    const token = ++listToken
    loading.value = true
    error.value = null
    try {
      const res = await listArticleSessionsByConfig(configId, users)
      if (token !== listToken) return
      summaries.value = res.summaries
    } catch (cause) {
      if (token !== listToken) return
      error.value = 'FETCH_FAILED'
      console.error('[article-reading] class list failed:', cause)
    } finally {
      if (token === listToken) loading.value = false
    }
  }

  /** WebSocket 进度事件会连发，去抖后只打一次接口 */
  function scheduleRefetch() {
    if (refetchTimer) clearTimeout(refetchTimer)
    refetchTimer = setTimeout(() => {
      refetchTimer = null
      void fetchClassSummary()
    }, REFETCH_DEBOUNCE_MS)
  }

  async function refreshAISummary() {
    const configId = options.configId.value
    const users = currentUsers()
    if (!configId || users.length === 0) return
    // 发请求前抓当时的指纹：成功才记下，于是手动点按钮同样会让紧接着的 tick 变成 no-op
    const requestedKey = classStateKey(configId, summaries.value)
    const token = ++summaryToken
    aiLoading.value = true
    aiError.value = null
    try {
      const res = await generateArticleClassSummary(configId, users)
      if (token !== summaryToken) return
      aiSummary.value = res.summary
      aiGeneratedAt.value = res.generatedAt
      aiFromCache.value = res.fromCache
      aiLlmStatus.value = res.llmStatus
      lastSummarizedKey = requestedKey
    } catch (cause) {
      if (token !== summaryToken) return
      aiError.value = 'SUMMARY_FAILED'
      console.error('[article-reading] class summary failed:', cause)
    } finally {
      if (token === summaryToken) aiLoading.value = false
    }
  }

  /** 定时刷新的闸门（spec §8.2）：只在真有新东西可总结时才调 LLM */
  function maybeAutoSummary() {
    if (aiLoading.value) return
    // 老师切走的分页不烧；切回来时由 visibilitychange 立刻补一次
    if (typeof document !== 'undefined' && document.hidden) return
    const configId = options.configId.value
    if (!configId) return
    // 进行中的学生也要 update（用户 2026-07-26 定，放宽自「必须有人完成」）。
    // 只有全班一人都没开始时才跳过 —— 那种情况总结栏只能写「未开始 N 人」，零信息量
    if (!summaries.value.some(row => row.status === 'completed' || row.status === 'reading')) return
    if (classStateKey(configId, summaries.value) === lastSummarizedKey) return
    void refreshAISummary()
  }

  /** 先列表后总结：重拉列表顺带修掉「WS 广播早于分数落地」的陈旧 */
  async function tick() {
    await fetchClassSummary()
    maybeAutoSummary()
  }

  function onVisibilityChange() {
    if (!document.hidden) maybeAutoSummary()
  }

  watch(
    [options.configId, options.studentArray],
    () => { void tick() },
    { immediate: true, deep: true },
  )

  onMounted(() => {
    autoTimer = setInterval(() => void tick(), AUTO_SUMMARY_INTERVAL_MS)
    document.addEventListener('visibilitychange', onVisibilityChange)
  })

  onUnmounted(() => {
    if (refetchTimer) clearTimeout(refetchTimer)
    refetchTimer = null
    if (autoTimer) clearInterval(autoTimer)
    autoTimer = null
    document.removeEventListener('visibilitychange', onVisibilityChange)
    // 令牌前进，卸载后回来的响应一律作废
    listToken += 1
    summaryToken += 1
  })

  return {
    summaries,
    loading,
    error,
    fetchClassSummary,
    scheduleRefetch,
    aiSummary,
    aiLoading,
    aiError,
    aiGeneratedAt,
    aiFromCache,
    aiLlmStatus,
    refreshAISummary,
  }
}
