import { ref, computed, onMounted, onUnmounted, type Ref } from 'vue'
import { lang } from '@/main'
import {
  listSpeakingSessionsByConfig,
  generateClassSummary,
  type ClassSessionSummary,
  type ClassSummaryResponse,
} from '@/services/speaking'
import type { ClassStudent, ClassStudentSummary, Locale } from './types'

interface UseClassSummaryOpts {
  configId: Ref<string>
  studentArray: Ref<ClassStudent[]>
  locale: Ref<Locale>
}

/** 把 i18n 模板里的 {key} 替换成实际值 */
function formatTpl(tpl: string, vars: Record<string, string | number>): string {
  return tpl.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? ''))
}

function mergeWithRoster(
  serverSummaries: ClassSessionSummary[],
  roster: ClassStudent[],
): ClassStudentSummary[] {
  const byUser = new Map(serverSummaries.map(s => [s.userId, s]))
  return roster.map(stu => {
    const found = byUser.get(stu.userid)
    if (!found) {
      return {
        userId: stu.userid, name: stu.name,
        status: 'not_started',
        overallScore: null, sessionId: null,
        createdAt: null, completedAt: null,
        rawStatus: null, overallStatus: null,
      }
    }
    const status = found.status === 'completed' ? 'submitted' : 'unsubmitted'
    return {
      userId: stu.userid, name: stu.name,
      status,
      overallScore: found.overallScore,
      sessionId: found.sessionId,
      createdAt: found.createdAt,
      completedAt: found.completedAt,
      rawStatus: found.status,
      overallStatus: found.overallStatus,
    }
  })
}

// 前端 fallback 规则版本(必须与后端 class_summary_rules.py 保持镜像)
function frontendRuleBullet2(summaries: ClassStudentSummary[]): string {
  const submitted = summaries.filter(s => s.status === 'submitted')
  if (submitted.length === 0) return (lang as any).ssSpkWaitingFirst
  const scores = submitted.map(s => s.overallScore).filter((x): x is number => x != null)
  if (!scores.length) return (lang as any).ssSpkWaitingFirst
  const avg = Math.round(scores.reduce((a, b) => a + b, 0) / scores.length)
  const max = Math.max(...scores)
  return formatTpl((lang as any).ssSpkAvgScoreTpl, { avg, max })
}

function frontendRuleBullet3(summaries: ClassStudentSummary[]): string {
  const total = summaries.length
  const submitted = summaries.filter(s => s.status === 'submitted').length
  const unfinished = total - submitted
  const rate = total ? Math.round(submitted / total * 100) : 0
  if (rate === 0)   return (lang as any).ssSpkWaitingStart
  if (rate < 50)    return formatTpl((lang as any).ssSpkRemindUnfinishedTpl, { n: unfinished })
  if (rate < 100)   return (lang as any).ssSpkProgressHalf
  return (lang as any).ssSpkAllDone
}

export function useClassSummary(opts: UseClassSummaryOpts) {
  // ─── list 数据 ─────────────────────────────────────────
  const summaries = ref<ClassStudentSummary[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)
  let fetchToken = 0
  let refetchTimer: number | null = null

  async function fetchClassSummary() {
    if (!opts.configId.value) {
      error.value = 'CONFIG_MISSING'
      summaries.value = []
      return
    }
    if (!opts.studentArray.value.length) return

    const token = ++fetchToken
    loading.value = true
    try {
      const userIds = opts.studentArray.value.map(s => s.userid)
      const data = await listSpeakingSessionsByConfig(opts.configId.value, userIds)
      if (token !== fetchToken) return
      summaries.value = mergeWithRoster(data.summaries, opts.studentArray.value)
      error.value = null
    } catch (e) {
      if (token !== fetchToken) return
      error.value = 'FETCH_FAILED'
    } finally {
      if (token === fetchToken) loading.value = false
    }
  }

  function scheduleRefetch() {
    if (refetchTimer) clearTimeout(refetchTimer)
    refetchTimer = window.setTimeout(fetchClassSummary, 1000)
  }

  // ─── AI 总结(混合模式) ───────────────────────────────
  const aiBackendBullets = ref<[string, string, string] | null>(null)
  const aiLoading = ref(false)
  const aiGeneratedAt = ref<string | null>(null)
  let aiToken = 0

  // bullet 1 永远 live(数字派生)
  const liveBullet1 = computed(() => {
    const total = summaries.value.length
    const done = summaries.value.filter(s => s.status === 'submitted').length
    const rate = total ? Math.round(done / total * 100) : 0
    return formatTpl((lang as any).ssSpkCompletedCountTpl, { done, total, rate })
  })

  // 暴露的 3 条 bullet:第 1 条永远 live,2/3 跟随后端或 fallback
  const aiBullets = computed<[string, string, string]>(() => {
    const b1 = liveBullet1.value
    if (aiBackendBullets.value) {
      return [b1, aiBackendBullets.value[1], aiBackendBullets.value[2]]
    }
    return [b1, frontendRuleBullet2(summaries.value), frontendRuleBullet3(summaries.value)]
  })

  async function refreshAISummary() {
    if (!opts.configId.value) return
    if (!opts.studentArray.value.length) return

    const token = ++aiToken
    aiLoading.value = true
    try {
      const userIds = opts.studentArray.value.map(s => s.userid)
      const data: ClassSummaryResponse = await generateClassSummary(
        opts.configId.value, userIds, opts.locale.value,
      )
      if (token !== aiToken) return
      aiBackendBullets.value = data.bullets
      aiGeneratedAt.value = data.generatedAt
    } catch (e) {
      if (token !== aiToken) return
      // 失败保持上次值;若从未成功,aiBullets 自动用前端 fallback
    } finally {
      if (token === aiToken) aiLoading.value = false
    }
  }

  // ─── 生命周期 ─────────────────────────────────────────
  onMounted(() => {
    fetchClassSummary()
    refreshAISummary()
  })
  onUnmounted(() => {
    if (refetchTimer) clearTimeout(refetchTimer)
    fetchToken++
    aiToken++
  })

  return {
    // list 数据
    summaries, loading, error, fetchClassSummary, scheduleRefetch,
    // AI 总结
    aiBullets, aiLoading, aiGeneratedAt, refreshAISummary,
  }
}
