<template>
  <div class="page-shell jdr-page">
    <section class="page-hero jdr-hero">
      <div class="page-eyebrow">JD-R Theory</div>
      <h1 class="page-title">JD-R 理论驱动的可解释分析</h1>
      <p class="page-description">
        基于工作要求-资源模型，从心理学理论视角解析员工缺勤的深层驱动因素，提供可解释的干预建议。
      </p>
    </section>

    <el-tabs v-model="activeTab" type="border-card" class="jdr-tabs">
      <!-- Tab 1: JD-R 维度分析 -->
      <el-tab-pane label="维度分析" name="dimensions">
        <el-row :gutter="20">
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">JD-R 维度雷达图</h3>
                <p class="section-caption">工作要求、工作资源与个人资源三维度均值对比</p>
              </template>
              <div v-if="dimensionData" ref="radarChartRef" style="height: 380px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">维度分布统计</h3>
                <p class="section-caption">各维度的均值、标准差与平衡度</p>
              </template>
              <div v-if="dimensionData" class="dim-stats">
                <div v-for="(item, key) in dimensionLabels" :key="key" class="dim-stat-row">
                  <div class="dim-stat-label">{{ item.label }}</div>
                  <div class="dim-stat-value">{{ dimensionData[key]?.mean || '-' }}</div>
                  <div class="dim-stat-sub">std: {{ dimensionData[key]?.std || '-' }}</div>
                </div>
                <div v-if="dimensionData?.balance" class="dim-stat-row dim-stat-balance">
                  <div class="dim-stat-label">JD-R 平衡度</div>
                  <div class="dim-stat-value">{{ dimensionData.balance.mean }}</div>
                  <div class="dim-stat-sub">正向比例: {{ dimensionData.balance.positive_ratio }}%</div>
                </div>
              </div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
        </el-row>
      </el-tab-pane>

      <!-- Tab 2: 倦怠与投入 -->
      <el-tab-pane label="倦怠与投入" name="burnout">
        <el-row :gutter="20">
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">倦怠与投入分布</h3>
                <p class="section-caption">工作倦怠(1-7)和工作投入(1-7)的分布对比</p>
              </template>
              <div v-if="burnoutData" ref="burnoutChartRef" style="height: 380px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">关键相关性</h3>
                <p class="section-caption">JD-R 维度与缺勤时长之间的关联强度</p>
              </template>
              <div v-if="burnoutData" ref="corrChartRef" style="height: 380px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
        </el-row>
      </el-tab-pane>

      <!-- Tab 3: 双路径分析 -->
      <el-tab-pane label="双路径分析" name="path">
        <el-row :gutter="20">
          <el-col :xs="24" :lg="14">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">JD-R 双路径理论模型</h3>
                <p class="section-caption">健康损伤路径(需求→倦怠→缺勤)与激励路径(资源→投入→低缺勤)</p>
              </template>
              <div class="path-diagram">
                <div class="path-flow">
                  <div class="path-section">
                    <div class="path-title">健康损伤路径</div>
                    <div class="path-nodes">
                      <div class="path-node node-demand">工作要求</div>
                      <div class="path-arrow">&rarr;</div>
                      <div class="path-node node-burnout">工作倦怠</div>
                      <div class="path-arrow">&rarr;</div>
                      <div class="path-node node-absence">缺勤时长</div>
                    </div>
                    <div v-if="pathData?.health_impairment" class="path-stats">
                      <span>直接效应: {{ pathData.health_impairment.direct_effect_demands }}</span>
                      <span>中介效应: {{ pathData.health_impairment.indirect_via_burnout }}</span>
                      <span>中介比例: {{ (pathData.health_impairment.mediation_ratio * 100).toFixed(1) }}%</span>
                    </div>
                  </div>
                  <div class="path-divider"></div>
                  <div class="path-section">
                    <div class="path-title">激励路径</div>
                    <div class="path-nodes">
                      <div class="path-node node-resource">工作资源</div>
                      <div class="path-arrow">&rarr;</div>
                      <div class="path-node node-engagement">工作投入</div>
                      <div class="path-arrow">&rarr;</div>
                      <div class="path-node node-absence-low">低缺勤</div>
                    </div>
                    <div v-if="pathData?.motivational" class="path-stats">
                      <span>直接效应: {{ pathData.motivational.direct_effect_resources }}</span>
                      <span>中介效应: {{ pathData.motivational.indirect_via_engagement }}</span>
                      <span>中介比例: {{ (pathData.motivational.mediation_ratio * 100).toFixed(1) }}%</span>
                    </div>
                  </div>
                </div>
              </div>
            </el-card>
          </el-col>
          <el-col :xs="24" :lg="10">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">风险等级分布</h3>
                <p class="section-caption">全员缺勤风险等级统计</p>
              </template>
              <div v-if="riskData" ref="riskChartRef" style="height: 320px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
        </el-row>
      </el-tab-pane>

      <!-- Tab 4: SHAP 解释 -->
      <el-tab-pane label="SHAP 解释" name="shap">
        <el-row :gutter="20">
          <el-col :xs="24" :lg="14">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <div class="section-heading" style="margin-bottom:0">
                  <div>
                    <h3 class="section-title">全局特征重要性 (SHAP)</h3>
                    <p class="section-caption">按 SHAP 值排列的特征贡献度</p>
                  </div>
                  <el-select v-model="shapModel" size="small" style="width: 160px" @change="loadShapGlobal">
                    <el-option label="随机森林" value="random_forest" />
                    <el-option label="XGBoost" value="xgboost" />
                    <el-option label="LightGBM" value="lightgbm" />
                    <el-option label="GBDT" value="gradient_boosting" />
                  </el-select>
                </div>
              </template>
              <div v-if="shapGlobalData" ref="shapGlobalRef" style="height: 420px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
          <el-col :xs="24" :lg="10">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">维度贡献占比</h3>
                <p class="section-caption">按 JD-R 理论维度聚合的 SHAP 贡献</p>
              </template>
              <div v-if="shapGlobalData" ref="shapDimPieRef" style="height: 420px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
        </el-row>
        <el-row :gutter="20" style="margin-top: 20px">
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">特征依赖图</h3>
                <p class="section-caption">选择特征查看其取值与 SHAP 值的关系</p>
              </template>
              <div style="margin-bottom: 12px">
                <el-select v-model="dependenceFeature" size="small" style="width: 200px" @change="loadDependence">
                  <el-option v-for="f in shapTopFeatures" :key="f.name" :label="f.name_cn" :value="f.name" />
                </el-select>
              </div>
              <div v-if="shapGlobalData" ref="shapDependenceRef" style="height: 320px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
          <el-col :xs="24" :lg="12">
            <el-card class="panel-card" shadow="never">
              <template #header>
                <h3 class="section-title">特征交互强度</h3>
                <p class="section-caption">Top 特征对的交互效应</p>
              </template>
              <div v-if="shapGlobalData" ref="shapInteractionRef" style="height: 320px"></div>
              <el-empty v-else description="加载中..." />
            </el-card>
          </el-col>
        </el-row>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import { nextTick, onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts'
import { ElMessage } from 'element-plus'
import { getDimensions, getBurnoutEngagement, getPathAnalysis, getRiskDistribution } from '@/api/jdr'
import { getGlobalImportance, getInteractions, getDependence } from '@/api/shap'

const activeTab = ref('dimensions')

// 数据
const dimensionData = ref(null)
const burnoutData = ref(null)
const pathData = ref(null)
const riskData = ref(null)
const shapGlobalData = ref(null)
const shapTopFeatures = ref([])
const shapModel = ref('random_forest')
const dependenceFeature = ref('月均加班时长')

// 图表 DOM ref
const radarChartRef = ref(null)
const burnoutChartRef = ref(null)
const corrChartRef = ref(null)
const riskChartRef = ref(null)
const shapGlobalRef = ref(null)
const shapDimPieRef = ref(null)
const shapDependenceRef = ref(null)
const shapInteractionRef = ref(null)

const dimensionLabels = {
  demands: { label: '工作要求指数', color: '#ef4444' },
  resources: { label: '工作资源指数', color: '#22c55e' },
  personal: { label: '个人资源指数', color: '#3b82f6' },
}

function getOrCreateChart(el) {
  if (!el) return null
  let chart = echarts.getInstanceByDom(el)
  if (!chart) chart = echarts.init(el)
  return chart
}

// 延迟渲染：等待 Vue 将 v-if 的 DOM 插入到页面
function scheduleRender(fn) {
  requestAnimationFrame(() => {
    nextTick().then(fn)
  })
}

// ── Tab 1: 维度分析 ──
async function loadDimensions() {
  try {
    dimensionData.value = await getDimensions()
    scheduleRender(renderRadarChart)
  } catch (e) {
    ElMessage.error('加载维度数据失败')
  }
}

function renderRadarChart() {
  const chart = getOrCreateChart(radarChartRef.value)
  if (!chart || !dimensionData.value) { console.warn('radarChart: DOM or data missing'); return }

  const dims = dimensionData.value
  const indicators = [
    { name: '工作要求', max: 10 },
    { name: '工作资源', max: 5 },
    { name: '个人资源', max: 5 },
    { name: 'JD-R平衡度', max: 5 },
  ]
  const values = [
    dims.demands?.mean || 0,
    dims.resources?.mean || 0,
    dims.personal?.mean || 0,
    dims.balance?.mean || 0,
  ]

  chart.setOption({
    tooltip: {},
    radar: { indicator: indicators, shape: 'circle', splitNumber: 5 },
    series: [{
      type: 'radar',
      data: [{
        value: values,
        name: 'JD-R 维度均值',
        areaStyle: { color: 'rgba(15, 118, 110, 0.2)' },
        lineStyle: { color: '#0f766e', width: 2 },
        itemStyle: { color: '#0f766e' },
      }],
    }],
  })
}

// ── Tab 2: 倦怠与投入 ──
async function loadBurnout() {
  try {
    burnoutData.value = await getBurnoutEngagement()
    scheduleRender(() => { renderBurnoutChart(); renderCorrChart() })
  } catch (e) {
    ElMessage.error('加载倦怠/投入数据失败')
  }
}

function renderBurnoutChart() {
  const chart = getOrCreateChart(burnoutChartRef.value)
  if (!chart || !burnoutData.value) { console.warn('burnoutChart: DOM or data missing'); return }

  const bDist = burnoutData.value.burnout?.distribution || []
  const eDist = burnoutData.value.engagement?.distribution || []
  const categories = bDist.map(d => d.range)

  chart.setOption({
    tooltip: { trigger: 'axis' },
    legend: { data: ['工作倦怠', '工作投入'] },
    xAxis: { type: 'category', data: categories },
    yAxis: { type: 'value', name: '人数' },
    series: [
      {
        name: '工作倦怠', type: 'bar', data: bDist.map(d => d.count),
        itemStyle: { color: '#ef4444' }, barWidth: '30%',
      },
      {
        name: '工作投入', type: 'bar', data: eDist.map(d => d.count),
        itemStyle: { color: '#22c55e' }, barWidth: '30%',
      },
    ],
  })
}

function renderCorrChart() {
  const chart = getOrCreateChart(corrChartRef.value)
  if (!chart || !burnoutData.value?.correlations) { console.warn('corrChart: DOM or data missing'); return }

  const corrs = burnoutData.value.correlations
  const items = [
    { name: '要求→倦怠', value: corrs.demands_vs_burnout },
    { name: '资源→投入', value: corrs.resources_vs_engagement },
    { name: '倦怠→缺勤', value: corrs.burnout_vs_absence_hours },
    { name: '投入→缺勤', value: corrs.engagement_vs_absence_hours },
    { name: '要求→缺勤', value: corrs.demands_vs_absence_hours },
    { name: '资源→缺勤', value: corrs.resources_vs_absence_hours },
  ].filter(i => i.value !== undefined)

  chart.setOption({
    tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
    xAxis: { type: 'value', name: '相关系数', min: -1, max: 1 },
    yAxis: { type: 'category', data: items.map(i => i.name) },
    series: [{
      type: 'bar', data: items.map(i => ({
        value: i.value,
        itemStyle: { color: i.value >= 0 ? '#22c55e' : '#ef4444' },
      })),
    }],
  })
}

// ── Tab 3: 双路径 ──
async function loadPathAndRisk() {
  try {
    const [path, risk] = await Promise.all([getPathAnalysis(), getRiskDistribution()])
    pathData.value = path
    riskData.value = risk
    scheduleRender(renderRiskChart)
  } catch (e) {
    ElMessage.error('加载路径分析失败')
  }
}

function renderRiskChart() {
  const chart = getOrCreateChart(riskChartRef.value)
  if (!chart || !riskData.value?.levels) { console.warn('riskChart: DOM or data missing'); return }

  const levels = riskData.value.levels
  chart.setOption({
    tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
    series: [{
      type: 'pie', radius: ['40%', '70%'],
      data: levels.map(l => ({
        name: l.label, value: l.count,
        itemStyle: { color: l.color },
      })),
      label: { formatter: '{b}\n{d}%' },
    }],
  })
}

// ── Tab 4: SHAP ──
async function loadShapGlobal() {
  try {
    const data = await getGlobalImportance(shapModel.value)
    if (data.error) { ElMessage.error(data.error); return }
    shapGlobalData.value = data
    shapTopFeatures.value = data.top_features || []
    if (shapTopFeatures.value.length && !dependenceFeature.value) {
      dependenceFeature.value = shapTopFeatures.value[0].name
    }
    scheduleRender(() => {
      renderShapGlobalChart()
      renderShapDimPie()
      loadDependence()
      loadInteractions()
    })
  } catch (e) {
    ElMessage.error('加载 SHAP 数据失败')
  }
}

function renderShapGlobalChart() {
  const chart = getOrCreateChart(shapGlobalRef.value)
  if (!chart || !shapGlobalData.value?.top_features) { console.warn('shapGlobal: DOM or data missing'); return }

  const features = shapGlobalData.value.top_features.slice(0, 15).reverse()
  const dimColors = {
    job_demands: '#ef4444',
    job_resources: '#22c55e',
    personal_resources: '#3b82f6',
    mediators: '#f59e0b',
    event_context: '#8b5cf6',
    other: '#6b7280',
  }

  chart.setOption({
    tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
    grid: { left: 140, right: 30, top: 10, bottom: 30 },
    xAxis: { type: 'value', name: 'Mean |SHAP|' },
    yAxis: { type: 'category', data: features.map(f => f.name_cn) },
    series: [{
      type: 'bar', data: features.map(f => ({
        value: f.importance,
        itemStyle: { color: dimColors[f.dimension] || '#6b7280' },
      })),
    }],
  })
}

function renderShapDimPie() {
  const chart = getOrCreateChart(shapDimPieRef.value)
  if (!chart || !shapGlobalData.value?.dimensions) { console.warn('shapDimPie: DOM or data missing'); return }

  const dims = shapGlobalData.value.dimensions
  const dimColorMap = {
    job_demands: '#ef4444',
    job_resources: '#22c55e',
    personal_resources: '#3b82f6',
    mediators: '#f59e0b',
    event_context: '#8b5cf6',
  }
  const pieData = Object.entries(dims).map(([key, info]) => {
    const total = info.features.reduce((s, f) => s + f.importance, 0)
    return { name: info.name_cn, value: parseFloat(total.toFixed(4)), itemStyle: { color: dimColorMap[key] || '#6b7280' } }
  })

  chart.setOption({
    tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
    series: [{
      type: 'pie', radius: ['35%', '65%'],
      data: pieData,
      label: { formatter: '{b}\n{d}%' },
    }],
  })
}

async function loadDependence() {
  if (!dependenceFeature.value) return
  try {
    const data = await getDependence(dependenceFeature.value, shapModel.value)
    if (data.error) return
    await nextTick()
    const chart = getOrCreateChart(shapDependenceRef.value)
    if (!chart) return

    const points = data.values.map((v, i) => [v, data.shap_values[i]])
    chart.setOption({
      tooltip: { trigger: 'item', formatter: (p) => `值: ${p.data[0].toFixed(2)}<br/>SHAP: ${p.data[1].toFixed(4)}` },
      grid: { left: 60, right: 20, top: 20, bottom: 40 },
      xAxis: { type: 'value', name: data.feature_cn },
      yAxis: { type: 'value', name: 'SHAP value' },
      series: [{
        type: 'scatter', data: points, symbolSize: 5,
        itemStyle: { color: '#0f766e', opacity: 0.6 },
      }],
    })
  } catch (e) { /* ignore */ }
}

async function loadInteractions() {
  try {
    const data = await getInteractions(shapModel.value, 10)
    if (data.error || !data.top_interactions) return
    await nextTick()
    const chart = getOrCreateChart(shapInteractionRef.value)
    if (!chart) return

    const interactions = data.top_interactions.slice(0, 8)
    chart.setOption({
      tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
      grid: { left: 160, right: 20, top: 10, bottom: 30 },
      xAxis: { type: 'value', name: '交互强度' },
      yAxis: { type: 'category', data: interactions.map(i => `${i.feature_1_cn} x ${i.feature_2_cn}`) },
      series: [{
        type: 'bar', data: interactions.map(i => i.strength),
        itemStyle: { color: '#f59e0b' },
      }],
    })
  } catch (e) { /* ignore */ }
}

// Tab 切换时重新渲染图表（等待 DOM 就绪）
watch(activeTab, async (tab) => {
  await nextTick()
  requestAnimationFrame(async () => {
    await nextTick()
    if (tab === 'dimensions') {
      if (dimensionData.value) renderRadarChart()
      else loadDimensions()
    }
    if (tab === 'burnout') {
      if (burnoutData.value) { renderBurnoutChart(); renderCorrChart() }
      else loadBurnout()
    }
    if (tab === 'path') {
      if (riskData.value) renderRiskChart()
      else loadPathAndRisk()
    }
    if (tab === 'shap') {
      if (shapGlobalData.value) { renderShapGlobalChart(); renderShapDimPie(); loadDependence(); loadInteractions() }
      else loadShapGlobal()
    }
  })
})

onMounted(() => {
  loadDimensions()
  loadBurnout()
  loadPathAndRisk()
  loadShapGlobal()
})
</script>

<style scoped>
.jdr-hero {
  background: linear-gradient(135deg, rgba(15, 23, 42, 0.96), rgba(59, 130, 246, 0.92) 50%, rgba(15, 118, 110, 0.88));
}

.jdr-tabs {
  border-radius: 18px;
  overflow: hidden;
}

.jdr-tabs :deep(.el-tabs__content) {
  padding: 20px;
}

.dim-stats {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.dim-stat-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.76);
}

.dim-stat-label {
  flex: 1;
  font-size: 14px;
  font-weight: 600;
  color: var(--text-main);
}

.dim-stat-value {
  font-size: 22px;
  font-weight: 700;
  color: #0f766e;
}

.dim-stat-sub {
  font-size: 12px;
  color: var(--text-subtle);
}

.dim-stat-balance {
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.08), rgba(255, 255, 255, 0.9));
}

.path-diagram {
  padding: 20px 0;
}

.path-flow {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.path-section {
  padding: 24px;
  border: 1px solid var(--line-soft);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.76);
}

.path-title {
  margin-bottom: 16px;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-main);
}

.path-nodes {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-bottom: 16px;
}

.path-node {
  padding: 12px 20px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
}

.node-demand { background: #ef4444; }
.node-burnout { background: #f59e0b; }
.node-absence { background: #dc2626; }
.node-resource { background: #22c55e; }
.node-engagement { background: #0f766e; }
.node-absence-low { background: #3b82f6; }

.path-arrow {
  font-size: 20px;
  font-weight: 700;
  color: var(--text-subtle);
}

.path-stats {
  display: flex;
  justify-content: center;
  gap: 24px;
  padding-top: 14px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px;
  color: var(--text-subtle);
}

.path-divider {
  height: 1px;
  background: var(--line-soft);
  margin: 0 40px;
}

.section-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

:deep(.panel-card .el-card__header) {
  padding-bottom: 0;
  border-bottom: none;
}
</style>
