<template>
  <div class="app-container historical-iot-page">
    <el-row :gutter="20">
      <el-col :xl="5" :lg="6" :md="7" :sm="24" :xs="24">
        <section class="glass-panel tree-panel">
          <div class="panel-heading">
            <div>
              <p class="panel-eyebrow">Device Navigator</p>
              <h3>历史设备树</h3>
            </div>
            <el-tag effect="plain" size="small">{{ monitorInfoOptions.length }} 个节点</el-tag>
          </div>

          <el-input
            v-model="workUnitName"
            class="tree-search"
            placeholder="请输入计量设备名称"
            clearable
            size="small"
            prefix-icon="el-icon-search"
          />

          <div v-loading="treeLoading" class="tree-wrapper">
            <el-tree
              ref="treeRef"
              :data="monitorInfoOptions"
              :props="monitorProps"
              :expand-on-click-node="false"
              :filter-node-method="filterNode"
              node-key="id"
              default-expand-all
              highlight-current
              @node-click="handleNodeClick"
            />
          </div>
        </section>
      </el-col>

      <el-col :xl="19" :lg="18" :md="17" :sm="24" :xs="24">
        <section class="hero-panel">
          <div class="hero-main">
            <div class="hero-copy">
              <p class="hero-eyebrow">Historical Curve Studio</p>
              <h2>历史环境曲线分析</h2>
              <p class="hero-desc">
                保留原页面的历史查询主链路，同时把图表容器、筛选区与结果区整体升级，让历史分析页更像一张可沉浸操作的业务驾驶舱。
              </p>
            </div>
            <div class="hero-tags">
              <el-tag effect="dark">{{ selectedMonitorName || '未选择设备' }}</el-tag>
              <el-tag effect="plain">指标 {{ chartPanels.length }} 项</el-tag>
              <el-tag effect="plain">采样 {{ queryParams.samplingInterval }} 分钟/点</el-tag>
            </div>
          </div>

          <div class="hero-metrics">
            <div class="metric-card">
              <span class="metric-label">当前设备</span>
              <strong class="metric-value">{{ selectedMonitorName || '未选择' }}</strong>
              <p class="metric-hint">{{ selectionModeText }}</p>
            </div>
            <div class="metric-card">
              <span class="metric-label">查询时间</span>
              <strong class="metric-value metric-time">{{ displayRangeText }}</strong>
              <p class="metric-hint">历史页负责完整时间范围检索</p>
            </div>
            <div class="metric-card">
              <span class="metric-label">结果点数</span>
              <strong class="metric-value">{{ historicalRecords.length }}</strong>
              <p class="metric-hint">完整保留接口返回的数据点</p>
            </div>
            <div class="metric-card">
              <span class="metric-label">图表数量</span>
              <strong class="metric-value">{{ chartPanels.length }}</strong>
              <p class="metric-hint">根据真实数据字段自动识别指标</p>
            </div>
          </div>
        </section>

        <section class="glass-panel filter-panel">
          <div class="panel-heading compact">
            <div>
              <p class="panel-eyebrow">Historical Query</p>
              <h3>历史筛选区</h3>
            </div>
            <div class="panel-actions">
              <el-button type="primary" size="small" icon="el-icon-search" @click="handleQuery">搜索</el-button>
              <el-button size="small" icon="el-icon-refresh" @click="resetQuery">重置</el-button>
              <!--
                这里先注释历史曲线页上的“多维报表”按钮，报表能力已拆分为多个独立菜单页面，避免继续回到旧的大单页入口。
              -->
              <!--
              <el-button type="warning" plain size="small" icon="el-icon-data-analysis" @click="openReportPage">多维报表</el-button>
              -->
            </div>
          </div>

          <el-form ref="queryFormRef" :model="queryParams" :inline="true" size="small" class="query-form">
            <el-form-item label="记录时间">
              <el-date-picker
                v-model="daterangeRecordTime"
                style="width: 340px"
                value-format="yyyy-MM-dd HH:mm:ss"
                type="datetimerange"
                range-separator="-"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
              />
            </el-form-item>
            <el-form-item label="采样间隔">
              <el-input-number v-model="queryParams.samplingInterval" :min="1" :max="1440" controls-position="right" />
              <span class="field-suffix">分钟/点</span>
            </el-form-item>
            <el-form-item label="设备名称">
              <el-input :model-value="selectedMonitorName || '请先在左侧选择具体设备节点'" readonly />
            </el-form-item>
          </el-form>
        </section>

        <section v-loading="loading" class="glass-panel chart-panel">
          <div class="panel-heading compact">
            <div>
              <p class="panel-eyebrow">Historical Canvas</p>
              <h3>历史曲线区</h3>
            </div>
            <div class="chart-status">
              <el-tag size="small" effect="plain">{{ selectedMonitorId || '未选设备' }}</el-tag>
              <el-tag size="small" effect="plain">结果 {{ historicalRecords.length }} 条</el-tag>
            </div>
          </div>

          <div v-if="!selectedMonitorId" class="empty-block">
            <el-empty description="请在左侧树中选择具体设备节点查看历史曲线" />
          </div>

          <div v-else-if="!historicalRecords.length" class="empty-block">
            <el-empty description="当前时间范围内暂无历史数据，请调整查询条件后重试" />
          </div>

          <div v-else-if="!chartPanels.length" class="empty-block">
            <el-empty description="已获取历史数据，但未识别到可绘制曲线的指标字段" />
          </div>

          <template v-else>
            <div class="chart-summary-bar">
              <span>设备：{{ selectedMonitorName }}</span>
              <span>范围：{{ displayRangeText }}</span>
              <span>采样：{{ queryParams.samplingInterval }} 分钟/点</span>
              <span>指标：{{ chartPanels.length }} 项</span>
            </div>

            <div class="chart-grid" :class="chartGridClass">
              <article v-for="panel in chartPanels" :key="panel.key" class="chart-card">
                <div class="chart-card-head">
                  <div>
                    <h4>{{ panel.label }}</h4>
                    <p>{{ panel.metric.unit ? `${panel.metric.label}(${panel.metric.unit})` : panel.metric.label }}</p>
                  </div>
                  <el-tag size="small" effect="plain">{{ panel.valueCount }} 个有效点</el-tag>
                </div>
                <Chart :ref="setChartRef(panel.key)" class="chart-canvas" :chart-option="panel.option" />
              </article>
            </div>
          </template>
        </section>
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { ElMessage } from 'element-plus';
import Chart from '@/components/Charts/Chart.vue';
import { getMonitorInfoTree } from '@/api/ems/base/baseMonitorInfo';
import { getRecordIotenvInstantList } from '@/api/ems/record/recordIotenvInstant';
import { parseTime } from '@/utils/ruoyi';
import type { RecordIotenvInstantVO } from '@/api/ems/types';
import {
  buildIotCurveOption,
  buildMetricHintsByNode,
  connectCurveCharts,
  normalizeIotCurveRecord,
  readMetricValue,
  resolveIotCurveMetrics,
  type CurveChartExpose,
  type IotCurveMetricDefinition,
  type NormalizedIotCurveRecord
} from '../iotCurveShared';

defineOptions({
  name: 'currentIOTCurve',
  dicts: ['collect_type']
});

interface ReportSelection {
  mode: string;
  monitorId: string;
  monitorIds: string[];
  monitorName: string;
  monitorType: string;
  deviceDisplayMap: Record<string, { label: string; type: unknown }>;
}

interface ChartPanel {
  key: string;
  label: string;
  metric: IotCurveMetricDefinition;
  valueCount: number;
  option: Record<string, unknown>;
}

const { proxy } = getCurrentInstance() as ComponentInternalInstance;

const queryFormRef = ref<ElFormInstance>();
const treeRef = ref<ElTreeInstance>();
const chartRefMap = shallowRef<Record<string, CurveChartExpose | null>>({});
const disconnectChartGroup = ref<() => void>(() => undefined);

const treeLoading = ref(false);
const loading = ref(false);
const monitorInfoOptions = ref<any[]>([]);
const workUnitName = ref('');
const daterangeRecordTime = ref<string[]>([]);
const historicalRecords = ref<NormalizedIotCurveRecord[]>([]);
const selectedMonitorName = ref('');
const selectedMonitorNode = ref<Record<string, unknown> | null>(null);
const selectedMonitorId = ref('');

const monitorProps = {
  children: 'children',
  label: 'label'
};

// 这里继续保留原有查询字段结构，避免 EMS 历史页与后端入参发生漂移。
const queryParams = reactive({
  monitorId: null as string | null,
  monitorIds: [] as string[],
  samplingInterval: 1,
  params: {} as Record<string, unknown>
});

const reportSelection = ref<ReportSelection>({
  mode: 'all',
  monitorId: '',
  monitorIds: [],
  monitorName: '',
  monitorType: '',
  deviceDisplayMap: {}
});

const metricHints = computed(() => buildMetricHintsByNode(selectedMonitorNode.value));

const chartPanels = computed<ChartPanel[]>(() => {
  const metrics = resolveIotCurveMetrics(historicalRecords.value, metricHints.value);
  return metrics.map((metric) => {
    const valueCount = historicalRecords.value.filter((item) => readMetricValue(item, metric) !== null).length;
    return {
      key: metric.key,
      label: metric.label,
      metric,
      valueCount,
      option: buildIotCurveOption({
        metric,
        monitorName: selectedMonitorName.value || '设备',
        records: historicalRecords.value,
        premium: true,
        subtitle: `历史查询 | 共 ${historicalRecords.value.length} 点`
      })
    };
  });
});

const displayRangeText = computed(() => {
  if (!daterangeRecordTime.value?.length) {
    return '--';
  }
  return `${daterangeRecordTime.value[0]} 至 ${daterangeRecordTime.value[1]}`;
});

const selectionModeText = computed(() => {
  const modeMap = {
    all: '当前页面全部设备可参与报表分析',
    group: '父节点可继续用于多设备报表对比',
    single: '当前曲线聚焦单设备历史轨迹'
  };
  return modeMap[reportSelection.value.mode] || '历史查询模式';
});

const chartGridClass = computed(() => {
  return chartPanels.value.length <= 1 ? 'chart-grid-single' : 'chart-grid-multi';
});

const setChartRef = (key: string) => {
  return (instance: any) => {
    if (instance) {
      chartRefMap.value[key] = instance as CurveChartExpose;
      return;
    }
    delete chartRefMap.value[key];
  };
};

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

const buildReportSelectionByNodes = (nodes, defaultName) => {
  const leafNodes = getLeafMonitorNodes(nodes);
  const monitorIds = leafNodes.map((item) => item.code);
  const typeSet = leafNodes.map((item) => item.type).filter((item) => item !== null && item !== undefined && item !== '');

  return {
    mode: monitorIds.length > 1 ? 'group' : 'single',
    monitorId: monitorIds.length === 1 ? monitorIds[0] : '',
    monitorIds,
    monitorName: defaultName,
    monitorType: Array.from(new Set(typeSet)).join(','),
    deviceDisplayMap: leafNodes.reduce((accumulator, item) => {
      accumulator[item.code] = {
        label: item.label,
        type: item.type
      };
      return accumulator;
    }, {})
  } as ReportSelection;
};

const resolveReportSelection = () => {
  if (reportSelection.value.monitorId || reportSelection.value.monitorIds.length > 0) {
    return reportSelection.value;
  }
  const allSelection = buildReportSelectionByNodes(monitorInfoOptions.value, '当前页面全部物联设备');
  allSelection.mode = allSelection.monitorIds.length > 1 ? 'all' : allSelection.mode;
  return allSelection;
};

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

const getTreeselect = async () => {
  treeLoading.value = true;
  try {
    // 这里不再硬编码能源/监测类型编号，直接读取当前系统可见设备树，避免后续增删类型时还要改前端。
    const response = await getMonitorInfoTree({});
    monitorInfoOptions.value = response.data || [];
    reportSelection.value = resolveReportSelection();
  } finally {
    treeLoading.value = false;
  }
};

const renderChartLinkage = () => {
  disconnectChartGroup.value();
  if (chartPanels.value.length < 2) {
    return;
  }
  void nextTick(() => {
    disconnectChartGroup.value();
    disconnectChartGroup.value = connectCurveCharts(
      chartPanels.value.map((item) => chartRefMap.value[item.key]),
      'historical-iot-chart-group'
    );
  });
};

const getChart = async () => {
  if (!queryParams.monitorId) {
    return;
  }

  loading.value = true;
  try {
    // 历史页要完整保留查询结果，所以这里只做标准化，不做截窗。
    const query = JSON.parse(JSON.stringify(queryParams));
    const { data = [] } = await getRecordIotenvInstantList(query);
    historicalRecords.value = data.map((item) => normalizeIotCurveRecord(item));
    renderChartLinkage();
  } finally {
    loading.value = false;
  }
};

const getList = async () => {
  queryParams.params = {};
  if (daterangeRecordTime.value?.length === 2) {
    queryParams.params.beginRecordTime = daterangeRecordTime.value[0];
    queryParams.params.endRecordTime = daterangeRecordTime.value[1];
  }
  await getChart();
};

const handleQuery = async () => {
  await getList();
};

const resetQuery = async () => {
  queryParams.samplingInterval = 1;
  queryFormRef.value?.resetFields();
  if (!daterangeRecordTime.value?.length) {
    const nowDate = parseTime(new Date(), '{y}-{m}-{d}');
    daterangeRecordTime.value = [`${nowDate} 09:00:00`, `${nowDate} 09:10:00`];
  }
  await handleQuery();
};

const handleNodeClick = async (data) => {
  if (data.children && data.children.length > 0) {
    reportSelection.value = buildReportSelectionByNodes(data.children, data.label);
    reportSelection.value.mode = 'group';
    ElMessage.info('父节点已用于多设备报表对比；历史曲线仍需选择具体设备节点查看');
    return;
  }

  queryParams.monitorIds = [];
  queryParams.monitorId = data.code;
  selectedMonitorId.value = String(data.code || '');
  selectedMonitorName.value = String(data.label || '');
  selectedMonitorNode.value = data;
  reportSelection.value = {
    mode: 'single',
    monitorId: String(data.code || ''),
    monitorIds: [String(data.code || '')],
    monitorName: String(data.label || ''),
    monitorType: String(data.type || ''),
    deviceDisplayMap: {
      [data.code]: {
        label: data.label,
        type: data.type
      }
    }
  };

  await handleQuery();
};

const openReportPage = () => {
  if (!daterangeRecordTime.value || daterangeRecordTime.value.length !== 2) {
    ElMessage.warning('请先选择完整的记录时间范围');
    return;
  }
  const currentSelection = resolveReportSelection();
  if (!currentSelection.monitorId && currentSelection.monitorIds.length === 0) {
    ElMessage.warning('当前没有可用于报表分析的设备');
    return;
  }

  const selectionKey = 'recordIotenvInstantDashboardSelection';
  window.sessionStorage.setItem(
    selectionKey,
    JSON.stringify({
      deviceDisplayMap: currentSelection.deviceDisplayMap || {},
      selectionLabel: currentSelection.monitorName,
      monitorType: currentSelection.monitorType || String(selectedMonitorNode.value?.type || '')
    })
  );

  proxy?.$router.push({
    path: '/ems/report/recordIotenvInstantDashboard/index',
    query: {
      selectionKey,
      source: 'iot',
      compareScope: currentSelection.mode,
      monitorId: currentSelection.monitorId,
      monitorIds: currentSelection.monitorIds.join(','),
      monitorName: currentSelection.monitorName,
      selectionLabel: currentSelection.monitorName,
      monitorType: currentSelection.monitorType || String(selectedMonitorNode.value?.type || ''),
      samplingInterval: String(queryParams.samplingInterval || 1),
      beginRecordTime: daterangeRecordTime.value[0],
      endRecordTime: daterangeRecordTime.value[1]
    }
  });
};

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

watch(chartPanels, () => {
  renderChartLinkage();
});

onMounted(async () => {
  const nowDate = parseTime(new Date(), '{y}-{m}-{d}');
  daterangeRecordTime.value = [`${nowDate} 09:00:00`, `${nowDate} 09:10:00`];
  await getTreeselect();
});

onBeforeUnmount(() => {
  disconnectChartGroup.value();
});
</script>

<style scoped>
.historical-iot-page {
  --page-bg-start: #f5f7ff;
  --page-bg-end: #fbfcff;
  --panel-border: rgba(148, 163, 184, 0.22);
  --panel-shadow: 0 18px 48px rgba(15, 23, 42, 0.08);
  --hero-shadow: 0 28px 64px rgba(15, 23, 42, 0.14);
  --text-primary: #0f172a;
  --text-secondary: #64748b;
  --accent: #0f766e;
  min-height: calc(100vh - 84px);
  background:
    radial-gradient(circle at left top, rgba(20, 184, 166, 0.14), transparent 30%),
    radial-gradient(circle at right top, rgba(37, 99, 235, 0.12), transparent 26%),
    linear-gradient(180deg, var(--page-bg-start), var(--page-bg-end));
}

.glass-panel,
.hero-panel {
  border: 1px solid var(--panel-border);
  border-radius: 24px;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(12px);
  box-shadow: var(--panel-shadow);
}

.tree-panel,
.filter-panel,
.chart-panel {
  padding: 20px;
}

.hero-panel {
  padding: 24px;
  margin-bottom: 20px;
  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;
  box-shadow: var(--hero-shadow);
  position: relative;
  overflow: hidden;
}

.hero-panel::after {
  content: '';
  position: absolute;
  inset: auto -40px -90px auto;
  width: 220px;
  height: 220px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
}

.panel-heading,
.hero-main,
.hero-metrics,
.chart-grid,
.chart-summary-bar {
  display: grid;
}

.panel-heading {
  grid-template-columns: 1fr auto;
  gap: 12px;
  align-items: center;
  margin-bottom: 18px;
}

.panel-heading.compact {
  margin-bottom: 16px;
}

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

.panel-eyebrow {
  color: var(--accent);
}

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

.hero-main {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 16px;
  align-items: start;
}

.hero-copy h2 {
  font-size: 28px;
  line-height: 1.2;
}

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

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

.hero-tags,
.panel-actions,
.chart-status {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.hero-metrics {
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  margin-top: 24px;
}

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

.metric-label {
  display: block;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.72);
}

.metric-value {
  display: block;
  margin-top: 10px;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
}

.metric-time {
  font-size: 16px;
}

.metric-hint {
  margin: 10px 0 0;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.78);
}

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

.tree-wrapper {
  min-height: 640px;
  max-height: 72vh;
  overflow: auto;
  padding: 12px;
  border-radius: 18px;
  background: linear-gradient(180deg, rgba(248, 250, 252, 0.96), rgba(241, 245, 249, 0.88));
}

.filter-panel,
.chart-panel {
  margin-bottom: 20px;
}

.query-form :deep(.el-form-item) {
  margin-right: 18px;
}

.field-suffix {
  margin-left: 8px;
  color: var(--text-secondary);
}

.chart-summary-bar {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
  margin-bottom: 16px;
  padding: 14px 16px;
  border-radius: 16px;
  background: linear-gradient(90deg, rgba(15, 118, 110, 0.08), rgba(37, 99, 235, 0.06));
  color: var(--text-secondary);
}

.chart-grid {
  gap: 16px;
}

.chart-grid-single {
  grid-template-columns: 1fr;
}

.chart-grid-multi {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.chart-card {
  padding: 16px;
  border-radius: 22px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.96)),
    linear-gradient(135deg, rgba(15, 118, 110, 0.05), rgba(37, 99, 235, 0.05));
  border: 1px solid rgba(226, 232, 240, 0.9);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
}

.chart-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}

.chart-card-head h4 {
  margin: 0;
  color: var(--text-primary);
  font-size: 16px;
}

.chart-card-head p {
  margin: 6px 0 0;
  color: var(--text-secondary);
  font-size: 12px;
}

.chart-canvas {
  width: 100%;
  height: 48vh;
  min-height: 380px;
  border-radius: 18px;
}

.empty-block {
  min-height: 56vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

@media (max-width: 1400px) {
  .hero-metrics {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 992px) {
  .hero-main,
  .chart-grid-multi {
    grid-template-columns: 1fr;
  }

  .hero-tags,
  .panel-actions,
  .chart-status {
    justify-content: flex-start;
  }

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

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

  .hero-copy h2 {
    font-size: 24px;
  }

  .hero-metrics {
    grid-template-columns: 1fr;
  }

  .tree-wrapper {
    min-height: 360px;
  }
}
</style>
