<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { Download, Search } from '@element-plus/icons-vue'
import * as echarts from 'echarts/core'
import { BarChart, LineChart, PieChart } from 'echarts/charts'
import { GridComponent, LegendComponent, TitleComponent, TooltipComponent } from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import { downloadApiFile } from '../api/excel'
import http from '../api/http'
import { academicTermLabel, academicTermOptionClass, defaultAcademicTermId } from '../utils/academicTerms'

echarts.use([BarChart, LineChart, PieChart, TitleComponent, TooltipComponent, LegendComponent, GridComponent, CanvasRenderer])

// ── Reference data ──
const terms = ref<any[]>([])
const colleges = ref<any[]>([])
const courseCategories = ref<any[]>([])

// ── Active tab ──
const activeTab = ref('students')

// ── Chart instance management ──
const chartMap = new Map<string, echarts.ECharts>()
function setChart(key: string, inst: echarts.ECharts) {
  chartMap.get(key)?.dispose()
  chartMap.set(key, inst)
}
function disposeCharts(prefix: string) {
  for (const [k, v] of chartMap) { if (k.startsWith(prefix)) { v.dispose(); chartMap.delete(k) } }
}

onUnmounted(() => { for (const v of chartMap.values()) v.dispose(); chartMap.clear() })

window.addEventListener('resize', () => { for (const v of chartMap.values()) v.resize() })

// ── Shared filter state ──
const globalTermId = ref<string>()

// ── 1. Students ──
const studentFilter = reactive({ collegeId: undefined as string | undefined, majorId: undefined as string | undefined, classId: undefined as string | undefined, grade: undefined as number | undefined })
const studentMajors = ref<any[]>([]); const studentClasses = ref<any[]>([])
const studentStats = ref<any>(null); const studentLoading = ref(false)

async function loadStudentStats() {
  studentLoading.value = true
  try {
    const params: any = {}
    if (globalTermId.value) params.academicTermId = globalTermId.value
    if (studentFilter.collegeId) params.collegeId = studentFilter.collegeId
    if (studentFilter.majorId) params.majorId = studentFilter.majorId
    if (studentFilter.classId) params.classId = studentFilter.classId
    if (studentFilter.grade) params.grade = studentFilter.grade
    const { data } = await http.get('/statistics/students/summary', { params })
    studentStats.value = data
    await nextTick()
    renderStudentCharts(data)
  } finally { studentLoading.value = false }
}

function renderStudentCharts(d: any) {
  const key = 'student-'
  disposeCharts(key)
  renderPie(key + 'college', 'student-college-chart', d.byCollege?.map((x: any) => ({ name: x.collegeName, value: x.count })) ?? [], '各学院学生分布')
  renderPie(key + 'gender', 'student-gender-chart', d.byGender?.map((x: any) => ({ name: x.gender === 'Male' ? '男' : x.gender === 'Female' ? '女' : x.gender, value: x.count })) ?? [], '性别分布')
  renderBar(key + 'status', 'student-status-chart', d.byStatus?.map((x: any) => x.status) ?? [], d.byStatus?.map((x: any) => x.count) ?? [], '学籍状态')
  renderLine(key + 'trend', 'student-trend-chart', d.enrollmentTrend?.map((x: any) => `${x.year}年`) ?? [], d.enrollmentTrend?.map((x: any) => x.count) ?? [], '历年招生趋势')
}

async function loadStudentMajors() {
  if (studentFilter.collegeId) {
    const { data } = await http.get('/base-data/majors')
    studentMajors.value = (data as any[]).filter((m: any) => m.collegeId === studentFilter.collegeId)
  } else { studentMajors.value = [] }
}
async function onStudentCollegeChange() {
  studentFilter.majorId = undefined; studentFilter.classId = undefined; studentClasses.value = []
  await loadStudentMajors()
}
async function onStudentMajorChange() {
  studentFilter.classId = undefined; studentClasses.value = []
  if (studentFilter.majorId) {
    const { data } = await http.get('/base-data/classes')
    studentClasses.value = (data as any[]).filter((c: any) => c.majorId === studentFilter.majorId)
  }
}

// ── 2. Courses ──
const courseFilter = reactive({ collegeId: undefined as string | undefined, categoryId: undefined as string | undefined, nature: undefined as string | undefined })
const courseStats = ref<any>(null); const courseLoading = ref(false)

async function loadCourseStats() {
  courseLoading.value = true
  try {
    const params: any = {}
    if (courseFilter.collegeId) params.collegeId = courseFilter.collegeId
    if (courseFilter.categoryId) params.categoryId = courseFilter.categoryId
    if (courseFilter.nature) params.nature = courseFilter.nature
    const { data } = await http.get('/statistics/courses/summary', { params })
    courseStats.value = data
    await nextTick()
    renderCourseCharts(data)
  } finally { courseLoading.value = false }
}

function renderCourseCharts(d: any) {
  const key = 'course-'
  disposeCharts(key)
  renderBar(key + 'college', 'course-college-chart', d.byCollege?.map((x: any) => x.collegeName) ?? [], d.byCollege?.map((x: any) => x.count) ?? [], '各学院课程数')
  renderPie(key + 'nature', 'course-nature-chart', d.byNature?.map((x: any) => ({ name: x.natureLabel, value: x.count })) ?? [], '课程性质')
  renderBar(key + 'credit', 'course-credit-chart', d.creditDistribution?.map((x: any) => x.range) ?? [], d.creditDistribution?.map((x: any) => x.count) ?? [], '学分分布')
  renderPie(key + 'assessment', 'course-assessment-chart', d.byAssessment?.map((x: any) => ({ name: x.label, value: x.count })) ?? [], '考核方式')
}

// ── 3. Grades ──
const gradeFilter = reactive({ collegeId: undefined as string | undefined, majorId: undefined as string | undefined, classId: undefined as string | undefined, courseId: undefined as string | undefined })
const gradeMajors = ref<any[]>([]); const gradeClasses = ref<any[]>([])
const gradeStats = ref<any>(null); const gradeLoading = ref(false)

async function loadGradeStats() {
  gradeLoading.value = true
  try {
    const params: any = {}
    if (globalTermId.value) params.academicTermId = globalTermId.value
    if (gradeFilter.collegeId) params.collegeId = gradeFilter.collegeId
    if (gradeFilter.majorId) params.majorId = gradeFilter.majorId
    if (gradeFilter.classId) params.classId = gradeFilter.classId
    if (gradeFilter.courseId) params.courseId = gradeFilter.courseId
    const { data } = await http.get('/statistics/grades/summary', { params })
    gradeStats.value = data
    await nextTick()
    renderGradeCharts(data)
  } finally { gradeLoading.value = false }
}

function renderGradeCharts(d: any) {
  const key = 'grade-'
  disposeCharts(key)
  renderBar(key + 'score', 'grade-score-chart', d.scoreDistribution?.map((x: any) => x.label) ?? [], d.scoreDistribution?.map((x: any) => x.count) ?? [], '分数段分布')
  renderBar(key + 'gpa', 'grade-gpa-chart', d.gpaDistribution?.map((x: any) => x.range) ?? [], d.gpaDistribution?.map((x: any) => x.count) ?? [], 'GPA分布')
  const prbc = d.passRateByCollege ?? []
  renderBarHorizontal(key + 'pr-college', 'grade-pr-college-chart', prbc.map((x: any) => x.collegeName), prbc.map((x: any) => +(x.passRate * 100).toFixed(1)), '各学院通过率(%)')
  const abc = (d.averageByCourse ?? []).slice(0, 15)
  renderBarHorizontal(key + 'avg-course', 'grade-avg-course-chart', abc.map((x: any) => x.courseName), abc.map((x: any) => x.averageScore), '课程均分Top15')
}

async function onGradeCollegeChange() {
  gradeFilter.majorId = undefined; gradeFilter.classId = undefined; gradeMajors.value = []; gradeClasses.value = []
  if (gradeFilter.collegeId) {
    const { data } = await http.get('/base-data/majors')
    gradeMajors.value = (data as any[]).filter((m: any) => m.collegeId === gradeFilter.collegeId)
  }
}
async function onGradeMajorChange() {
  gradeFilter.classId = undefined; gradeClasses.value = []
  if (gradeFilter.majorId) {
    const { data } = await http.get('/base-data/classes')
    gradeClasses.value = (data as any[]).filter((c: any) => c.majorId === gradeFilter.majorId)
  }
}

// ── 4. Pass Rates ──
const passRateFilter = reactive({ collegeId: undefined as string | undefined, courseId: undefined as string | undefined })
const passRateStats = ref<any>(null); const passRateLoading = ref(false)

async function loadPassRateStats() {
  passRateLoading.value = true
  try {
    const params: any = {}
    if (globalTermId.value) params.academicTermId = globalTermId.value
    if (passRateFilter.collegeId) params.collegeId = passRateFilter.collegeId
    if (passRateFilter.courseId) params.courseId = passRateFilter.courseId
    const { data } = await http.get('/statistics/pass-rates/summary', { params })
    passRateStats.value = data
    await nextTick()
    renderPassRateCharts(data)
  } finally { passRateLoading.value = false }
}

function renderPassRateCharts(d: any) {
  const key = 'pr-'
  disposeCharts(key)
  const bc = d.byCollege ?? []
  renderBar(key + 'college', 'pr-college-chart', bc.map((x: any) => x.collegeName), bc.map((x: any) => +(x.passRate * 100).toFixed(1)), '各学院通过率(%)')
  const bcn = (d.byCourse ?? []).slice(0, 15)
  renderBar(key + 'course', 'pr-course-chart', bcn.map((x: any) => x.courseName), bcn.map((x: any) => +(x.passRate * 100).toFixed(1)), '课程通过率Top15(%)')
  renderLine(key + 'trend', 'pr-trend-chart', d.trendByTerm?.map((x: any) => x.termName) ?? [], d.trendByTerm?.map((x: any) => +(x.passRate * 100).toFixed(1)) ?? [], '学期通过率趋势(%)')
  renderPie(key + 'nature', 'pr-nature-chart', d.passRateByNature?.map((x: any) => ({ name: x.natureLabel, value: x.total })) ?? [], '各性质课程记录数')
}

// ── 5. Teacher Workload ──
const workloadFilter = reactive({ collegeId: undefined as string | undefined })
const workloadStats = ref<any>(null); const workloadLoading = ref(false)

async function loadWorkloadStats() {
  workloadLoading.value = true
  try {
    const params: any = {}
    if (globalTermId.value) params.academicTermId = globalTermId.value
    if (workloadFilter.collegeId) params.collegeId = workloadFilter.collegeId
    const { data } = await http.get('/statistics/teacher-workload/summary', { params })
    workloadStats.value = data
    await nextTick()
    renderWorkloadCharts(data)
  } finally { workloadLoading.value = false }
}

function renderWorkloadCharts(d: any) {
  const key = 'wl-'
  disposeCharts(key)
  const bt = (d.byTeacher ?? []).slice(0, 20)
  renderBarHorizontal(key + 'teacher', 'wl-teacher-chart', bt.map((x: any) => x.teacherName), bt.map((x: any) => x.totalHours), '教师工作量Top20(学时)')
  const bcol = d.byCollege ?? []
  renderBar(key + 'college', 'wl-college-chart', bcol.map((x: any) => x.collegeName), bcol.map((x: any) => x.avgHoursPerTeacher), '各学院人均学时')
  const btit = d.byTitle ?? []
  renderBar(key + 'title', 'wl-title-chart', btit.map((x: any) => x.title), btit.map((x: any) => x.avgHours), '各职称人均学时')
  // distribute teachers by workload range
  const ranges = [
    { range: '0-50', min: 0, max: 50 },
    { range: '51-100', min: 51, max: 100 },
    { range: '101-150', min: 101, max: 150 },
    { range: '151-200', min: 151, max: 200 },
    { range: '200+', min: 201, max: 9999 },
  ]
  const dist = ranges.map(r => ({
    name: r.range + '学时',
    value: (d.byTeacher ?? []).filter((x: any) => x.totalHours >= r.min && x.totalHours <= r.max).length
  }))
  renderPie(key + 'dist', 'wl-dist-chart', dist, '工作量分布')
}

// ── 6. Classroom Utilization ──
const classroomFilter = reactive({ buildingId: undefined as string | undefined, campusId: undefined as string | undefined })
const classroomBuildings = ref<any[]>([]); const classroomCampuses = ref<any[]>([])
const classroomStats = ref<any>(null); const classroomLoading = ref(false)

async function loadClassroomStats() {
  classroomLoading.value = true
  try {
    const params: any = {}
    if (globalTermId.value) params.academicTermId = globalTermId.value
    if (classroomFilter.buildingId) params.buildingId = classroomFilter.buildingId
    if (classroomFilter.campusId) params.campusId = classroomFilter.campusId
    const { data } = await http.get('/statistics/classroom-utilization/summary', { params })
    classroomStats.value = data
    await nextTick()
    renderClassroomCharts(data)
  } finally { classroomLoading.value = false }
}

function renderClassroomCharts(d: any) {
  const key = 'cr-'
  disposeCharts(key)
  const bb = d.byBuilding ?? []
  renderBar(key + 'building', 'cr-building-chart', bb.map((x: any) => x.buildingName), bb.map((x: any) => +(x.utilizationRate * 100).toFixed(1)), '各教学楼利用率(%)')
  const bdow = d.byDayOfWeek ?? []
  renderBar(key + 'dow', 'cr-dow-chart', bdow.map((x: any) => x.dayLabel), bdow.map((x: any) => +(x.utilizationRate * 100).toFixed(1)), '各工作日利用率(%)')
  const bts = d.byTimeSlot ?? []
  renderBar(key + 'slot', 'cr-slot-chart', bts.map((x: any) => `第${x.period}节`), bts.map((x: any) => +(x.utilizationRate * 100).toFixed(1)), '各节次利用率(%)')
  renderBar(key + 'type', 'cr-type-chart', d.byClassroomType?.map((x: any) => x.roomType) ?? [], d.byClassroomType?.map((x: any) => +(x.utilizationRate * 100).toFixed(1)) ?? [], '各教室类型利用率(%)')
}

// ── Reusable chart renderers ──
function ensureDom(id: string): HTMLElement | null {
  return document.getElementById(id)
}

function renderPie(chartKey: string, domId: string, data: { name: string; value: number }[], title: string) {
  const dom = ensureDom(domId)
  if (!dom) return
  const inst = echarts.init(dom)
  inst.setOption({
    title: { text: title, left: 'center', textStyle: { fontSize: 14 } },
    tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
    legend: { bottom: 0, type: 'scroll' },
    series: [{ type: 'pie', radius: ['35%', '65%'], center: ['50%', '55%'], data, label: { formatter: '{b}\n{d}%' } }]
  })
  setChart(chartKey, inst)
}

function renderBar(chartKey: string, domId: string, categories: string[], values: number[], title: string) {
  const dom = ensureDom(domId)
  if (!dom) return
  const inst = echarts.init(dom)
  inst.setOption({
    title: { text: title, left: 'center', textStyle: { fontSize: 14 } },
    tooltip: { trigger: 'axis' },
    grid: { left: '3%', right: '4%', bottom: '12%', containLabel: true },
    xAxis: { type: 'category', data: categories, axisLabel: { rotate: 30, fontSize: 11 } },
    yAxis: { type: 'value' },
    series: [{ type: 'bar', data: values, itemStyle: { color: '#409EFF' } }]
  })
  setChart(chartKey, inst)
}

function renderBarHorizontal(chartKey: string, domId: string, categories: string[], values: number[], title: string) {
  const dom = ensureDom(domId)
  if (!dom) return
  const inst = echarts.init(dom)
  inst.setOption({
    title: { text: title, left: 'center', textStyle: { fontSize: 14 } },
    tooltip: { trigger: 'axis' },
    grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
    xAxis: { type: 'value' },
    yAxis: { type: 'category', data: categories.reverse(), axisLabel: { fontSize: 11 } },
    series: [{ type: 'bar', data: values.reverse(), itemStyle: { color: '#67C23A' } }]
  })
  setChart(chartKey, inst)
}

function renderLine(chartKey: string, domId: string, categories: string[], values: number[], title: string) {
  const dom = ensureDom(domId)
  if (!dom) return
  const inst = echarts.init(dom)
  inst.setOption({
    title: { text: title, left: 'center', textStyle: { fontSize: 14 } },
    tooltip: { trigger: 'axis' },
    grid: { left: '3%', right: '4%', bottom: '12%', containLabel: true },
    xAxis: { type: 'category', data: categories, axisLabel: { rotate: 30, fontSize: 11 } },
    yAxis: { type: 'value' },
    series: [{ type: 'line', data: values, smooth: true, itemStyle: { color: '#E6A23C' }, areaStyle: { color: 'rgba(230,162,60,0.15)' } }]
  })
  setChart(chartKey, inst)
}

// ── Excel export ──
function buildFilterParams(type: string): any {
  const p: any = {}
  if (globalTermId.value) p.academicTermId = globalTermId.value
  if (type === 'students') { if (studentFilter.collegeId) p.collegeId = studentFilter.collegeId; if (studentFilter.majorId) p.majorId = studentFilter.majorId; if (studentFilter.classId) p.classId = studentFilter.classId; if (studentFilter.grade) p.grade = studentFilter.grade }
  if (type === 'courses') { if (courseFilter.collegeId) p.collegeId = courseFilter.collegeId; if (courseFilter.categoryId) p.categoryId = courseFilter.categoryId; if (courseFilter.nature) p.nature = courseFilter.nature }
  if (type === 'grades') { if (gradeFilter.collegeId) p.collegeId = gradeFilter.collegeId; if (gradeFilter.majorId) p.majorId = gradeFilter.majorId; if (gradeFilter.classId) p.classId = gradeFilter.classId; if (gradeFilter.courseId) p.courseId = gradeFilter.courseId }
  if (type === 'pass-rates') { if (passRateFilter.collegeId) p.collegeId = passRateFilter.collegeId; if (passRateFilter.courseId) p.courseId = passRateFilter.courseId }
  if (type === 'teacher-workload') { if (workloadFilter.collegeId) p.collegeId = workloadFilter.collegeId }
  if (type === 'classroom-utilization') { if (classroomFilter.buildingId) p.buildingId = classroomFilter.buildingId; if (classroomFilter.campusId) p.campusId = classroomFilter.campusId }
  return p
}
async function exportStats(type: string) {
  const labelMap: Record<string, string> = { students: '学生统计', courses: '课程统计', grades: '成绩统计', 'pass-rates': '通过率统计', 'teacher-workload': '教师工作量统计', 'classroom-utilization': '教室利用率统计' }
  await downloadApiFile(`/statistics/${type}/export`, `${labelMap[type] ?? type}.xlsx`, { params: buildFilterParams(type) })
}

// ── Tab switching ──
watch(activeTab, async (tab) => {
  const loadMap: Record<string, { load: () => Promise<void>; stats: any }> = {
    'students': { load: loadStudentStats, stats: studentStats },
    'courses': { load: loadCourseStats, stats: courseStats },
    'grades': { load: loadGradeStats, stats: gradeStats },
    'pass-rates': { load: loadPassRateStats, stats: passRateStats },
    'teacher-workload': { load: loadWorkloadStats, stats: workloadStats },
    'classroom-utilization': { load: loadClassroomStats, stats: classroomStats },
  }
  const entry = loadMap[tab]
  if (!entry) return
  if (!entry.stats.value) { await entry.load() } else { await nextTick(); for (const v of chartMap.values()) v.resize() }
})

// ── Init ──
onMounted(async () => {
  const [tRes, cRes, catRes, bRes, campRes] = await Promise.all([
    http.get('/base-data/terms'),
    http.get('/base-data/colleges'),
    http.get('/base-data/course-categories'),
    http.get('/base-data/buildings').catch(() => ({ data: [] })),
    http.get('/base-data/campuses').catch(() => ({ data: [] })),
  ])
  terms.value = tRes.data
  colleges.value = cRes.data
  courseCategories.value = catRes.data
  classroomBuildings.value = bRes.data
  classroomCampuses.value = campRes.data
  globalTermId.value = defaultAcademicTermId(terms.value) ?? ''
  loadStudentStats()
})
</script>

<template>
  <div class="page-stack">
    <section class="page-intro">
      <div>
        <span class="section-kicker">REPORTS</span>
        <h2>统计报表</h2>
        <p>学生、课程、成绩、教师工作量与教室利用率的数据汇总与可视化分析。</p>
      </div>
      <div class="page-actions">
        <el-select v-model="globalTermId" placeholder="选择学期" style="width:220px" clearable @change="() => { loadStudentStats(); loadGradeStats(); loadPassRateStats(); loadWorkloadStats(); loadClassroomStats() }">
          <el-option v-for="t in terms" :key="t.id" :label="academicTermLabel(t)" :value="t.id" :class="academicTermOptionClass(t)" />
        </el-select>
      </div>
    </section>

    <el-tabs v-model="activeTab" class="stat-tabs">
      <!-- ═══ 学生统计 ═══ -->
      <el-tab-pane label="学生统计" name="students">
        <section class="data-card" v-loading="studentLoading">
          <div class="filter-bar">
            <el-select v-model="studentFilter.collegeId" clearable placeholder="学院" @change="onStudentCollegeChange">
              <el-option v-for="c in colleges" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-select v-model="studentFilter.majorId" clearable placeholder="专业" @change="onStudentMajorChange">
              <el-option v-for="m in studentMajors" :key="m.id" :label="m.name" :value="m.id" />
            </el-select>
            <el-select v-model="studentFilter.classId" clearable placeholder="班级">
              <el-option v-for="cl in studentClasses" :key="cl.id" :label="cl.name" :value="cl.id" />
            </el-select>
            <el-input-number v-model="studentFilter.grade" :min="2010" :max="2030" placeholder="年级" controls-position="right" style="width:140px" />
            <el-button type="primary" :icon="Search" @click="loadStudentStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('students')">导出Excel</el-button>
          </div>
          <div class="chart-grid">
            <div id="student-college-chart" class="chart-box" />
            <div id="student-gender-chart" class="chart-box" />
            <div id="student-status-chart" class="chart-box" />
            <div id="student-trend-chart" class="chart-box" />
          </div>
          <el-collapse v-if="studentStats">
            <el-collapse-item title="明细数据">
              <el-table :data="studentStats.byCollege ?? []" size="small" max-height="300">
                <el-table-column prop="collegeName" label="学院" />
                <el-table-column prop="count" label="学生数" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>

      <!-- ═══ 课程统计 ═══ -->
      <el-tab-pane label="课程统计" name="courses">
        <section class="data-card" v-loading="courseLoading">
          <div class="filter-bar">
            <el-select v-model="courseFilter.collegeId" clearable placeholder="学院">
              <el-option v-for="c in colleges" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-select v-model="courseFilter.categoryId" clearable placeholder="课程类别">
              <el-option v-for="cat in courseCategories" :key="cat.id" :label="cat.name" :value="cat.id" />
            </el-select>
            <el-select v-model="courseFilter.nature" clearable placeholder="课程性质">
              <el-option label="通识必修" value="GeneralRequired" />
              <el-option label="专业必修" value="MajorRequired" />
              <el-option label="专业选修" value="MajorElective" />
              <el-option label="通识选修" value="GeneralElective" />
              <el-option label="实践环节" value="Practice" />
            </el-select>
            <el-button type="primary" :icon="Search" @click="loadCourseStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('courses')">导出Excel</el-button>
          </div>
          <div class="chart-grid">
            <div id="course-college-chart" class="chart-box" />
            <div id="course-nature-chart" class="chart-box" />
            <div id="course-credit-chart" class="chart-box" />
            <div id="course-assessment-chart" class="chart-box" />
          </div>
          <el-collapse v-if="courseStats">
            <el-collapse-item title="明细数据">
              <el-table :data="courseStats.byCollege ?? []" size="small" max-height="300">
                <el-table-column prop="collegeName" label="学院" />
                <el-table-column prop="count" label="课程数" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>

      <!-- ═══ 成绩统计 ═══ -->
      <el-tab-pane label="成绩统计" name="grades">
        <section class="data-card" v-loading="gradeLoading">
          <div class="filter-bar">
            <el-select v-model="gradeFilter.collegeId" clearable placeholder="学院" @change="onGradeCollegeChange">
              <el-option v-for="c in colleges" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-select v-model="gradeFilter.majorId" clearable placeholder="专业" @change="onGradeMajorChange">
              <el-option v-for="m in gradeMajors" :key="m.id" :label="m.name" :value="m.id" />
            </el-select>
            <el-select v-model="gradeFilter.classId" clearable placeholder="班级">
              <el-option v-for="cl in gradeClasses" :key="cl.id" :label="cl.name" :value="cl.id" />
            </el-select>
            <el-button type="primary" :icon="Search" @click="loadGradeStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('grades')">导出Excel</el-button>
          </div>
          <div v-if="gradeStats?.overall" class="metrics-strip">
            <span class="metric-chip"><b>{{ gradeStats.overall.totalRecords }}</b> 条成绩</span>
            <span class="metric-chip"><b>{{ gradeStats.overall.averageScore }}</b> 平均分</span>
            <span class="metric-chip"><b>{{ (gradeStats.overall.passRate * 100).toFixed(1) }}%</b> 通过率</span>
          </div>
          <div class="chart-grid">
            <div id="grade-score-chart" class="chart-box" />
            <div id="grade-gpa-chart" class="chart-box" />
            <div id="grade-pr-college-chart" class="chart-box" />
            <div id="grade-avg-course-chart" class="chart-box" />
          </div>
          <el-collapse v-if="gradeStats">
            <el-collapse-item title="各学院通过率明细">
              <el-table :data="gradeStats.passRateByCollege ?? []" size="small" max-height="300">
                <el-table-column prop="collegeName" label="学院" />
                <el-table-column label="通过率" sortable="custom">
                  <template #default="{ row }">{{ (row.passRate * 100).toFixed(1) }}%</template>
                </el-table-column>
                <el-table-column prop="averageScore" label="平均分" sortable />
                <el-table-column prop="totalRecords" label="成绩条数" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>

      <!-- ═══ 通过率统计 ═══ -->
      <el-tab-pane label="通过率统计" name="pass-rates">
        <section class="data-card" v-loading="passRateLoading">
          <div class="filter-bar">
            <el-select v-model="passRateFilter.collegeId" clearable placeholder="学院">
              <el-option v-for="c in colleges" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-button type="primary" :icon="Search" @click="loadPassRateStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('pass-rates')">导出Excel</el-button>
          </div>
          <div v-if="passRateStats" class="metrics-strip">
            <span class="metric-chip"><b>{{ (passRateStats.overallPassRate * 100).toFixed(1) }}%</b> 总通过率</span>
            <span class="metric-chip"><b>{{ passRateStats.totalRecords }}</b> 条成绩</span>
          </div>
          <div class="chart-grid">
            <div id="pr-college-chart" class="chart-box" />
            <div id="pr-course-chart" class="chart-box" />
            <div id="pr-trend-chart" class="chart-box" />
            <div id="pr-nature-chart" class="chart-box" />
          </div>
          <el-collapse v-if="passRateStats">
            <el-collapse-item title="低通过率课程 (底10)">
              <el-table :data="passRateStats.byCourseTopFail ?? []" size="small" max-height="300">
                <el-table-column prop="courseCode" label="课程代码" />
                <el-table-column prop="courseName" label="课程名称" />
                <el-table-column label="通过率" sortable="custom">
                  <template #default="{ row }">{{ (row.passRate * 100).toFixed(1) }}%</template>
                </el-table-column>
                <el-table-column prop="total" label="学生数" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>

      <!-- ═══ 教师工作量 ═══ -->
      <el-tab-pane label="教师工作量" name="teacher-workload">
        <section class="data-card" v-loading="workloadLoading">
          <div class="filter-bar">
            <el-select v-model="workloadFilter.collegeId" clearable placeholder="学院">
              <el-option v-for="c in colleges" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-button type="primary" :icon="Search" @click="loadWorkloadStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('teacher-workload')">导出Excel</el-button>
          </div>
          <div v-if="workloadStats?.totals" class="metrics-strip">
            <span class="metric-chip"><b>{{ workloadStats.totals.totalTeachers }}</b> 位教师</span>
            <span class="metric-chip"><b>{{ workloadStats.totals.totalHours }}</b> 总学时</span>
            <span class="metric-chip"><b>{{ workloadStats.totals.avgHoursPerTeacher }}</b> 人均学时</span>
          </div>
          <div class="chart-grid">
            <div id="wl-teacher-chart" class="chart-box" />
            <div id="wl-college-chart" class="chart-box" />
            <div id="wl-title-chart" class="chart-box" />
            <div id="wl-dist-chart" class="chart-box" />
          </div>
          <el-collapse v-if="workloadStats">
            <el-collapse-item title="教师工作量明细 (Top50)">
              <el-table :data="(workloadStats.byTeacher ?? []).slice(0, 50)" size="small" max-height="400">
                <el-table-column prop="teacherName" label="姓名" />
                <el-table-column prop="teacherNumber" label="工号" />
                <el-table-column prop="collegeName" label="学院" />
                <el-table-column prop="title" label="职称" />
                <el-table-column prop="totalHours" label="总学时" sortable />
                <el-table-column prop="courseCount" label="课程数" sortable />
                <el-table-column prop="taskCount" label="教学班数" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>

      <!-- ═══ 教室利用率 ═══ -->
      <el-tab-pane label="教室利用率" name="classroom-utilization">
        <section class="data-card" v-loading="classroomLoading">
          <div class="filter-bar">
            <el-select v-model="classroomFilter.campusId" clearable placeholder="校区">
              <el-option v-for="c in classroomCampuses" :key="c.id" :label="c.name" :value="c.id" />
            </el-select>
            <el-select v-model="classroomFilter.buildingId" clearable placeholder="教学楼">
              <el-option v-for="b in classroomBuildings" :key="b.id" :label="b.name" :value="b.id" />
            </el-select>
            <el-button type="primary" :icon="Search" @click="loadClassroomStats">查询</el-button>
            <el-button :icon="Download" @click="exportStats('classroom-utilization')">导出Excel</el-button>
          </div>
          <div v-if="classroomStats?.totals" class="metrics-strip">
            <span class="metric-chip"><b>{{ classroomStats.totals.totalClassrooms }}</b> 间教室</span>
            <span class="metric-chip"><b>{{ (classroomStats.totals.overallUtilizationRate * 100).toFixed(1) }}%</b> 总利用率</span>
          </div>
          <div class="chart-grid">
            <div id="cr-building-chart" class="chart-box" />
            <div id="cr-dow-chart" class="chart-box" />
            <div id="cr-slot-chart" class="chart-box" />
            <div id="cr-type-chart" class="chart-box" />
          </div>
          <el-collapse v-if="classroomStats">
            <el-collapse-item title="各教学楼利用率明细">
              <el-table :data="classroomStats.byBuilding ?? []" size="small" max-height="300">
                <el-table-column prop="buildingName" label="教学楼" />
                <el-table-column prop="totalClassrooms" label="教室数" sortable />
                <el-table-column label="利用率" sortable="custom">
                  <template #default="{ row }">{{ (row.utilizationRate * 100).toFixed(1) }}%</template>
                </el-table-column>
                <el-table-column prop="totalUsedPeriods" label="已用节次" sortable />
                <el-table-column prop="totalAvailablePeriods" label="可用节次" sortable />
              </el-table>
            </el-collapse-item>
          </el-collapse>
        </section>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<style scoped>
.page-stack { max-width: 1400px; margin: 0 auto }
.stat-tabs { margin-top: 16px }
.stat-tabs :deep(.el-tabs__header) { margin-bottom: 12px }

.filter-bar {
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
  margin-bottom: 16px;
}

.chart-grid {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px;
  margin-bottom: 12px;
}
.chart-box { width: 100%; height: 340px; background: var(--el-fill-color-lighter, #fafafa); border-radius: 8px }

.metrics-strip {
  display: flex; gap: 16px; margin-bottom: 16px; flex-wrap: wrap;
}
.metric-chip {
  background: var(--el-color-primary-light-9, #ecf5ff); color: var(--el-color-primary, #409EFF);
  padding: 6px 16px; border-radius: 20px; font-size: 14px;
}
.metric-chip b { margin-right: 4px }

@media (max-width: 860px) {
  .chart-grid { grid-template-columns: 1fr }
}
</style>
