<template>
  <div v-loading="loading" class="app-container home-dashboard">
    <section class="hero-panel">
      <div class="hero-copy">
        <p class="hero-eyebrow">Hawei Plus Overview</p>
        <h1>海威PLUS 运营概览</h1>
        <p class="hero-desc">
          首页直接展示当前系统最新监测快照与报警概况。所有卡片和图表都基于实时接口返回的真实数据生成，方便值班人员进入系统后先看到整体状态，再进入明细页面处理。
        </p>
        <div class="hero-tags">
          <el-tag effect="dark">实时快照</el-tag>
          <el-tag effect="plain">报警概览</el-tag>
          <el-tag effect="plain">分组分布</el-tag>
          <el-tag effect="plain">重点设备</el-tag>
        </div>
      </div>

      <div class="hero-side">
        <div class="hero-side-card">
          <span>最近刷新</span>
          <strong>{{ lastUpdateTime || '--' }}</strong>
          <p>按首页初始化时接口返回的最新时间戳展示。</p>
        </div>
        <div class="hero-side-card">
          <span>当前主看指标</span>
          <strong>{{ primaryMetricLabel }}</strong>
          <p>用于分组均值和设备快照排序的默认指标。</p>
        </div>
      </div>
    </section>

    <div class="overview-grid">
      <div v-for="item in overviewCards" :key="item.label" class="overview-card">
        <span class="overview-label">{{ item.label }}</span>
        <strong class="overview-value">{{ item.value }}</strong>
        <p class="overview-desc">{{ item.desc }}</p>
      </div>
    </div>

    <section class="glass-panel logic-panel">
      <div class="section-head">
        <div>
          <p class="section-eyebrow">Logic Notes</p>
          <h3>首页统计口径</h3>
        </div>
      </div>
      <div class="logic-grid">
        <div v-for="item in logicNotes" :key="item.title" class="logic-card">
          <div class="logic-title">{{ item.title }}</div>
          <p class="logic-desc">{{ item.desc }}</p>
        </div>
      </div>
    </section>

    <div class="chart-grid two-col">
      <article class="chart-card">
        <div class="chart-head">
          <h3>指标快照对比</h3>
          <p>以最新快照为样本，对比活跃指标的平均值与峰值。</p>
        </div>
        <Chart class="chart chart-lg" :chart-option="metricOverviewOption" />
      </article>

      <article class="chart-card">
        <div class="chart-head">
          <h3>报警处理概览</h3>
          <p>直接展示当前未处理、已处理和其余统计情况。</p>
        </div>
        <Chart class="chart chart-lg" :chart-option="alarmOverviewOption" />
      </article>
    </div>

    <div class="chart-grid two-col">
      <article class="chart-card">
        <div class="chart-head">
          <h3>分组设备概览</h3>
          <p>按设备树顶层分组统计设备数量，并对主看指标求最新均值。</p>
        </div>
        <Chart class="chart chart-md" :chart-option="groupOverviewOption" />
      </article>

      <article class="chart-card">
        <div class="chart-head">
          <h3>重点设备快照</h3>
          <p>按主看指标的最新值降序展示重点设备。</p>
        </div>
        <Chart class="chart chart-md" :chart-option="deviceSnapshotOption" />
      </article>
    </div>

    <section class="glass-panel table-panel">
      <div class="section-head">
        <div>
          <p class="section-eyebrow">Latest Snapshot</p>
          <h3>最新设备清单</h3>
        </div>
      </div>

      <div v-if="!latestRecords.length" class="empty-panel">
        <el-empty description="当前没有获取到最新快照数据" />
      </div>

      <el-table v-else :data="latestTableData" stripe class="snapshot-table">
        <el-table-column prop="monitorName" label="设备名称" min-width="180" />
        <el-table-column prop="groupLabel" label="所属分组" min-width="140" />
        <el-table-column prop="metricLabel" label="主看指标" min-width="120" />
        <el-table-column prop="metricValue" label="最新值" min-width="120" />
        <el-table-column prop="recodeTime" label="记录时间" min-width="180" />
      </el-table>
    </section>
  </div>
</template>

<script setup name="Index" lang="ts">
import Chart from '@/components/Charts/Chart.vue';
import type { EChartsOption } from 'echarts';
import { getRecordAlarmDataSummary } from '@/api/ems/record/recordAlarmData';
import { getLatestRecords } from '@/api/ems/record/recordIotenvInstant';
import { getMonitorInfoTree } from '@/api/ems/base/baseMonitorInfo';
import { formatValue } from './ems/report/iotReportShared';
import { normalizeIotCurveRecord, readMetricValue, resolveIotCurveMetrics } from './ems/report/iotCurveShared';

interface GroupSnapshotItem {
  label: string;
  deviceCount: number;
  avgValue: number;
}

const loading = ref(false);
const latestRecords = ref<any[]>([]);
const monitorTreeOptions = ref<any[]>([]);
const alarmSummary = ref<Record<string, number>>({});

const lastUpdateTime = computed(() => {
  return latestRecords.value.length ? latestRecords.value.map((item) => item.__timeKey).filter(Boolean).sort().at(-1) || '' : '';
});

const getLeafNodes = (nodes, rootLabel = '') => {
  let result = [];
  (nodes || []).forEach((item) => {
    const currentRootLabel = rootLabel || String(item.label || '未命名分组');
    if (Array.isArray(item.children) && item.children.length > 0) {
      result = result.concat(getLeafNodes(item.children, currentRootLabel));
      return;
    }
    if (item.code) {
      result.push({
        ...item,
        __rootLabel: currentRootLabel
      });
    }
  });
  return result;
};

const leafNodeMap = computed(() => {
  return getLeafNodes(monitorTreeOptions.value).reduce((accumulator, item) => {
    accumulator[String(item.code)] = item;
    return accumulator;
  }, {});
});

const metricConfigs = computed(() => {
  return resolveIotCurveMetrics(latestRecords.value, []);
});

const primaryMetric = computed(() => metricConfigs.value[0] || null);
const primaryMetricLabel = computed(() => (primaryMetric.value ? primaryMetric.value.label : '待识别'));

const metricStats = computed(() => {
  return metricConfigs.value.map((metric) => {
    const values = latestRecords.value.map((item) => readMetricValue(item, metric)).filter((item): item is number => item !== null);
    const latestValue = values.at(-1) ?? null;
    const avgValue = values.length ? values.reduce((sum, item) => sum + item, 0) / values.length : 0;
    const maxValue = values.length ? Math.max(...values) : 0;
    return {
      ...metric,
      latestValue,
      avgValue,
      maxValue,
      count: values.length
    };
  });
});

const groupSnapshot = computed<GroupSnapshotItem[]>(() => {
  if (!primaryMetric.value) {
    return [];
  }
  const bucket = {} as Record<string, number[]>;
  latestRecords.value.forEach((item) => {
    const monitorId = String(item.monitorId || item.monitorCode || '');
    const rootLabel = leafNodeMap.value[monitorId]?.__rootLabel || '未归类';
    const metricValue = readMetricValue(item, primaryMetric.value!);
    if (!bucket[rootLabel]) {
      bucket[rootLabel] = [];
    }
    if (metricValue !== null) {
      bucket[rootLabel].push(metricValue);
    }
  });

  return Object.keys(bucket).map((label) => ({
    label,
    deviceCount: getLeafNodes(monitorTreeOptions.value).filter((item) => item.__rootLabel === label).length,
    avgValue: bucket[label].length ? bucket[label].reduce((sum, item) => sum + item, 0) / bucket[label].length : 0
  }));
});

const latestTableData = computed(() => {
  return latestRecords.value.slice(0, 12).map((item) => {
    const monitorId = String(item.monitorId || item.monitorCode || '');
    const metricValue = primaryMetric.value ? readMetricValue(item, primaryMetric.value) : null;
    return {
      monitorName: String(item.monitorName || leafNodeMap.value[monitorId]?.label || monitorId),
      groupLabel: leafNodeMap.value[monitorId]?.__rootLabel || '未归类',
      metricLabel: primaryMetric.value?.label || '--',
      metricValue: primaryMetric.value?.unit ? `${formatValue(metricValue)} ${primaryMetric.value.unit}` : formatValue(metricValue),
      recodeTime: item.__timeKey || '--'
    };
  });
});

const overviewCards = computed(() => [
  {
    label: '最新设备数',
    value: latestRecords.value.length,
    desc: '来自最新快照接口返回的设备条数。'
  },
  {
    label: '活跃指标数',
    value: metricConfigs.value.length,
    desc: '根据最新快照里真实有值的字段自动识别。'
  },
  {
    label: '报警总数',
    value: Number(alarmSummary.value.totalCount || 0),
    desc: '来自报警概览接口的累计统计。'
  },
  {
    label: '未处理报警',
    value: Number(alarmSummary.value.unhandledCount || 0),
    desc: '优先关注待处理报警数量。'
  }
]);

const logicNotes = computed(() => [
  {
    title: '设备数口径',
    desc: '首页设备数直接使用最新快照接口返回条数，不做虚构补数。'
  },
  {
    title: '指标口径',
    desc: `活跃指标从最新快照里真实有值的字段识别得到，当前默认主看指标为 ${primaryMetricLabel.value}。`
  },
  {
    title: '分组口径',
    desc: '分组统计按设备树顶层节点聚合，分组均值使用主看指标在该分组最新快照中的平均值。'
  }
]);

const metricOverviewOption = computed<EChartsOption | null>(() => {
  if (!metricStats.value.length) {
    return null;
  }
  return {
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      top: 8,
      data: ['平均值', '峰值']
    },
    grid: {
      top: 54,
      left: '10%',
      right: '6%',
      bottom: 36
    },
    xAxis: {
      type: 'category',
      data: metricStats.value.map((item) => item.label)
    },
    yAxis: {
      type: 'value',
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    series: [
      {
        name: '平均值',
        type: 'bar',
        barWidth: 18,
        data: metricStats.value.map((item) => Number(item.avgValue.toFixed(2))),
        itemStyle: {
          color: '#2563eb',
          borderRadius: [6, 6, 0, 0]
        }
      },
      {
        name: '峰值',
        type: 'bar',
        barWidth: 18,
        data: metricStats.value.map((item) => Number(item.maxValue.toFixed(2))),
        itemStyle: {
          color: '#14b8a6',
          borderRadius: [6, 6, 0, 0]
        }
      }
    ]
  };
});

const alarmOverviewOption = computed<EChartsOption>(() => {
  const totalCount = Number(alarmSummary.value.totalCount || 0);
  const unhandledCount = Number(alarmSummary.value.unhandledCount || 0);
  const handledCount = Number(alarmSummary.value.handledCount || 0);
  return {
    tooltip: {
      trigger: 'item'
    },
    legend: {
      bottom: 0
    },
    series: [
      {
        type: 'pie',
        radius: ['48%', '72%'],
        center: ['50%', '48%'],
        label: {
          formatter: '{b}\n{c}'
        },
        data: [
          { name: '未处理', value: unhandledCount, itemStyle: { color: '#ef4444' } },
          { name: '已处理', value: handledCount, itemStyle: { color: '#22c55e' } },
          { name: '其余', value: Math.max(totalCount - unhandledCount - handledCount, 0), itemStyle: { color: '#94a3b8' } }
        ]
      }
    ]
  };
});

const groupOverviewOption = computed<EChartsOption | null>(() => {
  if (!groupSnapshot.value.length) {
    return null;
  }
  return {
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      top: 8,
      data: ['设备数', `${primaryMetricLabel.value}均值`]
    },
    grid: {
      top: 56,
      left: '10%',
      right: '8%',
      bottom: 40
    },
    xAxis: {
      type: 'category',
      data: groupSnapshot.value.map((item) => item.label)
    },
    yAxis: [
      { type: 'value', name: '设备数' },
      { type: 'value', name: `${primaryMetricLabel.value}均值` }
    ],
    series: [
      {
        name: '设备数',
        type: 'bar',
        barWidth: 18,
        data: groupSnapshot.value.map((item) => item.deviceCount),
        itemStyle: {
          color: '#0f766e',
          borderRadius: [6, 6, 0, 0]
        }
      },
      {
        name: `${primaryMetricLabel.value}均值`,
        type: 'line',
        yAxisIndex: 1,
        smooth: true,
        data: groupSnapshot.value.map((item) => Number(item.avgValue.toFixed(2))),
        lineStyle: {
          color: '#2563eb',
          width: 3
        },
        itemStyle: {
          color: '#2563eb'
        }
      }
    ]
  };
});

const deviceSnapshotOption = computed<EChartsOption | null>(() => {
  if (!primaryMetric.value) {
    return null;
  }
  const topDevices = latestRecords.value
    .map((item) => {
      const monitorId = String(item.monitorId || item.monitorCode || '');
      return {
        monitorId,
        monitorName: String(item.monitorName || leafNodeMap.value[monitorId]?.label || monitorId),
        value: readMetricValue(item, primaryMetric.value!)
      };
    })
    .filter((item) => item.value !== null)
    .sort((left, right) => Number(right.value) - Number(left.value))
    .slice(0, 10);

  return {
    tooltip: {
      trigger: 'axis'
    },
    grid: {
      top: 20,
      left: '18%',
      right: '6%',
      bottom: 36
    },
    xAxis: {
      type: 'value',
      name: primaryMetric.value.unit ? `${primaryMetric.value.label}(${primaryMetric.value.unit})` : primaryMetric.value.label
    },
    yAxis: {
      type: 'category',
      data: topDevices.map((item) => item.monitorName.length > 12 ? `${item.monitorName.slice(0, 11)}...` : item.monitorName)
    },
    series: [
      {
        type: 'bar',
        data: topDevices.map((item) => item.value),
        itemStyle: {
          color: primaryMetric.value.color,
          borderRadius: [0, 6, 6, 0]
        }
      }
    ]
  };
});

const loadDashboard = async () => {
  loading.value = true;
  try {
    const [latestRes, alarmRes, treeRes] = await Promise.all([getLatestRecords(), getRecordAlarmDataSummary(), getMonitorInfoTree({})]);
    latestRecords.value = (latestRes.data || []).map((item) => normalizeIotCurveRecord(item));
    alarmSummary.value = (alarmRes.data || {}) as Record<string, number>;
    monitorTreeOptions.value = treeRes.data || [];
  } finally {
    loading.value = false;
  }
};

onMounted(() => {
  void loadDashboard();
});
</script>

<style lang="scss" scoped>
.home-dashboard {
  min-height: calc(100vh - 84px);
  background:
    radial-gradient(circle at top right, rgba(37, 99, 235, 0.14), transparent 24%),
    radial-gradient(circle at top left, rgba(20, 184, 166, 0.1), transparent 28%),
    linear-gradient(180deg, #f4f8ff 0%, #f8fafc 100%);
}

.hero-panel,
.glass-panel,
.chart-card,
.overview-card {
  border-radius: 24px;
  border: 1px solid rgba(148, 163, 184, 0.18);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(12px);
  box-shadow: 0 18px 48px rgba(15, 23, 42, 0.08);
}

.hero-panel {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) 320px;
  gap: 20px;
  padding: 28px;
  margin-bottom: 18px;
  background:
    linear-gradient(135deg, rgba(15, 118, 110, 0.96), rgba(37, 99, 235, 0.92)),
    linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0));
  color: #ffffff;
}

.hero-eyebrow,
.section-eyebrow {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.hero-eyebrow {
  color: rgba(255, 255, 255, 0.72);
}

.hero-panel h1,
.section-head h3,
.chart-head h3 {
  margin: 0;
}

.hero-panel h1 {
  font-size: 34px;
  line-height: 1.2;
}

.hero-desc {
  margin: 16px 0 0;
  max-width: 760px;
  line-height: 1.8;
  color: rgba(255, 255, 255, 0.84);
}

.hero-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}

.hero-side {
  display: grid;
  gap: 16px;
}

.hero-side-card {
  padding: 18px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.18);
}

.hero-side-card span {
  display: block;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.72);
}

.hero-side-card strong {
  display: block;
  margin-top: 10px;
  font-size: 22px;
  font-weight: 700;
}

.hero-side-card p {
  margin: 10px 0 0;
  color: rgba(255, 255, 255, 0.78);
  line-height: 1.6;
  font-size: 12px;
}

.overview-grid,
.logic-grid,
.chart-grid {
  display: grid;
  gap: 16px;
}

.overview-grid {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-bottom: 18px;
}

.overview-card {
  padding: 18px;
}

.overview-label {
  display: block;
  color: #64748b;
  font-size: 12px;
}

.overview-value {
  display: block;
  margin-top: 12px;
  font-size: 28px;
  font-weight: 700;
  color: #0f172a;
}

.overview-desc {
  margin: 10px 0 0;
  color: #64748b;
  line-height: 1.6;
  font-size: 13px;
}

.glass-panel,
.table-panel {
  padding: 18px 20px;
  margin-bottom: 18px;
}

.section-head,
.chart-head {
  margin-bottom: 14px;
}

.section-eyebrow {
  color: #2563eb;
}

.logic-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.logic-card {
  padding: 16px;
  border-radius: 18px;
  border: 1px solid rgba(226, 232, 240, 0.92);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.94)),
    linear-gradient(135deg, rgba(37, 99, 235, 0.05), rgba(20, 184, 166, 0.04));
}

.logic-title {
  color: #0f172a;
  font-size: 15px;
  font-weight: 700;
}

.logic-desc {
  margin: 10px 0 0;
  color: #64748b;
  line-height: 1.7;
  font-size: 13px;
}

.two-col {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin-bottom: 18px;
}

.chart-card {
  padding: 16px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.94)),
    linear-gradient(135deg, rgba(37, 99, 235, 0.05), rgba(20, 184, 166, 0.04));
}

.chart-head p {
  margin: 6px 0 0;
  color: #64748b;
  line-height: 1.6;
  font-size: 12px;
}

.chart {
  width: 100%;
}

.chart-lg {
  height: 42vh;
  min-height: 320px;
}

.chart-md {
  height: 38vh;
  min-height: 280px;
}

.empty-panel {
  padding: 32px 0;
}

@media (max-width: 1200px) {
  .hero-panel,
  .overview-grid,
  .logic-grid,
  .two-col {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 768px) {
  .hero-panel,
  .glass-panel,
  .chart-card,
  .overview-card {
    padding: 16px;
    border-radius: 20px;
  }

  .hero-panel h1 {
    font-size: 26px;
  }
}
</style>
