<template>
  <div class="app-container">
    <el-card shadow="never">
      <el-form :inline="true" :model="queryForm" size="small">
        <el-form-item label="时间范围">
          <el-date-picker
            v-model="timeRange"
            type="datetimerange"
            value-format="YYYY-MM-DD HH:mm:ss"
            range-separator="至"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            style="width: 380px"
          />
        </el-form-item>
        <el-form-item label="采样间隔阈值">
          <el-input-number v-model="queryForm.gapThresholdSeconds" :min="60" :max="86400" :step="60" style="width: 140px" />
          <span class="ml-1 text-xs text-gray-400">秒</span>
        </el-form-item>
        <el-form-item label="预期采样数">
          <el-input-number v-model="queryForm.expectedSampleCount" :min="1" :max="100000" style="width: 140px" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-row :gutter="16" class="mt-4">
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">入库延迟分布</span>
              <HelpButton title="入库延迟分布" :content="QUALITY_HELP" />
            </div>
          </template>
          <div ref="delayDistChartRef" class="chart-container" />
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">数据完整率</span>
              <HelpButton title="数据完整率" :content="QUALITY_HELP" />
            </div>
          </template>
          <el-table :data="completenessList" stripe size="small" max-height="300">
            <el-table-column prop="monitorName" label="测点" show-overflow-tooltip />
            <el-table-column prop="actualCount" label="实际数" width="80" align="right" />
            <el-table-column prop="completenessRate" label="完整率" width="120" align="right">
              <template #default="{ row }">
                <el-progress
                  :percentage="Math.round((row.completenessRate ?? 0) * 100)"
                  :stroke-width="12"
                  :color="row.completenessRate >= 0.9 ? '#67c23a' : row.completenessRate >= 0.7 ? '#e6a23c' : '#f56c6c'"
                />
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
    </el-row>

    <el-card shadow="never" class="mt-4">
      <template #header>
        <div class="card-header">
          <span class="font-bold">时间逆序可疑数据（recodeTime &lt; collectTime）</span>
          <div class="flex items-center gap-2">
            <el-tag type="danger" size="small">{{ timeReversalPage.total }} 条</el-tag>
            <HelpButton title="时间逆序可疑数据" :content="QUALITY_HELP" />
          </div>
        </div>
      </template>
      <div class="table-v2-wrapper">
        <el-auto-resizer>
          <template #default="{ width, height }">
            <el-table-v2
              :columns="timeReversalColumns"
              :data="timeReversalList"
              :width="width"
              :height="height"
              :row-height="40"
              :header-height="40"
            />
          </template>
        </el-auto-resizer>
      </div>
      <div class="pagination-wrapper">
        <el-pagination
          background
          layout="total, sizes, prev, pager, next"
          :total="timeReversalPage.total"
          :page-size="timeReversalPage.pageSize"
          :page-sizes="PAGE_SIZE_OPTIONS"
          :current-page="timeReversalPage.pageNum"
          @current-change="handleTimeReversalPageChange"
          @size-change="handleTimeReversalSizeChange"
        />
      </div>
    </el-card>

    <el-row :gutter="16" class="mt-4">
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">
                采样间隔异常
                <!-- 总数显著暴露，大批量时方便运维快速定位。 -->
                <el-tag type="warning" size="small" class="ml-2">{{ samplingGapPage.total }} 条</el-tag>
              </span>
              <HelpButton title="采样间隔异常" :content="QUALITY_HELP" />
            </div>
          </template>
          <!--
            通讯抖动 / 断点重传 / 时间同步异常时这张表容易映射上万行，
            原先普通 el-table 会把它们一次性渲染到 DOM；现升级到虚拟滚动表，
            配合 OFFSET/FETCH 分页使浏览器只处理视窗内的若干行。
          -->
          <div class="table-v2-wrapper-sm">
            <el-auto-resizer>
              <template #default="{ width, height }">
                <el-table-v2
                  :columns="samplingGapColumns"
                  :data="samplingGapList"
                  :width="width"
                  :height="height"
                  :row-height="40"
                  :header-height="40"
                />
              </template>
            </el-auto-resizer>
          </div>
          <div class="pagination-wrapper">
            <el-pagination
              background
              layout="total, sizes, prev, pager, next"
              :total="samplingGapPage.total"
              :page-size="samplingGapPage.pageSize"
              :page-sizes="PAGE_SIZE_OPTIONS"
              :current-page="samplingGapPage.pageNum"
              @current-change="handleSamplingGapPageChange"
              @size-change="handleSamplingGapSizeChange"
            />
          </div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="12">
        <el-card shadow="never">
          <template #header>
            <div class="card-header">
              <span class="font-bold">测点活跃度</span>
              <HelpButton title="测点活跃度" :content="QUALITY_HELP" />
            </div>
          </template>
          <el-table :data="activityList" stripe size="small" max-height="300">
            <el-table-column prop="monitorName" label="测点" show-overflow-tooltip />
            <el-table-column prop="actualCount" label="样本数" width="80" align="right" />
            <el-table-column prop="firstTime" label="首次" width="160" />
            <el-table-column prop="lastTime" label="末次" width="160" />
          </el-table>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { h, ref, reactive, onMounted, nextTick } from 'vue';
import { ElTag } from 'element-plus';
import * as echarts from 'echarts';
import {
  getDelayDistribution,
  getTimeReversal,
  getSamplingGapAnomalies,
  getCompletenessRate,
  getMonitorActivity
} from '@/api/ems/report/tempBoard';
import type { TempBoardQuery, TempBoardQualityVO } from '@/api/ems/report/tempBoard';
import HelpButton from '../components/HelpButton.vue';
import { QUALITY_HELP } from '../components/helpContent';
import { useChartResize } from '../components/useChartResize';

defineOptions({ name: 'TempBoardQuality' });

type PageState = {
  pageNum: number;
  pageSize: number;
  total: number;
};

const timeRange = ref<[string, string]>(['', '']);
const queryForm = reactive<TempBoardQuery>({ gapThresholdSeconds: 300, expectedSampleCount: 1440 });
const loading = ref(false);
const delayDistChartRef = ref<HTMLElement>();
const timeReversalList = ref<TempBoardQualityVO[]>([]);
const samplingGapList = ref<TempBoardQualityVO[]>([]);
const completenessList = ref<TempBoardQualityVO[]>([]);
const activityList = ref<TempBoardQualityVO[]>([]);
const timeReversalPage = reactive<PageState>({ pageNum: 1, pageSize: 20, total: 0 });
// 采样间隔异常同样引入分页模型，跟时间逆序保持一致。
const samplingGapPage = reactive<PageState>({ pageNum: 1, pageSize: 20, total: 0 });

// 与 anomaly 页保持一致的分页区间选项。
const PAGE_SIZE_OPTIONS = [20, 50, 100];

const { getChart } = useChartResize(delayDistChartRef);

// 采样间隔列：用虚拟滚动展示，间隔秒数用 ElTag统一视觉。
const samplingGapColumns: any[] = [
  { key: 'monitorName', dataKey: 'monitorName', title: '测点', width: 220 },
  {
    key: 'gapSeconds',
    dataKey: 'gapSeconds',
    title: '间隔(秒)',
    width: 120,
    align: 'right',
    cellRenderer: ({ cellData }: { cellData: number }) =>
      h(ElTag, { type: 'warning', size: 'small' }, () => `${cellData ?? '-'}s`)
  },
  { key: 'prevTime', dataKey: 'prevTime', title: '前次时间', width: 180 },
  { key: 'collectTime', dataKey: 'collectTime', title: '本次时间', width: 180 }
];

const timeReversalColumns: any[] = [
  {
    key: 'monitorId',
    dataKey: 'monitorId',
    title: '测点ID',
    width: 150
  },
  {
    key: 'monitorName',
    dataKey: 'monitorName',
    title: '测点名称',
    width: 180
  },
  {
    key: 'temperature',
    dataKey: 'temperature',
    title: '温度',
    width: 110,
    align: 'right',
    cellRenderer: ({ cellData }: { cellData: number }) => h('span', {}, `${cellData?.toFixed(2) ?? '-'}℃`)
  },
  {
    key: 'collectTime',
    dataKey: 'collectTime',
    title: '采集时间',
    width: 180
  },
  {
    key: 'recodeTime',
    dataKey: 'recodeTime',
    title: '入库时间',
    width: 180
  },
  {
    key: 'delaySeconds',
    dataKey: 'delaySeconds',
    title: '延迟(秒)',
    width: 110,
    align: 'right',
    // 改用 Element Plus 原生组件，避免手拼 class 在主题切换时样式丢失。
    cellRenderer: ({ cellData }: { cellData: number }) =>
      h(ElTag, { type: 'danger', size: 'small' }, () => `${cellData}s`)
  }
];

/** 初始化默认时间范围：昨天8:30 ~ 今天8:30 */
function initTimeRange() {
  const now = new Date();
  const end = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 8, 30, 0);
  const start = new Date(end.getTime() - 24 * 3600 * 1000);
  const p = (n: number) => n.toString().padStart(2, '0');
  const fmt = (d: Date) =>
    `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
  timeRange.value = [fmt(start), fmt(end)];
}

function syncTimeRange() {
  if (timeRange.value?.[0]) {
    queryForm.startTime = timeRange.value[0];
    queryForm.endTime = timeRange.value[1];
  }
}

async function loadTimeReversal() {
  const { data } = await getTimeReversal({
    ...queryForm,
    pageNum: timeReversalPage.pageNum,
    pageSize: timeReversalPage.pageSize
  });
  timeReversalList.value = data.rows;
  timeReversalPage.total = data.total;
}

async function loadSamplingGapList() {
  // 采样间隔单独走分页接口，翻页不会连带起完整率 / 活跃度等聚合结果。
  const { data } = await getSamplingGapAnomalies({
    ...queryForm,
    pageNum: samplingGapPage.pageNum,
    pageSize: samplingGapPage.pageSize
  });
  samplingGapList.value = data.rows;
  samplingGapPage.total = data.total;
}

async function loadOtherSections() {
  const [delayRes, completenessRes, activityRes] = await Promise.all([
    getDelayDistribution(queryForm),
    getCompletenessRate(queryForm),
    getMonitorActivity(queryForm)
  ]);
  completenessList.value = completenessRes.data;
  activityList.value = activityRes.data;
  await nextTick();
  renderDelayDistribution(delayRes.data);
}

function renderDelayDistribution(data: TempBoardQualityVO[]) {
  const chart = getChart(delayDistChartRef);
  if (!chart) return;
  if (!data.length) {
    chart.clear();
    return;
  }
  chart.setOption({
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'shadow' },
      formatter: (params: any) => `${params[0].name}<br/>样本数: <b>${params[0].value}</b>`
    },
    grid: { left: 60, right: 30, top: 30, bottom: 30 },
    xAxis: { type: 'category', data: data.map((d) => d.delayBucket), axisLabel: { color: '#666' } },
    yAxis: { type: 'value', name: '样本数', axisLabel: { color: '#666' }, splitLine: { lineStyle: { type: 'dashed' } } },
    series: [
      {
        type: 'bar',
        data: data.map((d) => d.sampleCount),
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
            { offset: 0, color: '#e6a23c' },
            { offset: 1, color: '#f5deb3' }
          ]),
          borderRadius: [4, 4, 0, 0]
        },
        label: { show: true, position: 'top', fontSize: 10, color: '#666' },
        barMaxWidth: 30
      }
    ]
  });
}

async function handleQuery() {
  syncTimeRange();
  timeReversalPage.pageNum = 1;
  // 切换查询条件后采样间隔分页也回到首页，避免旧 offset 越界。
  samplingGapPage.pageNum = 1;
  loading.value = true;
  try {
    await Promise.all([loadTimeReversal(), loadSamplingGapList(), loadOtherSections()]);
  } finally {
    loading.value = false;
  }
}

async function handleTimeReversalPageChange(page: number) {
  timeReversalPage.pageNum = page;
  syncTimeRange();
  await loadTimeReversal();
}

async function handleTimeReversalSizeChange(size: number) {
  // 改每页条数后回到第一页，保持与 anomaly 页相同的交互语义。
  timeReversalPage.pageSize = size;
  timeReversalPage.pageNum = 1;
  syncTimeRange();
  await loadTimeReversal();
}

async function handleSamplingGapPageChange(page: number) {
  samplingGapPage.pageNum = page;
  syncTimeRange();
  await loadSamplingGapList();
}

async function handleSamplingGapSizeChange(size: number) {
  samplingGapPage.pageSize = size;
  samplingGapPage.pageNum = 1;
  syncTimeRange();
  await loadSamplingGapList();
}

onMounted(() => {
  initTimeRange();
  handleQuery();
});
</script>

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

.chart-container {
  width: 100%;
  min-height: 300px;
}

.table-v2-wrapper {
  height: 500px;
}

.table-v2-wrapper-sm {
  /* 采样间隔表与同行右侧「测点活跃度」保持相同高度视觉上更整齐。 */
  height: 300px;
}

.pagination-wrapper {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}
</style>
