<script setup lang="ts">
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import type { EChartsOption } from 'echarts'

type ServiceState = 'normal' | 'busy' | 'error'
type TaskState = 'running' | 'pending' | 'completed' | 'failed'

interface ServiceStatus {
  name: string
  icon: string
  state: ServiceState
  instances: string
}

interface DashboardTask {
  id: number
  name: string
  state: TaskState
  trainType: string
  trainMethod: string
  baseModel: string
  progress: number
  accuracy: number | null
  startedAt: string
}

const router = useRouter()
const period = ref('7d')

const serviceStatuses: ServiceStatus[] = [
  { name: '模型推理', icon: 'fa-cube', state: 'normal', instances: '6 / 6' },
  { name: '模型微调', icon: 'fa-sliders', state: 'busy', instances: '4 / 6' },
  { name: '模型评测', icon: 'fa-bar-chart', state: 'normal', instances: '3 / 3' },
  { name: '数据处理', icon: 'fa-filter', state: 'error', instances: '1 / 3' },
]

const trainingTasks: DashboardTask[] = [
  {
    id: 103942,
    name: 'finance-sft-003',
    state: 'running',
    trainType: 'SFT',
    trainMethod: 'LoRA',
    baseModel: 'Qwen2.5-7B-Instruct',
    progress: 68,
    accuracy: 89.2,
    startedAt: '今天 09:18',
  },
  {
    id: 593021,
    name: 'legal-eval-008',
    state: 'pending',
    trainType: 'DPO',
    trainMethod: 'LoRA',
    baseModel: 'Qwen2.5-7B-Instruct',
    progress: 0,
    accuracy: null,
    startedAt: '今天 08:55',
  },
  {
    id: 849301,
    name: 'medical-cpt-002',
    state: 'completed',
    trainType: 'CPT',
    trainMethod: 'Full',
    baseModel: 'Qwen2.5-14B-Instruct',
    progress: 100,
    accuracy: 91.6,
    startedAt: '07/10 16:20',
  },
  {
    id: 201948,
    name: 'finance-sft-002',
    state: 'failed',
    trainType: 'SFT',
    trainMethod: 'LoRA',
    baseModel: 'Qwen2.5-7B-Instruct',
    progress: 42,
    accuracy: null,
    startedAt: '07/10 11:08',
  },
]

const serviceStateMeta: Record<ServiceState, { label: string; className: string }> = {
  normal: { label: '正常', className: 'is-normal' },
  busy: { label: '繁忙', className: 'is-busy' },
  error: { label: '异常', className: 'is-error' },
}

const taskStateMeta: Record<TaskState, { label: string; className: string }> = {
  running: { label: '训练中', className: 'is-running' },
  pending: { label: '等待中', className: 'is-pending' },
  completed: { label: '已完成', className: 'is-completed' },
  failed: { label: '训练失败', className: 'is-failed' },
}

const progressColor: Record<TaskState, string> = {
  running: '#4f46e5',
  pending: '#cbd5e1',
  completed: '#10b981',
  failed: '#ef4444',
}

const chartOption = computed<EChartsOption>(() => ({
  animationDuration: 500,
  color: ['#4f46e5', '#10b981', '#f59e0b'],
  grid: { top: 50, right: 50, bottom: 38, left: 46, containLabel: false },
  legend: {
    top: 4,
    left: 0,
    itemWidth: 12,
    itemHeight: 12,
    itemGap: 22,
    textStyle: { color: '#64748b', fontSize: 11 },
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: { type: 'shadow' },
    backgroundColor: 'rgba(15, 23, 42, 0.92)',
    borderWidth: 0,
    padding: [10, 12],
    textStyle: { color: '#ffffff', fontSize: 12 },
    valueFormatter: (value) => `${value}`,
  },
  xAxis: {
    type: 'category',
    data: ['07/05', '07/06', '07/07', '07/08', '07/09', '07/10', '07/11\n今天'],
    axisLine: { lineStyle: { color: '#e2e8f0' } },
    axisTick: { show: false },
    axisLabel: { color: '#64748b', fontSize: 11, lineHeight: 16, margin: 12 },
  },
  yAxis: [
    {
      type: 'value',
      name: '次数 / GPU 数',
      min: 0,
      max: 20,
      interval: 5,
      nameTextStyle: { color: '#64748b', fontSize: 11, align: 'left' },
      axisLabel: { color: '#64748b', fontSize: 11 },
      axisLine: { show: false },
      axisTick: { show: false },
      splitLine: { lineStyle: { color: '#eef2f7' } },
    },
    {
      type: 'value',
      name: '准确率',
      min: 0,
      max: 100,
      interval: 25,
      nameTextStyle: { color: '#64748b', fontSize: 11, align: 'right' },
      axisLabel: { color: '#64748b', fontSize: 11, formatter: '{value}%' },
      axisLine: { show: false },
      axisTick: { show: false },
      splitLine: { show: false },
    },
  ],
  series: [
    {
      name: '训练次数（次）',
      type: 'bar',
      data: [8, 12, 10, 15, 13, 18, 11],
      barMaxWidth: 16,
      itemStyle: { borderRadius: [3, 3, 0, 0] },
      label: { show: true, position: 'top', color: '#64748b', fontSize: 10 },
    },
    {
      name: 'GPU 使用数（个）',
      type: 'bar',
      data: [3, 4, 4, 6, 5, 7, 5],
      barMaxWidth: 16,
      itemStyle: { borderRadius: [3, 3, 0, 0] },
      label: { show: true, position: 'top', color: '#64748b', fontSize: 10 },
    },
    {
      name: '平均准确率（%）',
      type: 'bar',
      yAxisIndex: 1,
      data: [82, 85, 84, 88, 87, 91, 89],
      barMaxWidth: 16,
      itemStyle: { borderRadius: [3, 3, 0, 0] },
      label: { show: true, position: 'top', color: '#d97706', fontSize: 10 },
    },
  ],
}))

function viewAllTasks() {
  router.push('/fine-tune')
}

function viewTask(task: DashboardTask) {
  router.push(`/training-log/${task.id}`)
}

</script>

<template>
  <div class="dashboard-view">
    <section class="overview-section" aria-labelledby="overview-title">
      <h2 id="overview-title" class="section-title">平台运行状态</h2>
      <div class="overview-content">
        <div class="health-summary">
          <div class="health-icon" aria-hidden="true"><i class="fa fa-check" /></div>
          <div>
            <strong>整体运行正常</strong>
            <p>平台运行良好，各项服务稳定</p>
          </div>
        </div>
        <div class="overview-metrics">
          <div class="overview-metric">
            <span>在线服务</span>
            <strong>12</strong>
            <small>全部在线</small>
          </div>
          <div class="overview-metric">
            <span>运行中任务</span>
            <strong>5</strong>
            <small>较昨日 +1</small>
          </div>
          <div class="overview-metric is-alert">
            <span>待处理告警</span>
            <strong>2</strong>
            <small>较昨日 -1</small>
          </div>
        </div>
      </div>
    </section>

    <div class="dashboard-middle">
      <section class="chart-section" aria-labelledby="chart-title">
        <div class="section-heading-row">
          <h2 id="chart-title" class="section-title">近 7 天训练统计</h2>
          <el-select v-model="period" class="period-select" aria-label="统计周期">
            <el-option label="近7天" value="7d" />
          </el-select>
        </div>
        <VChart class="training-chart" :option="chartOption" autoresize />
      </section>

      <section class="service-section" aria-labelledby="service-title">
        <h2 id="service-title" class="section-title">服务状态</h2>
        <div class="service-table" role="table" aria-label="服务状态">
          <div class="service-row service-header" role="row">
            <span role="columnheader">服务名称</span>
            <span role="columnheader">状态</span>
            <span role="columnheader">实例数</span>
          </div>
          <div v-for="service in serviceStatuses" :key="service.name" class="service-row" role="row">
            <span class="service-name" role="cell">
              <i class="fa" :class="service.icon" aria-hidden="true" />
              {{ service.name }}
            </span>
            <span role="cell">
              <span class="state-pill" :class="serviceStateMeta[service.state].className">
                {{ serviceStateMeta[service.state].label }}
              </span>
            </span>
            <span class="instance-count" role="cell">{{ service.instances }}</span>
          </div>
        </div>
      </section>
    </div>

    <section class="tasks-section" aria-labelledby="tasks-title">
      <div class="section-heading-row tasks-heading">
        <h2 id="tasks-title" class="section-title">训练任务</h2>
        <el-button link type="primary" @click="viewAllTasks">查看全部任务</el-button>
      </div>
      <div class="tasks-table-wrap">
        <table class="tasks-table">
          <thead>
            <tr>
              <th>任务名称</th>
              <th>任务状态</th>
              <th>训练方式</th>
              <th>基座模型</th>
              <th>训练进度</th>
              <th>准确率</th>
              <th>开始时间</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="task in trainingTasks" :key="task.id">
              <td class="task-name">{{ task.name }}</td>
              <td>
                <span class="task-state" :class="taskStateMeta[task.state].className">
                  {{ taskStateMeta[task.state].label }}
                </span>
              </td>
              <td>{{ task.trainType }} / {{ task.trainMethod }}</td>
              <td>{{ task.baseModel }}</td>
              <td>
                <div class="progress-cell">
                  <el-progress
                    :percentage="task.progress"
                    :stroke-width="6"
                    :show-text="false"
                    :color="progressColor[task.state]"
                  />
                  <span>{{ task.progress }}%</span>
                </div>
              </td>
              <td class="numeric-value">{{ task.accuracy == null ? '--' : `${task.accuracy}%` }}</td>
              <td>{{ task.startedAt }}</td>
              <td>
                <el-button link type="primary" @click="viewTask(task)">查看详情</el-button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>
  </div>
</template>

<style scoped lang="scss">
.dashboard-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 10px;
  min-width: 0;
  min-height: 0;
  color: #1e293b;
}

.overview-section,
.chart-section,
.service-section,
.tasks-section {
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  background: #ffffff;
}

.section-title {
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  font-weight: 600;
  color: #1e293b;
}

.overview-section {
  padding: 12px 14px 13px;
}

.overview-content {
  display: grid;
  grid-template-columns: minmax(300px, 1.05fr) minmax(540px, 1.75fr);
  align-items: stretch;
  margin-top: 10px;
}

.health-summary {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 86px;
  padding: 6px 18px 6px 12px;
  border-right: 1px solid #e2e8f0;

  strong {
    display: block;
    color: #10b981;
    font-size: 20px;
    line-height: 1.3;
    font-weight: 700;
  }

  p {
    margin: 5px 0 0;
    color: #64748b;
    font-size: 13px;
  }
}

.health-icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  flex: 0 0 56px;
  border-radius: 50%;
  background: #10b981;
  color: #ffffff;
  font-size: 26px;
  box-shadow: 0 6px 16px rgba(16, 185, 129, 0.14);
}

.overview-metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}

.overview-metric {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  border-right: 1px solid #e2e8f0;

  &:last-child {
    border-right: none;
  }

  span,
  small {
    color: #64748b;
    font-size: 12px;
  }

  strong {
    font-size: 26px;
    line-height: 1;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
  }

  &.is-alert strong {
    color: #ef4444;
  }
}

.dashboard-middle {
  display: grid;
  grid-template-columns: minmax(0, 1.65fr) minmax(330px, 0.95fr);
  flex: 1 1 auto;
  gap: 10px;
  min-height: 0;
}

.chart-section,
.service-section {
  display: flex;
  flex-direction: column;
  min-height: 280px;
  padding: 12px 14px;
}

.section-heading-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.period-select {
  width: 94px;

  :deep(.el-select__wrapper) {
    min-height: 30px;
  }
}

.training-chart {
  flex: 1 1 auto;
  width: 100%;
  height: auto;
  min-height: 230px;
}

.service-table {
  display: grid;
  grid-template-rows: 36px repeat(4, minmax(48px, 1fr));
  flex: 1 1 auto;
  margin-top: 12px;
  min-height: 0;
}

.service-row {
  display: grid;
  grid-template-columns: minmax(130px, 1.35fr) minmax(72px, 0.7fr) 72px;
  align-items: center;
  min-height: 48px;
  border-top: 1px solid #eef2f7;
  color: #475569;
  font-size: 13px;
}

.service-header {
  min-height: 36px;
  border-top: none;
  color: #64748b;
  font-size: 12px;
  font-weight: 600;
}

.service-name {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #334155;
  font-weight: 500;

  .fa {
    width: 18px;
    color: #64748b;
    text-align: center;
  }
}

.state-pill,
.task-state {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 22px;
  padding: 0 8px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.is-normal,
.is-completed {
  color: #059669;
  background: #ecfdf5;
}

.is-busy,
.is-pending {
  color: #d97706;
  background: #fffbeb;
}

.is-error,
.is-failed {
  color: #dc2626;
  background: #fef2f2;
}

.is-running {
  color: #4f46e5;
  background: #eef2ff;
}

.instance-count,
.numeric-value {
  font-variant-numeric: tabular-nums;
}

.tasks-section {
  padding: 10px 0 0;
  overflow: hidden;
}

.tasks-heading {
  min-height: 30px;
  padding: 0 14px 8px;
}

.tasks-table-wrap {
  overflow-x: auto;
}

.tasks-table {
  width: 100%;
  min-width: 980px;
  border-collapse: collapse;
  table-layout: fixed;
  color: #475569;
  font-size: 12px;

  th,
  td {
    height: 38px;
    padding: 6px 10px;
    border-top: 1px solid #eef2f7;
    text-align: left;
    vertical-align: middle;
    white-space: nowrap;
  }

  th {
    height: 34px;
    background: #f8fafc;
    color: #475569;
    font-weight: 600;
  }

  th:nth-child(1) { width: 14%; }
  th:nth-child(2) { width: 10%; }
  th:nth-child(3) { width: 11%; }
  th:nth-child(4) { width: 17%; }
  th:nth-child(5) { width: 17%; }
  th:nth-child(6) { width: 9%; }
  th:nth-child(7) { width: 12%; }
  th:nth-child(8) { width: 10%; }
}

.task-name {
  color: #334155;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
}

.progress-cell {
  display: grid;
  grid-template-columns: minmax(72px, 1fr) 38px;
  align-items: center;
  gap: 8px;
  font-variant-numeric: tabular-nums;

  :deep(.el-progress-bar__outer) {
    background: #e2e8f0;
  }
}

@media (max-height: 900px) and (min-width: 1181px) {
  .dashboard-view {
    gap: 8px;
  }

  .section-title {
    font-size: 14px;
  }

  .overview-section {
    padding: 8px 12px 9px;
  }

  .overview-content {
    margin-top: 6px;
  }

  .health-summary {
    gap: 10px;
    min-height: 64px;
    padding: 4px 14px 4px 8px;

    strong {
      font-size: 18px;
    }

    p {
      margin-top: 3px;
      font-size: 12px;
    }
  }

  .health-icon {
    width: 44px;
    height: 44px;
    flex-basis: 44px;
    font-size: 20px;
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.12);
  }

  .overview-metric {
    gap: 2px;

    span,
    small {
      font-size: 11px;
    }

    strong {
      font-size: 23px;
    }
  }

  .dashboard-middle {
    gap: 8px;
  }

  .chart-section,
  .service-section {
    min-height: 240px;
    padding: 10px 12px;
  }

  .training-chart {
    min-height: 200px;
  }

  .service-table {
    grid-template-rows: 32px repeat(4, minmax(40px, 1fr));
    margin-top: 8px;
  }

  .service-row {
    min-height: 40px;
    font-size: 12px;
  }

  .service-header {
    min-height: 32px;
    font-size: 11px;
  }

  .state-pill,
  .task-state {
    min-height: 20px;
    padding-inline: 7px;
    font-size: 11px;
  }

  .tasks-section {
    padding-top: 6px;
  }

  .tasks-heading {
    min-height: 24px;
    padding: 0 12px 6px;
  }

  .tasks-table {
    th,
    td {
      height: 32px;
      padding: 4px 8px;
    }

    th {
      height: 30px;
    }
  }
}

@media (max-width: 1180px) {
  .overview-content {
    grid-template-columns: 1fr;
  }

  .health-summary {
    border-right: none;
    border-bottom: 1px solid #e2e8f0;
  }

  .overview-metrics {
    min-height: 94px;
  }

  .dashboard-middle {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dashboard-view * {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
</style>
