<template>
  <div>
    <h3>差异分析看板</h3>

    <!-- 筛选栏 -->
    <div style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;align-items:center;">
      <el-select v-model="filterYear" placeholder="年份" style="width:100px;" @change="loadReport">
        <el-option v-for="y in yearOptions" :key="y" :label="y" :value="y" />
      </el-select>
      <el-select v-model="filterMonth" placeholder="月份" style="width:90px;" @change="loadReport">
        <el-option v-for="m in 12" :key="m" :label="`${m}月`" :value="m" />
      </el-select>
      <el-select v-model="filterDimension" placeholder="维度" clearable style="width:110px;" @change="filterChanged">
        <el-option label="财务" value="finance" />
        <el-option label="客户" value="customer" />
        <el-option label="内部流程" value="process" />
        <el-option label="学习成长" value="learning" />
      </el-select>
      <el-select v-model="alertFilter" placeholder="预警级别" clearable style="width:120px;" @change="filterChanged">
        <el-option label="全部" value="" />
        <el-option label="红色预警（超20%）" value="red" />
        <el-option label="黄色预警（超10%）" value="yellow" />
        <el-option label="正常（10%以内）" value="normal" />
      </el-select>
      <el-button type="primary" @click="loadReport">刷新</el-button>
      <el-button @click="exportReport">导出CSV</el-button>
    </div>

    <!-- 汇总统计卡片（维度级） -->
    <el-row :gutter="16" style="margin-bottom:16px;">
      <el-col :span="6">
        <el-card shadow="hover">
          <div class="stat-card">
            <div class="stat-label">已录预算KPI</div>
            <div class="stat-value">{{ stats.total_kpis || 0 }}</div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="6" v-for="dim in dimensionCards" :key="dim.key">
        <el-card shadow="hover" :body-style="{ borderLeft: '4px solid ' + dim.color }" style="cursor:pointer;" @click="scrollToDim(dim.key)">
          <div class="stat-card">
            <div class="stat-label">{{ dim.icon }} {{ dim.name }}</div>
            <div class="stat-value" :class="dim.summary.level + '-text'">
              {{ dim.summary.deviation_rate != null ? dim.summary.deviation_rate.toFixed(1) + '%' : '-' }}
            </div>
            <div style="font-size:11px;color:#999;margin-top:2px;">
              {{ dim.summary.has_budget }}/{{ dim.summary.count }} KPI有预算
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 差异趋势图（简易柱状图） -->
    <el-card style="margin-bottom:16px;">
      <template #header>
        <div style="display:flex;justify-content:space-between;align-items:center;">
          <span>差异趋势（各月实际 vs 预算）</span>
          <el-select v-model="trendKpi" placeholder="选择KPI" style="width:220px;" @change="loadTrend">
            <el-option v-for="k in kpiOptions" :key="k.id" :label="`${k.kpi_code} ${k.kpi_name}`" :value="k.id" />
          </el-select>
        </div>
      </template>
      <div v-if="trendData.length > 0" style="display:flex;align-items:flex-end;gap:8px;height:200px;padding:20px 0;overflow-x:auto;">
        <div v-for="(item, idx) in trendData" :key="idx" style="display:flex;flex-direction:column;align-items:center;min-width:60px;">
          <div :title="`实际: ${item.actual}, 预算: ${item.budget}`" class="trend-bar-group" style="display:flex;gap:3px;height:160px;align-items:flex-end;">
            <div
              class="trend-bar actual-bar"
              :style="{ height: barHeight(item.actual, maxTrend) + 'px' }"
              :title="`实际 ${item.actual}`"
            ></div>
            <div
              class="trend-bar budget-bar"
              :style="{ height: barHeight(item.budget, maxTrend) + 'px' }"
              :title="`预算 ${item.budget}`"
            ></div>
          </div>
          <span style="font-size:11px;color:#909399;margin-top:4px;">{{ item.period }}</span>
          <span v-if="item.deviation !== undefined" :style="{ fontSize:'10px', color: item.deviation > 0 ? '#f56c6c' : '#67c23a' }">
            {{ item.deviation > 0 ? '+' : '' }}{{ item.deviation.toFixed(1) }}%
          </span>
        </div>
      </div>
      <div v-else style="text-align:center;color:#999;padding:40px;">
        {{ trendLoading ? '加载中...' : '选择一个KPI查看趋势' }}
      </div>
    </el-card>

    <!-- 维度→目标→KPI 三层树形表格 -->
    <el-card v-if="hierarchyData.length > 0" :body-style="{ padding: 0 }">
      <el-table
        :data="flattenHierarchy"
        v-loading="loading"
        border stripe
        size="small"
        style="width:100%;"
        row-key="__uid"
        :tree-props="{ children: '_children' }"
        :indent="24"
        :default-expand-all="expandedAll"
        @row-click="onRowClick"
      >
        <el-table-column label="层级" min-width="280">
          <template #default="{ row }">
            <div style="display:flex;align-items:center;gap:6px;">
              <span v-if="row._type === 'dimension'" style="font-size:16px;">{{ row.icon }}</span>
              <span :style="{
                fontWeight: row._type === 'dimension' ? 700 : row._type === 'objective' ? 600 : 400,
                fontSize: row._type === 'dimension' ? '14px' : '13px',
                color: row._type === 'dimension' ? '#303133' : '#606266'
              }">{{ row._type === 'dimension' ? row.name + ' 维度' : row.name }}</span>
              <el-tag v-if="row._type === 'dimension'" size="small" :type="levelTag(row.summary.level)" style="margin-left:4px;">
                {{ row.summary.deviation_rate != null ? row.summary.deviation_rate.toFixed(1) + '%' : '--' }}
              </el-tag>
              <el-tag v-if="row._type === 'objective'" size="small" :type="levelTag(row.summary.level)" style="margin-left:4px;">
                {{ row.summary.deviation_rate != null ? row.summary.deviation_rate.toFixed(1) + '%' : '--' }}
              </el-tag>
              <span v-if="row._type === 'dimension'" style="font-size:11px;color:#999;margin-left:8px;">
                {{ row.summary.has_budget }}/{{ row.summary.count }} KPI
              </span>
              <span v-if="row._type === 'objective'" style="font-size:11px;color:#999;margin-left:8px;">
                {{ row.summary.has_budget }}/{{ row.summary.count }} KPI
              </span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="kpi_code" label="KPI编码" width="110">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi'" style="font-family:monospace;font-size:12px;">{{ row.kpi_code }}</span>
          </template>
        </el-table-column>
        <el-table-column label="预算值" width="120" align="right">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi'" :style="{ color: row.budget_value != null ? '#303133' : '#999' }">
              {{ row.budget_value != null ? fmtVal(row.budget_value) : '--' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="实际值" width="120" align="right">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi'" :style="{ color: row.actual_value != null ? '#303133' : '#999' }">
              {{ row.actual_value != null ? fmtVal(row.actual_value) : '--' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="差异额" width="120" align="right">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi'" :style="{ color: (row.deviation_amount || 0) > 0 ? '#f56c6c' : '#67c23a' }">
              {{ row.deviation_amount !== undefined ? fmtVal(row.deviation_amount) : '--' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="差异率" width="100" align="right">
          <template #default="{ row }">
            <el-tag v-if="row._type === 'kpi' && row.deviation_rate !== undefined" :type="deviationTag(row.deviation_rate)" size="small">
              {{ row.deviation_rate > 0 ? '+' : '' }}{{ row.deviation_rate.toFixed(2) }}%
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="同比" width="85" align="right">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi' && row.yoy?.diff_rate != null"
              :style="{ color: (row.yoy.diff_rate || 0) > 0 ? '#f56c6c' : '#67c23a', fontSize:'12px' }">
              {{ row.yoy.diff_rate > 0 ? '+' : '' }}{{ row.yoy.diff_rate.toFixed(1) }}%
            </span>
          </template>
        </el-table-column>
        <el-table-column label="环比" width="85" align="right">
          <template #default="{ row }">
            <span v-if="row._type === 'kpi' && row.mom?.diff_rate != null"
              :style="{ color: (row.mom.diff_rate || 0) > 0 ? '#f56c6c' : '#67c23a', fontSize:'12px' }">
              {{ row.mom.diff_rate > 0 ? '+' : '' }}{{ row.mom.diff_rate.toFixed(1) }}%
            </span>
          </template>
        </el-table-column>
        <el-table-column label="预警" width="80" align="center">
          <template #default="{ row }">
            <el-tag v-if="row._type === 'kpi' && row.deviation_rate != null" :type="deviationTag(row.deviation_rate)" size="small">
              {{ row.deviation_rate > 20 ? '红色' : row.deviation_rate > 10 ? '黄色' : '正常' }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 无数据提示 -->
    <el-empty v-if="!loading && hierarchyData.length === 0 && reportData.length === 0" description="暂无差异分析数据，请先在预算管理中录入预算" style="padding:40px 0;" />
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { budgetApi, kpiApi } from '../api/index'

const currentYear = new Date().getFullYear()
const yearOptions = computed(() => {
  const years: number[] = []
  for (let y = currentYear - 2; y <= currentYear + 2; y++) years.push(y)
  return years
})

const filterYear = ref(currentYear)
const filterMonth = ref(new Date().getMonth() + 1)
const filterDimension = ref('')
const alertFilter = ref('')
const loading = ref(false)
const reportData = ref<any[]>([])
const hierarchyData = ref<any[]>([])
const stats = ref<any>({})
const expandedAll = ref(true)

// ── 维度卡片计算 ──
const dimensionCards = computed(() => {
  return hierarchyData.value.map(d => ({
    key: d.key,
    name: d.name,
    icon: d.icon,
    color: d.color,
    summary: d.summary
  }))
})

// ── 平铺树结构为el-table可用的带_children的列表 ──
const flattenHierarchy = computed(() => {
  const result: any[] = []
  let uid = 0
  for (const dim of hierarchyData.value) {
    const dimRow = { ...dim, _type: 'dimension', _children: [], __uid: `dim_${++uid}` }
    for (const obj of dim.objectives) {
      const objRow = { ...obj, _type: 'objective', _children: [], __uid: `obj_${++uid}` }
      for (const kpi of obj.kpis) {
        objRow._children.push({
          ...kpi,
          _type: 'kpi',
          _children: undefined,
          __uid: `kpi_${++uid}_${kpi.kpi_id}`
        })
      }
      dimRow._children.push(objRow)
    }
    result.push(dimRow)
  }
  return result
})

// ── 工具函数 ──
const dimMap: Record<string, string> = { finance: '财务', customer: '客户', process: '内部流程', learning: '学习成长' }
const dimTagMap: Record<string, string> = { finance: 'danger', customer: 'warning', process: 'primary', learning: 'success' }

function levelTag(level: string) {
  if (level === 'red') return 'danger'
  if (level === 'yellow') return 'warning'
  if (level === 'green') return 'success'
  return 'info'
}

function deviationTag(rate: number) {
  if (rate > 20) return 'danger'
  if (rate > 10) return 'warning'
  return 'success'
}

function fmtVal(v: any) {
  if (v === null || v === undefined) return '--'
  return Number(v).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}

// ── 筛选变更（前端过滤树） ──
function filterChanged() {
  // 维度或预警级别变化时，后端的hierarchical接口不支持前端过滤
  // 重新加载（后端过滤）
  loadReport()
}

function scrollToDim(key: string) {
  // 展开所有，让目标维度可见
  expandedAll.value = true
}

function onRowClick(row: any) {
  // KPI级点击跳到详情
  if (row._type === 'kpi' && row.kpi_id) {
    window.open('/#/kpis/' + row.kpi_id, '_blank')
  }
}

// ── 加载差异报告 ──
async function loadReport() {
  loading.value = true
  try {
    const params: any = { hierarchical: true }
    if (filterYear.value) params.year = filterYear.value
    if (filterMonth.value) params.month = filterMonth.value
    if (filterDimension.value) params.dimension = filterDimension.value
    if (alertFilter.value) params.alert_level = alertFilter.value
    const r: any = await budgetApi.deviationReport(params)
    reportData.value = r.items || []
    hierarchyData.value = r.hierarchy || []
    stats.value = r.summary || {}
    // 如果hierarchy有数据，用层级中的统计补全stats
    if (hierarchyData.value.length > 0) {
      let total = 0, hasBudget = 0
      for (const dim of hierarchyData.value) {
        total += dim.summary.count || 0
        hasBudget += dim.summary.has_budget || 0
      }
      stats.value.total_kpis = total
      stats.value.has_budget = hasBudget
    }
  } catch (e) {
    ElMessage.error('加载差异报告失败')
  }
  loading.value = false
}

// ── 趋势图 ──
const trendKpi = ref<number | null>(null)
const kpiOptions = ref<any[]>([])
const trendData = ref<any[]>([])
const trendLoading = ref(false)
const maxTrend = ref(0)

async function loadKpiOptions() {
  try {
    const r: any = await kpiApi.list({ page_size: 200 })
    const data = r.data || r || []
    kpiOptions.value = Array.isArray(data) ? data : (data.items || [])
  } catch (e) { /* ignore */ }
}

async function loadTrend() {
  if (!trendKpi.value) { trendData.value = []; return }
  trendLoading.value = true
  try {
    const r: any = await budgetApi.deviationReport({ kpi_id: trendKpi.value })
    const data = r.data || r || []
    const items = Array.isArray(data) ? data : (data.items || [])
    const monthly = items.filter((i: any) => i.budget_value !== null)
      .sort((a: any, b: any) => {
        const keyA = a.period || ''
        const keyB = b.period || ''
        return keyA.localeCompare(keyB)
      })
    trendData.value = monthly.map((i: any) => ({
      period: i.period,
      actual: i.actual_value || 0,
      budget: i.budget_value || 0,
      deviation: i.deviation_rate,
    }))
    maxTrend.value = Math.max(...trendData.value.flatMap((d: any) => [d.actual, d.budget]), 1)
  } catch (e) { /* ignore */ }
  trendLoading.value = false
}

function barHeight(val: number, max: number) {
  if (!max) return 0
  return Math.max(4, (val / max) * 150)
}

// ── 导出CSV ──
function exportReport() {
  const dims = hierarchyData.value
  if (dims.length === 0) { ElMessage.warning('无数据可导出'); return }
  const headers = ['维度', '战略目标', 'KPI编码', 'KPI名称', '预算值', '实际值', '差异额', '差异率(%)', '同比(%)', '环比(%)', '预警']
  const csvRows = [headers.join(',')]
  for (const dim of dims) {
    for (const obj of dim.objectives) {
      if (obj.kpis.length === 0) {
        csvRows.push([dim.name, `"${obj.name}"`].join(','))
      }
      for (const k of obj.kpis) {
        csvRows.push([
          dim.name, `"${obj.name}"`, k.kpi_code || '', `"${k.kpi_name || ''}"`,
          k.budget_value ?? '', k.actual_value ?? '',
          k.deviation_amount ?? '', k.deviation_rate?.toFixed(2) ?? '',
          k.yoy?.diff_rate?.toFixed(1) ?? '', k.mom?.diff_rate?.toFixed(1) ?? '',
          k.deviation_rate != null ? (k.deviation_rate > 20 ? '红色' : k.deviation_rate > 10 ? '黄色' : '正常') : ''
        ].join(','))
      }
    }
  }
  const blob = new Blob([csvRows.join('\n')], { type: 'text/csv' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `偏差分析报告_${filterYear.value}年${filterMonth.value}月.csv`
  a.click()
  URL.revokeObjectURL(url)
  ElMessage.success('导出成功')
}

onMounted(() => {
  loadReport()
  loadKpiOptions()
})
</script>

<style scoped>
.stat-card { text-align: center; padding: 4px 0; }
.stat-label { font-size: 13px; color: #909399; margin-bottom: 6px; }
.stat-value { font-size: 24px; font-weight: bold; color: #303133; }
.red-text { color: #f56c6c; }
.yellow-text { color: #e6a23c; }
.green-text { color: #67c23a; }
.gray-text { color: #909399; }
.trend-bar { width: 18px; border-radius: 3px 3px 0 0; transition: height 0.3s; }
.actual-bar { background: #409eff; }
.budget-bar { background: #e6a23c; }
</style>
