<template>
  <div class="app-container report-page">
    <el-row :gutter="18">
      <el-col :xl="5" :lg="6" :md="7" :sm="24" :xs="24">
        <section class="glass-panel tree-panel">
          <div class="panel-head">
            <div>
              <p class="panel-eyebrow">Monitor Tree</p>
              <h3>分析点位树</h3>
            </div>
          </div>
          <el-input v-model="treeKeyword" placeholder="输入点位名称筛选" clearable class="tree-search" />
          <el-tree
            ref="treeRef"
            v-loading="treeLoading"
            :data="treeData"
            node-key="id"
            :props="{ label: 'label', children: 'children' }"
            default-expand-all
            highlight-current
            :filter-node-method="filterTree"
            @node-click="handleNodeClick"
          />
        </section>
      </el-col>

      <el-col :xl="19" :lg="18" :md="17" :sm="24" :xs="24">
        <section class="hero-panel">
          <div>
            <p class="panel-eyebrow hero-eyebrow">Instrument Condition</p>
            <h2>仪表工况分析</h2>
            <p class="hero-desc">
              所有统计值都直接来自 `record_iotenv_instant_YYYYMMDD` 分表真实记录。这里支持秒/分/时三种时间粒度，并严格区分“页面支持”和“当前无数据”。
            </p>
          </div>
          <div class="hero-tags">
            <el-tag effect="dark">{{ selectionLabel || '未选择点位' }}</el-tag>
            <el-tag effect="plain">{{ queryForm.samplingGranularity }}</el-tag>
            <el-tag effect="plain">{{ queryForm.samplingInterval }} 间隔</el-tag>
          </div>
        </section>

        <section class="glass-panel">
          <div class="panel-head">
            <div>
              <p class="panel-eyebrow">Query</p>
              <h3>分析筛选</h3>
            </div>
            <el-button type="primary" @click="handleQuery">刷新分析</el-button>
          </div>

          <el-form :inline="true" :model="queryForm" size="small" class="query-form">
            <el-form-item label="分析范围">
              <el-input :model-value="selectionLabel || '请先在左侧选择节点'" readonly style="width: 280px" />
            </el-form-item>
            <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: 340px"
              />
            </el-form-item>
            <el-form-item label="粒度">
              <el-select v-model="queryForm.samplingGranularity" style="width: 120px">
                <el-option label="秒级" value="SECOND" />
                <el-option label="分钟级" value="MINUTE" />
                <el-option label="小时级" value="HOUR" />
              </el-select>
            </el-form-item>
            <el-form-item label="间隔">
              <el-input-number v-model="queryForm.samplingInterval" :min="1" :max="3600" controls-position="right" />
            </el-form-item>
            <el-form-item label="指标">
              <el-select
                v-model="queryForm.metricCodes"
                multiple
                collapse-tags
                collapse-tags-tooltip
                placeholder="自动识别全部有效指标"
                style="width: 320px"
              >
                <el-option v-for="item in metricOptions" :key="item.metricCode" :label="item.metricName" :value="item.metricCode" />
              </el-select>
            </el-form-item>
          </el-form>
        </section>

        <div v-if="reportData?.summaryCards?.length" class="summary-grid">
          <article v-for="item in reportData.summaryCards" :key="item.metricCode" class="summary-card">
            <div class="summary-title">{{ item.metricName }}</div>
            <div class="summary-value">
              {{ formatNumber(item.latest) }}<span>{{ item.unit }}</span>
            </div>
            <div class="summary-foot">均值 {{ formatNumber(item.avg) }}{{ item.unit }}</div>
            <div class="summary-foot">峰值 {{ formatNumber(item.max) }}{{ item.unit }}</div>
          </article>
        </div>

        <section v-loading="loading" class="glass-panel">
          <div class="panel-head">
            <div>
              <p class="panel-eyebrow">Trend</p>
              <h3>工况曲线</h3>
            </div>
            <el-tag size="small" effect="plain">{{ chartSeries.length }} 条序列</el-tag>
          </div>

          <el-empty v-if="!reportData || reportData.hasData === false" :description="reportData?.emptyReason || '当前条件下无可分析数据'" />
          <Chart v-else class="chart-host" :chart-option="chartOption" />
        </section>

        <section v-if="reportData?.seriesList?.length" class="glass-panel">
          <div class="panel-head">
            <div>
              <p class="panel-eyebrow">Series</p>
              <h3>序列明细</h3>
            </div>
          </div>

          <el-table :data="seriesTableRows" stripe>
            <el-table-column prop="monitorName" label="点位" min-width="180" />
            <el-table-column prop="metricName" label="指标" min-width="120" />
            <el-table-column prop="sampleCount" label="采样点数" min-width="100" />
            <el-table-column prop="firstTime" label="首点时间" min-width="180" />
            <el-table-column prop="lastTime" label="末点时间" min-width="180" />
          </el-table>
        </section>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import { ElMessage } from 'element-plus';
import type { EChartsOption } from 'echarts';
import { useRoute } from 'vue-router';
import Chart from '@/components/Charts/Chart.vue';
import { getMonitorInfoTree } from '@/api/ems/base/baseMonitorInfo';
import { getInstrumentConditionReport } from '@/api/ems/report/iotAdvancedReport';
import type { EmsTreeNode, InstrumentConditionReportVO, InstrumentConditionSeriesVO, IotMetricOptionVO } from '@/api/ems/types';
import { parseTime } from '@/utils/ruoyi';

defineOptions({
  name: 'InstrumentConditionReport'
});

const treeRef = ref();
const route = useRoute();
const treeLoading = ref(false);
const loading = ref(false);
const treeKeyword = ref('');
const treeData = ref<EmsTreeNode[]>([]);
const selectionLabel = ref('');
const reportData = ref<InstrumentConditionReportVO>();

const createDefaultRange = () => {
  const now = new Date();
  const start = new Date(now.getTime() - 2 * 60 * 60 * 1000);
  return [parseTime(start, '{y}-{m}-{d} {h}:{i}:{s}'), parseTime(now, '{y}-{m}-{d} {h}:{i}:{s}')];
};

const timeRange = ref<string[]>(createDefaultRange());

const queryForm = reactive({
  monitorIds: [] as string[],
  samplingGranularity: 'MINUTE',
  samplingInterval: 5,
  metricCodes: [] as string[]
});

const metricOptions = computed<IotMetricOptionVO[]>(() => reportData.value?.availableMetrics || []);

const activeSeries = computed(() => {
  const source = reportData.value?.seriesList || [];
  if (!queryForm.metricCodes.length) {
    return source;
  }
  return source.filter((item) => queryForm.metricCodes.includes(String(item.metricCode || '')));
});

const chartSeries = computed(() => activeSeries.value);

const chartOption = computed<EChartsOption>(() => {
  const timeAxis = Array.from(
    new Set(chartSeries.value.flatMap((item) => (item.points || []).map((point) => String(point.time || ''))).filter((item) => item))
  ).sort();

  return {
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      top: 8,
      data: chartSeries.value.map((item) => buildSeriesName(item))
    },
    grid: {
      top: 60,
      left: '7%',
      right: '4%',
      bottom: 48
    },
    dataZoom: [
      {
        type: 'slider',
        height: 16
      }
    ],
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: timeAxis
    },
    yAxis: {
      type: 'value',
      splitLine: {
        lineStyle: {
          type: 'dashed'
        }
      }
    },
    series: chartSeries.value.map((item) => {
      const pointMap = (item.points || []).reduce(
        (accumulator, point) => {
          accumulator[String(point.time || '')] = Number(point.value || 0);
          return accumulator;
        },
        {} as Record<string, number>
      );
      return {
        name: buildSeriesName(item),
        type: 'line',
        smooth: true,
        connectNulls: false,
        showSymbol: false,
        data: timeAxis.map((time) => (Object.prototype.hasOwnProperty.call(pointMap, time) ? pointMap[time] : null))
      };
    })
  };
});

const seriesTableRows = computed(() => {
  return chartSeries.value.map((item) => ({
    monitorName: item.monitorName,
    metricName: item.metricName,
    sampleCount: item.points?.length || 0,
    firstTime: item.points?.[0]?.time || '--',
    lastTime: item.points?.[item.points.length - 1]?.time || '--'
  }));
});

const loadTree = async () => {
  treeLoading.value = true;
  try {
    const response = await getMonitorInfoTree({});
    treeData.value = response.data || [];
  } finally {
    treeLoading.value = false;
  }
};

const getLeafNodes = (nodes: EmsTreeNode[]): EmsTreeNode[] => {
  let result: EmsTreeNode[] = [];
  (nodes || []).forEach((item) => {
    if (item.children && item.children.length > 0) {
      result = result.concat(getLeafNodes(item.children));
      return;
    }
    if (item.code) {
      result.push(item);
    }
  });
  return result;
};

const handleNodeClick = (node: EmsTreeNode) => {
  const targetNodes = node.children && node.children.length > 0 ? getLeafNodes([node]) : [node];
  queryForm.monitorIds = targetNodes.map((item) => String(item.code || '')).filter((item) => item);
  selectionLabel.value = String(node.label || '当前节点');
};

const handleQuery = async () => {
  if (!queryForm.monitorIds.length) {
    ElMessage.warning('请先选择分析点位');
    return;
  }
  if (!timeRange.value || timeRange.value.length !== 2) {
    ElMessage.warning('请选择完整的记录时间范围');
    return;
  }
  loading.value = true;
  try {
    const { data } = await getInstrumentConditionReport({
      monitorIds: queryForm.monitorIds,
      metricCodes: queryForm.metricCodes,
      samplingGranularity: queryForm.samplingGranularity,
      samplingInterval: queryForm.samplingInterval,
      beginRecordTime: timeRange.value[0],
      endRecordTime: timeRange.value[1]
    } as any);
    reportData.value = data || { hasData: false, emptyReason: '接口未返回有效数据' };
  } finally {
    loading.value = false;
  }
};

const buildSeriesName = (item: InstrumentConditionSeriesVO) => {
  if (queryForm.monitorIds.length <= 1) {
    return String(item.metricName || item.metricCode || '未命名指标');
  }
  return `${item.monitorName}-${item.metricName}`;
};

const filterTree = (value: string, data: EmsTreeNode) => {
  if (!value) {
    return true;
  }
  return String(data.label || '').includes(value);
};

const formatNumber = (value: unknown) => {
  if (value === null || value === undefined || value === '') {
    return '--';
  }
  const numberValue = Number(value);
  return Number.isNaN(numberValue) ? '--' : numberValue.toFixed(2);
};

watch(treeKeyword, (value) => {
  treeRef.value?.filter(value);
});

watch(
  metricOptions,
  (value) => {
    if (!value.length) {
      queryForm.metricCodes = [];
      return;
    }
    queryForm.metricCodes = queryForm.metricCodes.filter((item) => value.some((metric) => metric.metricCode === item));
  },
  {
    immediate: true
  }
);

onMounted(async () => {
  await loadTree();
  await nextTick();
  const routeMonitorIds = String(route.query.monitorIds || '')
    .split(',')
    .map((item) => item.trim())
    .filter((item) => item);
  if (routeMonitorIds.length) {
    queryForm.monitorIds = routeMonitorIds;
    selectionLabel.value = String(route.query.selectionLabel || '带参复盘范围');
  }
  const beginRecordTime = String(route.query.beginRecordTime || '');
  const endRecordTime = String(route.query.endRecordTime || '');
  if (beginRecordTime && endRecordTime) {
    timeRange.value = [beginRecordTime, endRecordTime];
  }
  const metricCodes = String(route.query.metricCodes || '')
    .split(',')
    .map((item) => item.trim())
    .filter((item) => item);
  if (metricCodes.length) {
    queryForm.metricCodes = metricCodes;
  }
  if (queryForm.monitorIds.length) {
    await handleQuery();
  }
});
</script>

<style scoped>
.report-page {
  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%);
}

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

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

.tree-search {
  margin-bottom: 12px;
}

.hero-panel {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding: 24px;
  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 {
  color: rgba(255, 255, 255, 0.72);
}

.hero-panel h2,
.panel-head h3 {
  margin: 0;
}

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

.hero-tags,
.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

.hero-tags {
  flex-wrap: wrap;
  align-content: flex-start;
}

.panel-head {
  margin-bottom: 14px;
}

.panel-eyebrow {
  margin: 0 0 6px;
  color: #2563eb;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
  margin-bottom: 18px;
}

.summary-card {
  padding: 18px;
}

.summary-title {
  color: #64748b;
  font-size: 13px;
}

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

.summary-value span {
  margin-left: 6px;
  font-size: 14px;
  color: #64748b;
}

.summary-foot {
  margin-top: 8px;
  color: #64748b;
  font-size: 12px;
}

.chart-host {
  width: 100%;
  height: 420px;
}

@media (max-width: 992px) {
  .hero-panel {
    display: block;
  }

  .hero-tags {
    margin-top: 12px;
  }
}
</style>
