<!--
  页面名称：Dashboard.vue
  页面描述：测试总览页面，展示统计数据、趋势图表和最近执行记录

  @author czj
  @date 2026-07-09
-->

<template>
  <div class="dashboard-page">
    <!-- 统计卡片 -->
    <el-row :gutter="20" class="stats-row">
      <el-col :span="6">
        <el-card class="stats-card" shadow="hover">
          <div class="stats-content">
            <el-icon class="stats-icon passed"><CircleCheck /></el-icon>
            <div class="stats-info">
              <span class="stats-value">{{ stats.case_runs.passed }}</span>
              <span class="stats-label">本月通过</span>
            </div>
          </div>
          <div class="stats-footer">
            <span class="footer-text">执行 {{ stats.executions.total }} 次</span>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card" shadow="hover">
          <div class="stats-content">
            <el-icon class="stats-icon failed"><CircleClose /></el-icon>
            <div class="stats-info">
              <span class="stats-value">{{ stats.case_runs.failed }}</span>
              <span class="stats-label">本月失败</span>
            </div>
          </div>
          <div class="stats-footer">
            <span class="footer-text">跳过 {{ stats.case_runs.skipped }} 次</span>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card" shadow="hover">
          <div class="stats-content">
            <el-icon class="stats-icon rate"><TrendCharts /></el-icon>
            <div class="stats-info">
              <span class="stats-value">{{ stats.case_runs.pass_rate }}%</span>
              <span class="stats-label">平均通过率</span>
            </div>
          </div>
          <div class="stats-footer">
            <span
              class="footer-text"
              :class="passRateStatus"
            >
              {{ passRateStatusText }}
            </span>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stats-card" shadow="hover">
          <div class="stats-content">
            <el-icon class="stats-icon total"><DataBoard /></el-icon>
            <div class="stats-info">
              <span class="stats-value">{{ stats.cases.total }}</span>
              <span class="stats-label">总用例数</span>
            </div>
          </div>
          <div class="stats-footer">
            <span class="footer-text">{{ stats.modules.total }} 个模块</span>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 图表区域 -->
    <el-row :gutter="20" class="charts-row">
      <el-col :span="16">
        <el-card class="chart-card" shadow="never">
          <template #header>
            <div class="card-header">
              <span>执行趋势（近30天）</span>
              <el-radio-group v-model="chartType" size="small">
                <el-radio-button value="executions">执行次数</el-radio-button>
                <el-radio-button value="passRate">通过率</el-radio-button>
              </el-radio-group>
            </div>
          </template>
          <div ref="trendChartRef" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="8">
        <el-card class="chart-card" shadow="never">
          <template #header>
            <span>模块用例分布</span>
          </template>
          <div ref="moduleChartRef" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 最近执行记录 -->
    <el-card class="recent-executions" shadow="never">
      <template #header>
        <div class="card-header">
          <span>最近执行记录</span>
          <el-button type="primary" size="small" @click="goToExecution">
            查看全部
          </el-button>
        </div>
      </template>

      <el-table
        :data="stats.recent_executions"
        stripe
        style="width: 100%"
        v-loading="loading"
      >
        <el-table-column prop="name" label="执行名称" min-width="200" />
        <el-table-column label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="getStatusType(row.status)">
              {{ getStatusText(row.status) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="通过率" width="100">
          <template #default="{ row }">
            <span :class="getPassRateClass(row.pass_rate)">
              {{ row.pass_rate }}%
            </span>
          </template>
        </el-table-column>
        <el-table-column label="耗时" width="100">
          <template #default="{ row }">
            {{ row.duration?.toFixed(1) || 0 }}s
          </template>
        </el-table-column>
        <el-table-column prop="trigger_by" label="触发人" width="100" />
        <el-table-column label="时间" width="180">
          <template #default="{ row }">
            {{ formatTime(row.created_at) }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="80">
          <template #default="{ row }">
            <el-button
              size="small"
              type="primary"
              link
              @click="viewExecution(row.id)"
            >
              详情
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 快捷操作 -->
    <el-card class="quick-actions" shadow="never">
      <template #header>
        <span>快捷操作</span>
      </template>

      <el-row :gutter="20">
        <el-col :span="6">
          <div class="action-item" @click="goToRecorder">
            <el-icon :size="32"><VideoCamera /></el-icon>
            <span>录制用例</span>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="action-item" @click="runAllTests">
            <el-icon :size="32"><VideoPlay /></el-icon>
            <span>执行全部测试</span>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="action-item" @click="goToModules">
            <el-icon :size="32"><Folder /></el-icon>
            <span>管理模块</span>
          </div>
        </el-col>
        <el-col :span="6">
          <div class="action-item" @click="goToReports">
            <el-icon :size="32"><DataLine /></el-icon>
            <span>查看报告</span>
          </div>
        </el-col>
      </el-row>
    </el-card>
  </div>
</template>

<script setup lang="ts">
/**
 * Dashboard 总览页面
 *
 * 功能：
 * 1. 展示统计数据卡片（通过数、失败数、通过率、用例数）
 * 2. 展示执行趋势图表（ECharts）
 * 3. 展示模块用例分布（饼图）
 * 4. 展示最近执行记录
 * 5. 提供快捷操作入口
 */

import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import {
  CircleCheck,
  CircleClose,
  TrendCharts,
  DataBoard,
  VideoCamera,
  VideoPlay,
  Folder,
  DataLine
} from '@element-plus/icons-vue'
import * as echarts from 'echarts'
import { statsApi } from '@/api/stats'
import { executionApi } from '@/api/executions'

const router = useRouter()

// ==================== 响应式数据 ====================

const loading = ref(false)

// 统计数据
const stats = ref({
  period_days: 30,
  executions: { total: 0 },
  case_runs: {
    total: 0,
    passed: 0,
    failed: 0,
    skipped: 0,
    pass_rate: 0,
  },
  cases: { total: 0 },
  modules: { total: 0 },
  recent_executions: [] as any[],
})

// 趋势数据
const trendData = ref<any[]>([])

// 模块数据
const moduleData = ref<any[]>([])

// 图表类型
const chartType = ref<'executions' | 'passRate'>('executions')

// 图表引用
const trendChartRef = ref<HTMLElement>()
const moduleChartRef = ref<HTMLElement>()
let trendChart: echarts.ECharts | null = null
let moduleChart: echarts.ECharts | null = null

// ==================== 计算属性 ====================

const passRateStatus = computed(() => {
  const rate = stats.value.case_runs.pass_rate
  if (rate >= 90) return 'status-success'
  if (rate >= 70) return 'status-warning'
  return 'status-danger'
})

const passRateStatusText = computed(() => {
  const rate = stats.value.case_runs.pass_rate
  if (rate >= 90) return '状态良好'
  if (rate >= 70) return '需要关注'
  return '需要改进'
})

// ==================== 方法定义 ====================

const loadStats = async () => {
  loading.value = true
  try {
    const [overviewRes, trendRes, modulesRes] = await Promise.all([
      statsApi.getOverview(30),
      statsApi.getTrend(30),
      statsApi.getModules(),
    ])

    stats.value = overviewRes
    trendData.value = trendRes.trend
    moduleData.value = modulesRes.modules

    // 初始化图表
    await nextTick()
    initTrendChart()
    initModuleChart()
  } catch (error: any) {
    console.error('加载统计数据失败:', error)
    ElMessage.error('加载统计数据失败')
  } finally {
    loading.value = false
  }
}

const initTrendChart = () => {
  if (!trendChartRef.value) return

  if (trendChart) {
    trendChart.dispose()
  }

  trendChart = echarts.init(trendChartRef.value)

  const dates = trendData.value.map(d => d.date.slice(5)) // MM-DD 格式
  const executions = trendData.value.map(d => d.executions)
  const passRates = trendData.value.map(d => d.pass_rate)

  const option: echarts.EChartsOption = {
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      }
    },
    legend: {
      data: chartType.value === 'executions' ? ['执行次数'] : ['通过率']
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: dates,
      axisLabel: {
        rotate: 45,
        interval: 4
      }
    },
    yAxis: {
      type: 'value',
      name: chartType.value === 'executions' ? '次数' : '通过率(%)',
      min: chartType.value === 'passRate' ? 0 : undefined,
      max: chartType.value === 'passRate' ? 100 : undefined,
    },
    series: chartType.value === 'executions' ? [
      {
        name: '执行次数',
        type: 'line',
        smooth: true,
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(64, 158, 255, 0.5)' },
            { offset: 1, color: 'rgba(64, 158, 255, 0.1)' }
          ])
        },
        lineStyle: {
          color: '#409eff',
          width: 2
        },
        itemStyle: {
          color: '#409eff'
        },
        data: executions
      }
    ] : [
      {
        name: '通过率',
        type: 'line',
        smooth: true,
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: 'rgba(103, 194, 58, 0.5)' },
            { offset: 1, color: 'rgba(103, 194, 58, 0.1)' }
          ])
        },
        lineStyle: {
          color: '#67c23a',
          width: 2
        },
        itemStyle: {
          color: '#67c23a'
        },
        data: passRates
      }
    ]
  }

  trendChart.setOption(option)
}

const initModuleChart = () => {
  if (!moduleChartRef.value) return

  if (moduleChart) {
    moduleChart.dispose()
  }

  moduleChart = echarts.init(moduleChartRef.value)

  const data = moduleData.value.map(m => ({
    name: m.name,
    value: m.case_count
  })).filter(d => d.value > 0)

  const option: echarts.EChartsOption = {
    tooltip: {
      trigger: 'item',
      formatter: '{b}: {c} ({d}%)'
    },
    legend: {
      orient: 'vertical',
      left: 'left',
      top: 'center'
    },
    series: [
      {
        type: 'pie',
        radius: ['40%', '70%'],
        center: ['60%', '50%'],
        avoidLabelOverlap: false,
        itemStyle: {
          borderRadius: 10,
          borderColor: '#fff',
          borderWidth: 2
        },
        label: {
          show: false,
          position: 'center'
        },
        emphasis: {
          label: {
            show: true,
            fontSize: 16,
            fontWeight: 'bold'
          }
        },
        labelLine: {
          show: false
        },
        data: data
      }
    ]
  }

  moduleChart.setOption(option)
}

const getStatusType = (status: string) => {
  const typeMap: Record<string, string> = {
    completed: 'success',
    running: 'warning',
    failed: 'danger',
    pending: 'info'
  }
  return typeMap[status] || 'info'
}

const getStatusText = (status: string) => {
  const textMap: Record<string, string> = {
    completed: '完成',
    running: '运行中',
    failed: '失败',
    pending: '待执行'
  }
  return textMap[status] || status
}

const getPassRateClass = (rate: number) => {
  if (rate >= 90) return 'rate-success'
  if (rate >= 70) return 'rate-warning'
  return 'rate-danger'
}

const formatTime = (time: string) => {
  if (!time) return '-'
  return new Date(time).toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  })
}

/** 导航方法 */
const goToExecution = () => router.push('/execution')
const goToRecorder = () => router.push('/recorder')
const goToModules = () => router.push('/modules')
const goToReports = () => router.push('/reports')

const viewExecution = (id: string) => {
  router.push(`/execution?id=${id}`)
}

/** 执行全部测试 */
const runAllTests = async () => {
  try {
    // 获取所有用例
    const execution = await executionApi.create({
      case_ids: [], // 空数组表示全部用例（需要后端支持）
      name: `全量测试-${new Date().toLocaleDateString()}`,
    })
    await executionApi.run(execution.id)
    ElMessage.success('执行任务已启动')
    router.push('/execution')
  } catch (error: any) {
    ElMessage.error('启动执行失败: ' + error.message)
  }
}

// 监听图表类型变化
watch(chartType, () => {
  initTrendChart()
})

// 窗口大小变化时重绘图表
const handleResize = () => {
  trendChart?.resize()
  moduleChart?.resize()
}

// ==================== 生命周期 ====================

onMounted(() => {
  loadStats()
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  trendChart?.dispose()
  moduleChart?.dispose()
})
</script>

<style lang="scss" scoped>
.dashboard-page {
  .stats-row {
    margin-bottom: 20px;
  }

  .stats-card {
    .stats-content {
      display: flex;
      align-items: center;
      gap: 16px;

      .stats-icon {
        font-size: 48px;

        &.passed { color: #67c23a; }
        &.failed { color: #f56c6c; }
        &.rate { color: #409eff; }
        &.total { color: #e6a23c; }
      }

      .stats-info {
        display: flex;
        flex-direction: column;

        .stats-value {
          font-size: 32px;
          font-weight: 600;
          color: #303133;
        }

        .stats-label {
          font-size: 14px;
          color: #909399;
        }
      }
    }

    .stats-footer {
      margin-top: 12px;
      padding-top: 12px;
      border-top: 1px solid #ebeef5;

      .footer-text {
        font-size: 13px;
        color: #909399;

        &.status-success { color: #67c23a; }
        &.status-warning { color: #e6a23c; }
        &.status-danger { color: #f56c6c; }
      }
    }
  }

  .charts-row {
    margin-bottom: 20px;

    .chart-card {
      .card-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
      }

      .chart-container {
        height: 300px;
      }
    }
  }

  .recent-executions {
    margin-bottom: 20px;

    .card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .rate-success { color: #67c23a; font-weight: 600; }
    .rate-warning { color: #e6a23c; font-weight: 600; }
    .rate-danger { color: #f56c6c; font-weight: 600; }
  }

  .quick-actions {
    .action-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 12px;
      padding: 24px;
      background: #f5f7fa;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.3s;

      &:hover {
        background: #e6ebf5;
        transform: translateY(-2px);
      }

      span {
        font-size: 14px;
        color: #606266;
      }
    }
  }
}
</style>