<template>
  <div v-loading="loading" class="dashboard-page page-stack">
    <section class="page-toolbar">
      <div>
        <span class="eyebrow">{{ pageConfig.group }}</span>
        <h1>{{ pageConfig.title }}</h1>
        <p>{{ pageConfig.description }}</p>
      </div>
      <div class="toolbar-actions">
        <el-button :icon="Download">导出</el-button>
        <el-button :icon="Refresh" :loading="loading" @click="loadOverview">刷新数据</el-button>
      </div>
    </section>

    <section class="stats-grid dashboard-kpis">
      <article v-for="item in pageKpis" :key="item.label" class="stat-card">
        <div :class="['stat-mark', item.tone]">{{ item.label.slice(0, 1) }}</div>
        <div>
          <span>{{ item.label }}</span>
          <strong>{{ item.value }}</strong>
          <em>{{ item.change }}</em>
        </div>
      </article>
    </section>

    <section class="overview-grid">
      <ChartPanel
        v-for="chart in pageCharts"
        :key="chart.key"
        :class="{ 'wide-chart': chart.wide, 'tall-chart': chart.tall }"
        :title="chart.title"
        :subtitle="chart.subtitle"
        :option="chart.option"
      />
    </section>

    <section v-if="pageConfig.table === 'department'" class="data-section">
      <div class="section-header">
        <div>
          <h2>{{ pageConfig.tableTitle }}</h2>
          <p>{{ pageConfig.tableSubtitle }}</p>
        </div>
      </div>
      <el-table :data="dashboard.departmentRows" empty-text="暂无科室数据" row-key="id">
        <el-table-column prop="department" label="科室" min-width="130" />
        <el-table-column prop="caseCount" label="病例数" width="100" />
        <el-table-column prop="trainCount" label="训练次数" width="110" />
        <el-table-column prop="effectiveTrain" label="有效训练" width="110" />
        <el-table-column prop="activeUsers" label="活跃用户" width="110" />
        <el-table-column prop="avgScore" label="平均分" width="100" />
      </el-table>
    </section>

    <section v-else-if="pageConfig.table === 'case'" class="data-section">
      <div class="section-header">
        <div>
          <h2>{{ pageConfig.tableTitle }}</h2>
          <p>{{ pageConfig.tableSubtitle }}</p>
        </div>
      </div>
      <el-table :data="caseRows" empty-text="暂无病例使用数据" row-key="id">
        <el-table-column prop="title" label="病例名称" min-width="220" />
        <el-table-column prop="count" label="训练次数" width="110" />
        <el-table-column prop="total" label="完成训练" width="110" />
        <el-table-column prop="passRate" label="通过率" width="110">
          <template #default="{ row }">{{ percentText(row.passRate) }}</template>
        </el-table-column>
      </el-table>
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import type { EChartsOption } from 'echarts'
import { ElMessage } from 'element-plus'
import { Download, Refresh } from '@element-plus/icons-vue'
import ChartPanel from '@/components/ChartPanel.vue'
import { fetchHospitalOverview, type HospitalOverview } from '@/api/stats'
import { useAppStore } from '@/stores/app'

type StatTone = 'blue' | 'green' | 'purple' | 'orange'
type TableMode = 'department' | 'case' | ''

interface StatCard {
  label: string
  value: string
  change: string
  tone: StatTone
}

interface PageConfig {
  title: string
  group: string
  description: string
  table: TableMode
  tableTitle: string
  tableSubtitle: string
}

interface ChartSpec {
  key: string
  title: string
  subtitle: string
  option: EChartsOption
  wide?: boolean
  tall?: boolean
}

const axisLine = { lineStyle: { color: '#dce3eb' } }
const splitLine = { lineStyle: { color: '#eef2f7' } }
const route = useRoute()
const appStore = useAppStore()
const loading = ref(false)
const overview = ref<HospitalOverview | null>(null)

const pageConfigs: Record<string, PageConfig> = {
  'hospital-data': {
    title: '运营数据',
    group: '运营数据',
    description: '汇总本院训练、科室、病例和学习效果核心指标。',
    table: 'department',
    tableTitle: '科室运营明细',
    tableSubtitle: '来自医院驾驶舱总览的科室聚合数据'
  },
  'case-usage': {
    title: '病例使用',
    group: '运营数据',
    description: '查看本院病例资产、病例使用次数和训练通过率。',
    table: 'case',
    tableTitle: '病例使用明细',
    tableSubtitle: '病例训练次数、完成训练和通过率'
  },
  'training-stats': {
    title: '训练统计',
    group: '运营数据',
    description: '跟踪本院训练规模、完成率和科室训练投入。',
    table: 'department',
    tableTitle: '科室训练明细',
    tableSubtitle: '训练总次数、有效训练和平均成绩'
  },
  'dept-analysis': {
    title: '科室分析',
    group: '运营数据',
    description: '按科室分析病例数、训练次数、活跃用户和平均成绩。',
    table: 'department',
    tableTitle: '科室综合排行',
    tableSubtitle: '病例、训练、有效训练、活跃用户和平均分'
  },
  'ability-trend': {
    title: '能力趋势',
    group: '能力提升',
    description: '对比本院学员能力维度、平均分和平台平均水平。',
    table: '',
    tableTitle: '',
    tableSubtitle: ''
  },
  'student-ranking': {
    title: '学生排行',
    group: '能力提升',
    description: '按科室聚合查看本院学员训练表现和平均成绩。',
    table: 'department',
    tableTitle: '科室学生表现排行',
    tableSubtitle: '以科室为单位聚合活跃用户、训练次数和平均分'
  }
}

const currentPage = computed(() => String(route.params.page || route.path.split('/').pop() || 'hospital-data'))
const pageConfig = computed(() => pageConfigs[currentPage.value] || pageConfigs['hospital-data'])

const dashboard = computed(() => {
  const data = overview.value
  const summary = data?.summary || { train_months: [], train_monthly: [] }
  const competency = data?.competency || { radar: [], radar_platform: [] }
  const caseAsset = data?.case_asset || { top_used: [], pass_high: [], pass_low: [] }
  const departments = data?.dept_rank || []
  const trainMonthly = summary.train_monthly || []
  const departmentRows = departments.map(item => ({
    id: item.id,
    department: item.department,
    caseCount: item.case_count,
    trainCount: item.train_count,
    effectiveTrain: item.effective_train,
    activeUsers: item.active_users,
    avgScore: item.avg_score
  }))

  return {
    summary,
    caseAsset,
    departments,
    departmentRows,
    months: summary.train_months || [],
    trainingCounts: trainMonthly,
    latestMonthTraining: trainMonthly[trainMonthly.length - 1] || 0,
    growthRates: calcGrowth(trainMonthly),
    scoreGauge: {
      hospital: competency.student_avg || summary.avg_score || 0,
      platform: competency.platform_avg || 0
    },
    departmentCases: departmentRows.map(item => ({ name: item.department, value: item.caseCount })),
    departmentTraining: departmentRows.map(item => ({ name: item.department, total: item.trainCount, effective: item.effectiveTrain })),
    departmentActiveUsers: departmentRows.map(item => ({ name: item.department, value: item.activeUsers })),
    departmentScores: departmentRows.map(item => ({ name: item.department, value: item.avgScore })),
    caseUsageTop: caseAsset.top_used.map(item => ({ id: item.case_id, name: item.title, value: item.count })),
    passRateBest: caseAsset.pass_high.map(item => ({ id: item.case_id, name: item.title, rate: item.pass_rate, total: item.total })),
    passRateWorst: caseAsset.pass_low.map(item => ({ id: item.case_id, name: item.title, rate: item.pass_rate, total: item.total })),
    abilityCompare: mergeRadar(competency.radar, competency.radar_platform),
    totals: {
      caseCount: departmentRows.reduce((total, item) => total + item.caseCount, 0),
      trainCount: departmentRows.reduce((total, item) => total + item.trainCount, 0),
      effectiveTrain: departmentRows.reduce((total, item) => total + item.effectiveTrain, 0),
      activeUsers: departmentRows.reduce((total, item) => total + item.activeUsers, 0)
    }
  }
})

const caseRows = computed(() => {
  const rows = new Map<number, { id: number; title: string; count: number; total: number; passRate: number | null }>()

  dashboard.value.caseUsageTop.forEach(item => {
    rows.set(item.id, { id: item.id, title: item.name, count: item.value, total: 0, passRate: null })
  })
  ;[...dashboard.value.passRateBest, ...dashboard.value.passRateWorst].forEach(item => {
    const row = rows.get(item.id)
    rows.set(item.id, {
      id: item.id,
      title: item.name,
      count: row?.count || 0,
      total: item.total,
      passRate: item.rate
    })
  })

  return Array.from(rows.values()).sort((a, b) => b.count - a.count)
})

const pageKpis = computed<StatCard[]>(() => {
  const summary = dashboard.value.summary
  const caseAsset = dashboard.value.caseAsset
  const totals = dashboard.value.totals
  const bestDept = [...dashboard.value.departmentRows].sort((a, b) => b.avgScore - a.avgScore)[0]

  if (currentPage.value === 'case-usage') {
    return [
      stat('累计病例总数', numberText(caseAsset.total), '本院病例', 'blue'),
      stat('当月新增病例', numberText(caseAsset.new_month), '本月新增', 'green'),
      stat('已使用病例数', numberText(caseRows.value.length), '有训练记录', 'purple'),
      stat('最高使用次数', numberText(dashboard.value.caseUsageTop[0]?.value), dashboard.value.caseUsageTop[0]?.name || '暂无数据', 'orange')
    ]
  }

  if (currentPage.value === 'training-stats') {
    return [
      stat('累计训练次数', numberText(summary.train_total), '本院训练', 'blue'),
      stat('本月训练次数', numberText(dashboard.value.latestMonthTraining), '最近月份', 'green'),
      stat('训练完成率', percentText(summary.complete_rate), '完成训练占比', 'purple'),
      stat('有效训练次数', numberText(totals.effectiveTrain), '科室合计', 'orange')
    ]
  }

  if (currentPage.value === 'dept-analysis') {
    return [
      stat('本院科室数', numberText(summary.dept_count), '当前机构', 'blue'),
      stat('科室病例数', numberText(totals.caseCount), '科室合计', 'green'),
      stat('科室训练数', numberText(totals.trainCount), '科室合计', 'purple'),
      stat('活跃用户数', numberText(totals.activeUsers), '科室合计', 'orange')
    ]
  }

  if (currentPage.value === 'ability-trend') {
    return [
      stat('本院平均分', scoreText(dashboard.value.scoreGauge.hospital), '学生训练平均', 'blue'),
      stat('平台平均分', scoreText(dashboard.value.scoreGauge.platform), '平台对比', 'green'),
      stat('训练完成率', percentText(summary.complete_rate), '完成训练占比', 'purple'),
      stat('能力维度数', numberText(dashboard.value.abilityCompare.length), '雷达维度', 'orange')
    ]
  }

  if (currentPage.value === 'student-ranking') {
    return [
      stat('本院学员数', numberText(summary.student_count), '学生用户', 'blue'),
      stat('平均训练得分', scoreText(summary.avg_score), '本院平均', 'green'),
      stat('累计训练次数', numberText(summary.train_total), '本院训练', 'purple'),
      stat('最高分科室', bestDept?.department || '-', bestDept ? scoreText(bestDept.avgScore) : '暂无数据', 'orange')
    ]
  }

  return [
    stat('本院科室数', numberText(summary.dept_count), '当前机构', 'blue'),
    stat('带教老师数', numberText(summary.doctor_count), '医生用户', 'green'),
    stat('本院学员数', numberText(summary.student_count), '学生用户', 'purple'),
    stat('累计训练次数', numberText(summary.train_total), '本院训练', 'blue'),
    stat('训练完成率', percentText(summary.complete_rate), '完成训练占比', 'orange'),
    stat('平均训练得分', scoreText(summary.avg_score), '归一百分制', 'green')
  ]
})

const pageCharts = computed<ChartSpec[]>(() => {
  if (currentPage.value === 'case-usage') {
    return [
      chart('case-top', '使用病例最高次数 Top10', '按病例训练次数排序', caseUsageTopOption.value, true, true),
      chart('case-pass', '病例通过率排行', '按完成训练通过率排序', casePassRateOption.value),
      chart('case-total', '病例资产概览', '累计病例与当月新增病例', caseAssetOption.value)
    ]
  }

  if (currentPage.value === 'training-stats') {
    return [
      chart('training-trend', '本院近6个月训练次数', '柱状图为训练次数，折线图为环比增长率', trainingTrendOption.value, true),
      chart('dept-training', '各科室训练次数与有效训练次数', '训练总次数与完整完成次数对比', departmentTrainingOption.value, true),
      chart('score-gauge', '本院训练完成率', '完成率与平均分概览', completionGaugeOption.value)
    ]
  }

  if (currentPage.value === 'dept-analysis') {
    return [
      chart('dept-cases', '各科室病例数排行', '按科室统计当前病例数', departmentCasesOption.value),
      chart('dept-training', '各科室训练次数与有效训练次数', '训练总次数与完整完成次数对比', departmentTrainingOption.value, true),
      chart('dept-active', '各科室活跃用户排行', '产生训练行为的活跃用户数', departmentActiveOption.value),
      chart('dept-score', '各科室平均成绩', '按科室计算训练平均成绩', departmentScoreOption.value)
    ]
  }

  if (currentPage.value === 'ability-trend') {
    return [
      chart('ability-radar', '本院各维度得分率', '雷达图叠加平台平均线', abilityCompareOption.value, true),
      chart('score-compare', '本院学员平均分与平台对比', '统计本院所有学生训练平均分', scoreGaugeOption.value),
      chart('dept-score', '各科室平均成绩', '按科室计算训练平均成绩', departmentScoreOption.value)
    ]
  }

  if (currentPage.value === 'student-ranking') {
    return [
      chart('dept-score-rank', '科室学生平均分排行', '按科室聚合学生训练平均分', departmentScoreRankingOption.value, true),
      chart('dept-active', '科室活跃学生排行', '按科室聚合活跃用户数', departmentActiveOption.value),
      chart('dept-training', '科室训练投入排行', '按科室聚合训练次数', departmentTrainRankingOption.value)
    ]
  }

  return [
    chart('training-trend', '本院近6个月训练次数', '柱状图为训练次数，折线图为环比增长率', trainingTrendOption.value, true),
    chart('score-gauge', '本院学员平均分与平台对比', '统计本院所有学生训练平均分', scoreGaugeOption.value),
    chart('dept-training', '各科室训练次数与有效训练次数', '训练总次数与完整完成次数对比', departmentTrainingOption.value, true),
    chart('case-top', '使用病例最高次数 Top10', '按病例训练次数排序', caseUsageTopOption.value)
  ]
})

const trainingTrendOption = computed<EChartsOption>(() => ({
  color: ['#2563eb', '#f59e0b'],
  tooltip: { trigger: 'axis' },
  legend: { top: 0 },
  grid: { left: 48, right: 48, top: 42, bottom: 32 },
  xAxis: { type: 'category', data: dashboard.value.months, axisLine },
  yAxis: [
    { type: 'value', name: '训练次数', splitLine },
    { type: 'value', name: '环比', axisLabel: { formatter: '{value}%' }, splitLine: { show: false } }
  ],
  series: [
    { name: '训练次数', type: 'bar', barWidth: 22, data: dashboard.value.trainingCounts, itemStyle: { borderRadius: [5, 5, 0, 0] } },
    { name: '环比增长率', type: 'line', yAxisIndex: 1, smooth: true, data: dashboard.value.growthRates }
  ]
}))

const scoreGaugeOption = computed<EChartsOption>(() => ({
  color: ['#2563eb', '#0f766e'],
  series: [
    {
      name: '本院平均分',
      type: 'gauge',
      radius: '82%',
      min: 0,
      max: 100,
      progress: { show: true, roundCap: true, width: 12 },
      axisLine: { lineStyle: { width: 12 } },
      pointer: { width: 4 },
      detail: { formatter: '{value}', fontSize: 24, offsetCenter: [0, '62%'] },
      data: [{ value: dashboard.value.scoreGauge.hospital, name: `平台 ${dashboard.value.scoreGauge.platform}` }]
    }
  ]
}))

const completionGaugeOption = computed<EChartsOption>(() => ({
  color: ['#0f766e'],
  series: [
    {
      name: '训练完成率',
      type: 'gauge',
      radius: '82%',
      min: 0,
      max: 100,
      progress: { show: true, roundCap: true, width: 12 },
      axisLine: { lineStyle: { width: 12 } },
      pointer: { width: 4 },
      detail: { formatter: '{value}%', fontSize: 22, offsetCenter: [0, '62%'] },
      data: [{ value: dashboard.value.summary.complete_rate || 0, name: `平均分 ${scoreText(dashboard.value.summary.avg_score)}` }]
    }
  ]
}))

const departmentCasesOption = computed<EChartsOption>(() => horizontalBarOption(
  dashboard.value.departmentCases.map(item => item.name),
  dashboard.value.departmentCases.map(item => item.value),
  '病例数',
  '#2563eb'
))

const departmentTrainingOption = computed<EChartsOption>(() => ({
  color: ['#2563eb', '#0f766e'],
  tooltip: { trigger: 'axis' },
  legend: { top: 0 },
  grid: { left: 70, right: 24, top: 42, bottom: 28 },
  xAxis: { type: 'value', splitLine },
  yAxis: { type: 'category', inverse: true, data: dashboard.value.departmentTraining.map(item => item.name), axisLine },
  series: [
    { name: '训练总次数', type: 'bar', barWidth: 14, data: dashboard.value.departmentTraining.map(item => item.total) },
    { name: '有效训练次数', type: 'bar', barWidth: 14, data: dashboard.value.departmentTraining.map(item => item.effective) }
  ]
}))

const departmentActiveOption = computed<EChartsOption>(() => horizontalBarOption(
  dashboard.value.departmentActiveUsers.map(item => item.name),
  dashboard.value.departmentActiveUsers.map(item => item.value),
  '活跃用户',
  '#0f766e'
))

const departmentScoreOption = computed<EChartsOption>(() => ({
  color: ['#7c3aed'],
  tooltip: { trigger: 'axis' },
  grid: { left: 40, right: 20, top: 28, bottom: 32 },
  xAxis: { type: 'category', data: dashboard.value.departmentScores.map(item => item.name), axisLine },
  yAxis: { type: 'value', max: 100, splitLine },
  series: [
    { name: '平均成绩', type: 'bar', barWidth: 22, data: dashboard.value.departmentScores.map(item => item.value), itemStyle: { borderRadius: [5, 5, 0, 0] } }
  ]
}))

const departmentScoreRankingOption = computed<EChartsOption>(() => {
  const rows = [...dashboard.value.departmentScores].sort((a, b) => b.value - a.value)
  return horizontalBarOption(
    rows.map(item => item.name),
    rows.map(item => item.value),
    '平均分',
    '#f59e0b',
    100
  )
})

const departmentTrainRankingOption = computed<EChartsOption>(() => {
  const rows = [...dashboard.value.departmentTraining].sort((a, b) => b.total - a.total)
  return horizontalBarOption(
    rows.map(item => item.name),
    rows.map(item => item.total),
    '训练次数',
    '#2563eb'
  )
})

const caseUsageTopOption = computed<EChartsOption>(() => horizontalBarOption(
  dashboard.value.caseUsageTop.map(item => item.name),
  dashboard.value.caseUsageTop.map(item => item.value),
  '训练次数',
  '#2563eb'
))

const casePassRateOption = computed<EChartsOption>(() => {
  const rows = [...caseRows.value].filter(item => item.passRate !== null).sort((a, b) => (b.passRate || 0) - (a.passRate || 0))
  return horizontalBarOption(
    rows.map(item => item.title),
    rows.map(item => item.passRate || 0),
    '通过率',
    '#0f766e',
    100
  )
})

const caseAssetOption = computed<EChartsOption>(() => ({
  color: ['#2563eb', '#f59e0b'],
  tooltip: { trigger: 'axis' },
  grid: { left: 42, right: 20, top: 28, bottom: 32 },
  xAxis: { type: 'category', data: ['累计病例', '当月新增'], axisLine },
  yAxis: { type: 'value', splitLine },
  series: [
    {
      name: '病例数',
      type: 'bar',
      barWidth: 28,
      data: [dashboard.value.caseAsset.total || 0, dashboard.value.caseAsset.new_month || 0],
      itemStyle: { borderRadius: [5, 5, 0, 0] }
    }
  ]
}))

const abilityCompareOption = computed<EChartsOption>(() => ({
  color: ['#2563eb', '#f59e0b'],
  legend: { top: 0 },
  radar: {
    radius: 96,
    indicator: dashboard.value.abilityCompare.map(item => ({ name: item.name, max: 100 }))
  },
  series: [
    {
      type: 'radar',
      data: [
        { name: '本院平均', value: dashboard.value.abilityCompare.map(item => item.hospital), areaStyle: { color: 'rgba(37, 99, 235, 0.14)' } },
        { name: '平台平均', value: dashboard.value.abilityCompare.map(item => item.platform), areaStyle: { color: 'rgba(245, 158, 11, 0.1)' } }
      ]
    }
  ]
}))

function horizontalBarOption(names: string[], values: number[], seriesName: string, color: string, max?: number): EChartsOption {
  return {
    color: [color],
    tooltip: { trigger: 'axis' },
    grid: { left: 100, right: 24, top: 18, bottom: 22 },
    xAxis: { type: 'value', max, splitLine },
    yAxis: { type: 'category', inverse: true, data: names, axisLabel: { width: 94, overflow: 'truncate' }, axisLine },
    series: [
      { name: seriesName, type: 'bar', barWidth: 14, data: values, itemStyle: { borderRadius: [0, 5, 5, 0] } }
    ]
  }
}

async function loadOverview() {
  if (!appStore.token) {
    ElMessage.warning('缺少登录信息，请重新登录')
    return
  }
  if (loading.value) {
    return
  }

  try {
    loading.value = true
    overview.value = await fetchHospitalOverview(appStore.token)
  } catch (error) {
    ElMessage.error(error instanceof Error ? error.message : '获取医院概览失败')
  } finally {
    loading.value = false
  }
}

function stat(label: string, value: string, change: string, tone: StatTone): StatCard {
  return { label, value, change, tone }
}

function chart(key: string, title: string, subtitle: string, option: EChartsOption, wide = false, tall = false): ChartSpec {
  return { key, title, subtitle, option, wide, tall }
}

function numberText(value: number | null | undefined) {
  return typeof value === 'number' && Number.isFinite(value) ? value.toLocaleString('zh-CN') : '-'
}

function scoreText(value: number | null | undefined) {
  return typeof value === 'number' && Number.isFinite(value) ? value.toFixed(1) : '-'
}

function percentText(value: number | null | undefined) {
  return typeof value === 'number' && Number.isFinite(value) ? `${value.toFixed(1)}%` : '-'
}

function calcGrowth(values: number[]) {
  return values.map((value, index) => {
    if (index === 0 || !values[index - 1]) {
      return 0
    }
    return Number((((value - values[index - 1]) / values[index - 1]) * 100).toFixed(1))
  })
}

function mergeRadar(
  hospital: Array<{ dimension: string; score: number }>,
  platform: Array<{ dimension: string; score: number }>
) {
  const platformMap = new Map(platform.map(item => [item.dimension, item.score]))
  const names = Array.from(new Set([...hospital.map(item => item.dimension), ...platform.map(item => item.dimension)]))
  return names.map(name => ({
    name,
    hospital: hospital.find(item => item.dimension === name)?.score || 0,
    platform: platformMap.get(name) || 0
  }))
}

watch(
  () => appStore.token,
  token => {
    if (token) {
      loadOverview()
    }
  },
  { immediate: true }
)
</script>
