<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">Balance Root</p>
              <h3>回路根节点</h3>
            </div>
          </div>
          <el-tree
            v-loading="treeLoading"
            :data="treeData"
            node-key="id"
            :props="{ label: 'label', children: 'children' }"
            default-expand-all
            highlight-current
            @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">Meter Balance</p>
            <h2>计量平衡报表</h2>
            <p class="hero-desc">当前页面只对同口径指标做平衡分析。若指标不是累计/流量类，页面表达的是工况不平衡，而不是实际损耗金额。</p>
          </div>
          <el-tag effect="dark">{{ selectedRootName || '未选择根节点' }}</el-tag>
        </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">
            <el-form-item label="根节点">
              <el-input :model-value="selectedRootName || '请先在左侧选择根节点'" readonly style="width: 260px" />
            </el-form-item>
            <el-form-item label="指标">
              <el-select v-model="queryForm.metricCode" style="width: 180px">
                <el-option v-for="item in metricOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="聚合">
              <el-select v-model="queryForm.aggregationType" style="width: 120px">
                <el-option label="最新值" value="LAST" />
                <el-option label="平均值" value="AVG" />
                <el-option label="汇总值" value="SUM" />
              </el-select>
            </el-form-item>
            <el-form-item label="告警阈值">
              <el-input-number v-model="queryForm.imbalanceThreshold" :min="0" :max="1" :step="0.01" :precision="2" controls-position="right" />
            </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>
        </section>

        <section v-loading="loading" class="glass-panel">
          <div class="panel-head">
            <div>
              <p class="panel-eyebrow">Overview</p>
              <h3>平衡概览</h3>
            </div>
          </div>

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

          <template v-else>
            <div class="summary-grid">
              <article class="summary-card">
                <span>上游值</span>
                <strong>{{ formatNumber(reportData.upstreamValue) }}</strong>
              </article>
              <article class="summary-card">
                <span>下游汇总</span>
                <strong>{{ formatNumber(reportData.downstreamTotal) }}</strong>
              </article>
              <article class="summary-card">
                <span>差异值</span>
                <strong>{{ formatNumber(reportData.diffValue) }}</strong>
              </article>
              <article class="summary-card">
                <span>差异率</span>
                <strong>{{ formatPercent(reportData.diffRate) }}</strong>
              </article>
            </div>

            <el-alert :title="reportData.helpText || ''" type="info" :closable="false" show-icon class="page-alert" />

            <Chart class="chart-host" :chart-option="chartOption" />
          </template>
        </section>

        <MeterBalanceTopology :circuits="reportData?.circuits || []" @locate="handleLocateCircuit" />
      </el-col>
    </el-row>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue';
import { ElMessage } from 'element-plus';
import type { EChartsOption } from 'echarts';
import { useRouter } from 'vue-router';
import Chart from '@/components/Charts/Chart.vue';
import MeterBalanceTopology from '../components/MeterBalanceTopology.vue';
import { getMonitorInfoTree } from '@/api/ems/base/baseMonitorInfo';
import { getMeterBalanceReport } from '@/api/ems/report/iotAdvancedReport';
import type { EmsTreeNode, MeterBalanceCircuitVO, MeterBalanceReportVO } from '@/api/ems/types';
import { parseTime } from '@/utils/ruoyi';

defineOptions({
  name: 'MeterBalanceReport'
});

const router = useRouter();
const treeLoading = ref(false);
const loading = ref(false);
const treeData = ref<EmsTreeNode[]>([]);
const selectedRootName = ref('');
const reportData = ref<MeterBalanceReportVO>();

const metricOptions = [
  { label: '温度', value: 'temperature' },
  { label: '湿度', value: 'humidity' },
  { label: '照度', value: 'illuminance' },
  { label: '噪声', value: 'noise' },
  { label: '浓度', value: 'concentration' },
  { label: '振动速度', value: 'vibrationSpeed' },
  { label: '振动位移', value: 'vibrationDisplacement' },
  { label: '振动加速度', value: 'vibrationAcceleration' },
  { label: '振动温度', value: 'vibrationTemp' }
];

const createDefaultRange = () => {
  const now = new Date();
  const start = new Date(now.getTime() - 24 * 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({
  rootMonitorId: '',
  metricCode: 'temperature',
  aggregationType: 'AVG',
  imbalanceThreshold: 0.1
});

const chartOption = computed<EChartsOption>(() => {
  const circuits = reportData.value?.circuits || [];
  return {
    color: ['#2563eb'],
    tooltip: {
      trigger: 'axis'
    },
    grid: {
      top: 20,
      left: '16%',
      right: '6%',
      bottom: 36
    },
    xAxis: {
      type: 'value',
      axisLabel: {
        formatter: (value: number) => `${(value * 100).toFixed(0)}%`
      }
    },
    yAxis: {
      type: 'category',
      data: circuits.map((item) => item.monitorName)
    },
    series: [
      {
        type: 'bar',
        data: circuits.map((item) => Number(item.diffRate || 0)),
        itemStyle: {
          color: (params: any) => (circuits[params.dataIndex]?.abnormal ? '#ef4444' : '#22c55e'),
          borderRadius: [0, 6, 6, 0]
        }
      }
    ]
  };
});

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

const handleNodeClick = (node: EmsTreeNode) => {
  queryForm.rootMonitorId = String(node.code || '');
  selectedRootName.value = String(node.label || '');
  if (node.metricCode) {
    queryForm.metricCode = String(node.metricCode);
  }
};

const handleQuery = async () => {
  if (!queryForm.rootMonitorId) {
    ElMessage.warning('请先选择平衡分析根节点');
    return;
  }
  if (!timeRange.value || timeRange.value.length !== 2) {
    ElMessage.warning('请选择完整的记录时间范围');
    return;
  }
  loading.value = true;
  try {
    const { data } = await getMeterBalanceReport({
      rootMonitorId: queryForm.rootMonitorId,
      metricCode: queryForm.metricCode,
      aggregationType: queryForm.aggregationType,
      imbalanceThreshold: queryForm.imbalanceThreshold,
      beginRecordTime: timeRange.value[0],
      endRecordTime: timeRange.value[1]
    });
    reportData.value = data || { hasData: false, emptyReason: '接口未返回有效数据' };
  } finally {
    loading.value = false;
  }
};

const handleLocateCircuit = (row: MeterBalanceCircuitVO) => {
  router.push({
    path: '/ems/report/instrument-condition-report',
    query: {
      monitorIds: row.monitorIds?.join(','),
      beginRecordTime: timeRange.value[0],
      endRecordTime: timeRange.value[1],
      metricCodes: reportData.value?.metricCode
    }
  });
};

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

const formatPercent = (value: unknown) => {
  if (value === null || value === undefined || value === '') {
    return '--';
  }
  const numberValue = Number(value);
  return Number.isNaN(numberValue) ? '--' : `${(numberValue * 100).toFixed(2)}%`;
};

onMounted(async () => {
  await loadTree();
});
</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;
}

.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);
}

.panel-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  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(180px, 1fr));
  gap: 16px;
  margin-bottom: 18px;
}

.summary-card {
  padding: 18px;
}

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

.summary-card strong {
  display: block;
  margin-top: 12px;
  font-size: 28px;
  color: #0f172a;
}

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

.page-alert {
  margin-bottom: 16px;
}

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