<template>
  <div class="alignment-page">
    <div class="page-header">
      <h3>战略执行看板</h3>
      <div>
        <el-button v-if="alignConfigured" @click="loadTree" :loading="loading" :disabled="loading" style="margin-right:8px;">
          刷新数据
        </el-button>
        <el-button type="primary" @click="showSelector = true">
          {{ alignConfigured ? '切换模式' : '配置对齐模式' }}
        </el-button>
      </div>
    </div>

    <!-- 模式选择器 -->
    <div v-if="showSelector" class="align-setup">
      <el-alert v-if="!alignConfigured" title="系统尚未配置KPI对齐模式" type="warning" :closable="false" show-icon class="section-gap" />
      <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;">
        <el-card v-for="mode in alignModes" :key="mode.key"
          :class="{ 'mode-card': true, 'selected-mode': selectedMode === mode.key }"
          shadow="hover" @click="selectedMode = mode.key"
        >
          <template #header>
            <div style="display:flex;justify-content:space-between;align-items:center;">
              <span style="font-weight:600;">{{ mode.name }}</span>
              <el-radio :model-value="selectedMode === mode.key" :label="mode.key">&nbsp;</el-radio>
            </div>
          </template>
          <p style="font-size:13px;color:#666;line-height:1.6;">{{ mode.description }}</p>
          <el-tag type="info" size="small">示例</el-tag>
          <p style="font-size:12px;color:#999;margin-top:4px;background:#f5f7fa;padding:6px 8px;border-radius:4px;">{{ mode.example }}</p>
        </el-card>
      </div>
      <div style="margin-top:16px;display:flex;gap:12px;">
        <el-button type="primary" size="large" @click="saveAlignConfig" :loading="saving" :disabled="!selectedMode">
          {{ alignConfigured ? '切换为「' + selectedModeName + '」' : '确定并启用「' + selectedModeName + '」' }}
        </el-button>
        <el-button v-if="alignConfigured" @click="showSelector = false; selectedMode = currentMode?.key || ''">取消</el-button>
      </div>
    </div>

    <!-- 看板主体 -->
    <div v-else>
      <!-- 地图选择器 -->
      <div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap;">
        <span style="font-size:13px;color:#666;white-space:nowrap;">筛选地图：</span>
        <el-select v-model="selectedMapId" placeholder="全部KPI" clearable style="width:240px;" @change="onMapChange">
          <el-option v-for="m in mapList" :key="m.id" :label="m.title" :value="m.id" />
        </el-select>
        <span v-if="selectedMapId" style="font-size:12px;color:#409eff;">仅显示该地图关联KPI的对齐关系</span>
        <span v-else style="font-size:12px;color:#999;">显示全部KPI</span>
      </div>
      <!-- 状态栏 -->
      <div style="display:flex;gap:16px;margin-bottom:16px;flex-wrap:wrap;">
        <el-card shadow="never" style="flex:1;min-width:120px;">
          <div style="font-size:12px;color:#999;">对齐模式</div>
          <div style="font-size:16px;font-weight:600;margin-top:4px;">{{ currentMode?.name || '-' }}</div>
        </el-card>
        <el-card shadow="never" style="flex:1;min-width:120px;">
          <div style="font-size:12px;color:#999;">KPI总数</div>
          <div style="font-size:16px;font-weight:600;margin-top:4px;">{{ treeData?.total || 0 }}</div>
        </el-card>
        <el-card shadow="never" style="flex:1;min-width:120px;">
          <div style="font-size:12px;color:#999;">有数据</div>
          <div style="font-size:16px;font-weight:600;margin-top:4px;">{{ kpiWithData }}</div>
        </el-card>
        <el-card shadow="never" style="flex:1;min-width:120px;">
          <div style="font-size:12px;color:#999;">红黄灯</div>
          <div style="font-size:16px;font-weight:600;margin-top:4px;">
            <span v-if="redCount > 0" style="color:#f56c6c;">{{ redCount }}红</span>
            <span v-if="redCount > 0 && yellowCount > 0" style="color:#999;margin:0 4px;">/</span>
            <span v-if="yellowCount > 0" style="color:#e6a23c;">{{ yellowCount }}黄</span>
            <span v-if="redCount === 0 && yellowCount === 0" style="color:#67c23a;">全部正常</span>
          </div>
        </el-card>
      </div>

      <!-- 对齐树 -->
      <div style="border:1px solid #e4e7ed;border-radius:8px;padding:12px;background:#fff;">
        <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
          <span style="font-weight:500;">对齐关系（{{ treeData?.mode_name || '' }}）</span>
          <span style="font-size:12px;color:#999;" v-if="treeData">
            最后数据期间：{{ latestPeriod }}
            <el-button text size="small" @click="loadTree" :loading="loading" style="margin-left:8px;">刷新</el-button>
          </span>
        </div>
        <el-tree v-if="treeData" :data="treeData.tree || []" :props="{ label: 'kpi_name', children: 'children' }" default-expand-all>
          <template #default="{ data }">
            <div class="tree-node-row">
              <!-- 维度组 -->
              <template v-if="data.is_dimension_group">
                <span :style="{color: dimColor(data.dimension), fontWeight:600}">{{ data.kpi_name }}</span>
                <span class="tree-meta">（{{ data.child_count }}个KPI）</span>
                <span v-if="data.description" class="tree-desc">— {{ data.description }}</span>
              </template>
              <!-- 类别组 -->
              <template v-else-if="data.is_category_group">
                <el-tag size="small" type="success">{{ data.category_label }}</el-tag>
                <span v-if="data.feeds" class="tree-drive">→ 驱动 {{ feedLabels(data.feeds) }}</span>
                <span v-else class="tree-drive" style="color:#67c23a;">最终结果</span>
                <span class="tree-meta">（{{ data.child_count }}个）</span>
              </template>
              <!-- KPI节点 -->
              <template v-else>
                <span class="tree-level-dot" :class="'level-' + (data.alert_level || 'none')"></span>
                <span class="tree-code">{{ data.kpi_code }}</span>
                <span class="tree-name">{{ data.kpi_name }}</span>
                <span v-if="data.alignment_type === 'vertical_split'" class="tree-tag tag-amber">承接 {{ data.parent_code }}</span>
                <span v-if="data.drives" class="tree-tag tag-gray">→ {{ dimLabel(data.drives) }}</span>
                <!-- 目标值 -->
                <span class="tree-val" v-if="data.target_value != null">
                  目标：<strong>{{ fmtNum(data.target_value) }}</strong>{{ data.unit }}
                </span>
                <!-- 实际值 -->
                <span class="tree-val" v-if="data.actual_value != null" :class="statusClass(data)">
                  实绩：<strong>{{ fmtNum(data.actual_value) }}</strong>{{ data.unit }}
                </span>
                <span v-else class="tree-val tree-val-na">实绩：-</span>
                <!-- 偏差率 -->
                <span v-if="data.actual_value != null && data.target_value != null && data.target_value > 0"
                  class="tree-deviation" :class="devClass(data)">
                  {{ calcDev(data) }}
                </span>
              </template>
            </div>
          </template>
        </el-tree>
        <div v-else-if="!loading" style="text-align:center;padding:40px;color:#999;">
          暂无对齐数据，请先配置对齐模式
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'

const route = useRoute()
const router = useRouter()

const alignModes = ref<any[]>([])
const alignConfigured = ref(false)
const currentMode = ref<any>(null)
const selectedMode = ref('')
const saving = ref(false)
const loading = ref(false)
const treeData = ref<any>(null)
const showSelector = ref(false)

// 地图选择
const mapList = ref<any[]>([])
const selectedMapId = ref<number | null>(null)

async function loadMapList() {
  try {
    const token = localStorage.getItem('cma_token')
    const r = await fetch('/api/cma/maps', {
      headers: { 'Authorization': `'Bearer ' + token` },
    }).then(r => r.json())
    mapList.value = r.data || []
  } catch {}
}

function onMapChange(val: number | null) {
  selectedMapId.value = val
  // 更新URL（可选）
  if (val) {
    router.replace(`/alignment?map_id=${val}`)
  } else {
    router.replace('/alignment')
  }
  loadTree()
}

const selectedModeName = computed(() => {
  const m = alignModes.value.find(m => m.key === selectedMode.value)
  return m ? m.name : ''
})

// 统计
const kpiWithData = computed(() => {
  if (!treeData.value) return 0
  return countKpiField(treeData.value.tree || [], 'actual_value')
})
const redCount = computed(() => {
  if (!treeData.value) return 0
  return countAlert(treeData.value.tree || [], 'red')
})
const yellowCount = computed(() => {
  if (!treeData.value) return 0
  return countAlert(treeData.value.tree || [], 'yellow')
})
const latestPeriod = computed(() => {
  if (!treeData.value) return '-'
  return findLatestPeriod(treeData.value.tree || [])
})

function countKpiField(nodes: any[], field: string): number {
  let count = 0
  for (const n of nodes) {
    if (n.children) count += countKpiField(n.children, field)
    else if (n[field] != null) count++
  }
  return count
}
function countAlert(nodes: any[], level: string): number {
  let count = 0
  for (const n of nodes) {
    if (n.children) count += countAlert(n.children, level)
    else if (n.alert_level === level) count++
  }
  return count
}
function findLatestPeriod(nodes: any[]): string {
  let latest = ''
  for (const n of nodes) {
    if (n.children) {
      const sub = findLatestPeriod(n.children)
      if (sub > latest) latest = sub
    } else if (n.period && n.period > latest) {
      latest = n.period
    }
  }
  return latest
}

const dimColor = (dim: string) => {
  const colors: Record<string, string> = { finance: '#409eff', customer: '#67c23a', process: '#e6a23c', learning: '#f56c6c' }
  return colors[dim] || '#999'
}
const dimLabel = (dim: string) => {
  const labels: Record<string, string> = { finance: '财务', customer: '客户', process: '内部流程', learning: '学习成长', internal_process: '内部流程' }
  return labels[dim] || dim
}
const feedLabels = (feeds: string[] | null) => {
  if (!feeds) return ''
  const map: Record<string, string> = {
    supply_chain: '供应链效率', delivery_quality: '交付质量',
    customer_scale: '客户规模', customer_concentration: '客户集中度',
    customer_satisfaction: '客户满意', revenue_growth: '收入增长',
    profitability: '盈利水平', cost_control: '成本费用', asset_efficiency: '资产效率',
  }
  return feeds.map(f => map[f] || f).join('、')
}
const fmtNum = (v: number) => {
  if (v == null) return '-'
  if (v >= 10000) return (v / 10000).toFixed(1) + '万'
  if (Number.isInteger(v)) return v.toLocaleString()
  return v.toFixed(1)
}
const calcDev = (d: any) => {
  if (d.actual_value == null || d.target_value == null || d.target_value === 0) return ''
  const dev = ((d.actual_value - d.target_value) / d.target_value * 100)
  const sign = dev > 0 ? '+' : ''
  return `${sign}${dev.toFixed(1)}%`
}
const statusClass = (d: any) => {
  if (d.alert_level === 'red') return 'val-red'
  if (d.alert_level === 'yellow') return 'val-yellow'
  if (d.alert_level === 'green') return 'val-green'
  return ''
}
const devClass = (d: any) => {
  if (d.alert_level === 'red') return 'dev-red'
  if (d.alert_level === 'yellow') return 'dev-yellow'
  return 'dev-green'
}

async function loadConfig() {
  try {
    const r = await fetch('/api/cma/alignment/config').then(r => r.json())
    alignModes.value = r.modes || []
    alignConfigured.value = r.configured || false
    if (r.configured && r.mode) {
      currentMode.value = alignModes.value.find(m => m.key === r.mode.mode) || null
      selectedMode.value = r.mode.mode
    }
    showSelector.value = !r.configured
    if (r.configured) loadTree()
  } catch {}
}

async function saveAlignConfig() {
  if (!selectedMode.value) return
  saving.value = true
  try {
    const token = localStorage.getItem('cma_token')
    await fetch('/api/cma/alignment/config', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json', 'Authorization': `'Bearer ' + token` },
      body: JSON.stringify({ mode: selectedMode.value }),
    }).then(r => r.json())
    ElMessage.success('对齐模式已设置')
    currentMode.value = alignModes.value.find(m => m.key === selectedMode.value) || null
    alignConfigured.value = true
    showSelector.value = false
    loadTree()
  } catch { ElMessage.error('设置失败') }
  saving.value = false
}

async function loadTree() {
  loading.value = true
  try {
    const token = localStorage.getItem('cma_token')
    let url = '/api/cma/alignment/tree'
    if (selectedMapId.value) url += `?map_id=${selectedMapId.value}`
    const r = await fetch(url, {
      headers: { 'Authorization': `'Bearer ' + token` },
    }).then(r => r.json())
    treeData.value = r
  } catch (e: any) {
    ElMessage.error(e.message || '加载失败')
  }
  loading.value = false
}

onMounted(() => {
  loadConfig()
  loadMapList()
  // 如果URL有map_id参数，自动选中对应地图
  if (route.query.map_id) {
    const mid = Number(route.query.map_id)
    if (mid) {
      selectedMapId.value = mid
    }
  }
})
</script>

<style scoped>
.alignment-page { padding: 16px; height: 100%; overflow-y: auto; }
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.page-header h3 { margin: 0; font-size: 18px; font-weight: 600; }

.mode-card { cursor: pointer; transition: all 0.2s; border: 2px solid transparent; }
.mode-card:hover { border-color: #409eff; }
.selected-mode { border-color: #409eff; background: #f0f7ff; }

.tree-node-row { display: flex; align-items: center; gap: 6px; font-size: 13px; padding: 3px 0; flex-wrap: wrap; }
.tree-code { font-family: monospace; font-size: 11px; color: #909399; }
.tree-name { color: #303133; }
.tree-meta { font-size: 11px; color: #999; }
.tree-desc { font-size: 11px; color: #909399; }
.tree-drive { font-size: 11px; color: #e6a23c; }
.tree-tag { font-size: 11px; padding: 1px 6px; border-radius: 3px; }
.tag-amber { background: #fdf6ec; color: #e6a23c; }
.tag-gray { background: #f4f4f5; color: #909399; }
.tree-level-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.level-red { background: #f56c6c; }
.level-yellow { background: #e6a23c; }
.level-green { background: #67c23a; }
.level-none { background: #dcdfe6; }
.tree-val { font-size: 12px; color: #606266; margin-left: 4px; }
.tree-val-na { color: #ccc; }
.val-red { color: #f56c6c; }
.val-yellow { color: #e6a23c; }
.val-green { color: #67c23a; }
.tree-deviation { font-size: 11px; font-weight: 500; padding: 1px 5px; border-radius: 3px; }
.dev-red { background: #fef0f0; color: #f56c6c; }
.dev-yellow { background: #fdf6ec; color: #e6a23c; }
.dev-green { background: #f0f9eb; color: #67c23a; }
</style>
