<template>
  <div class="p-2 senior-report-page">
    <el-card shadow="hover" class="filter-card">
      <el-form :inline="true">
        <el-form-item label="类型">
          <el-select v-model="reportType" class="type-select" @change="reloadAll">
            <el-option v-for="dict in device_type" :key="dict.value" :label="dict.label" :value="dict.value" />
          </el-select>
        </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="结束时间"
            :default-time="defaultTime"
            @change="handleTimeChange"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="reloadAll">查询</el-button>
          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <el-card shadow="hover" class="chart-card">
      <template #header>
        <div class="card-header">
          <span>{{ valueName }}河流图</span>
          <el-switch v-model="riverShowGroup" active-text="显示设备组" inactive-text="只显示设备" @change="loadRiver" />
        </div>
      </template>
      <div v-loading="riverLoading" class="chart-wrap">
        <div ref="riverChartRef" class="chart"></div>
        <el-empty v-if="!riverLoading && riverEmpty" class="chart-empty" description="暂无功率数据" />
      </div>
    </el-card>

    <el-card shadow="hover" class="chart-card">
      <template #header>
        <div class="card-header">
          <span>{{ valueName }}矩形树图</span>
          <el-switch v-model="treemapShowGroup" active-text="显示设备组" inactive-text="只显示设备" @change="loadTreemap" />
        </div>
      </template>
      <div v-loading="treemapLoading" class="chart-wrap">
        <div ref="treemapChartRef" class="chart"></div>
        <el-empty v-if="!treemapLoading && treemapEmpty" class="chart-empty" description="暂无功率数据" />
      </div>
    </el-card>

    <el-card shadow="hover" class="chart-card">
      <template #header>
        <div class="card-header">
          <span>{{ flowValueName }}流向图</span>
        </div>
      </template>
      <div v-loading="flowLoading" class="chart-wrap">
        <div ref="flowChartRef" class="chart"></div>
        <el-empty v-if="!flowLoading && flowEmpty" class="chart-empty" description="暂无流向数据" />
      </div>
    </el-card>
  </div>
</template>

<script setup name="SeniorReport" lang="ts">
import * as echarts from 'echarts';
import { getSeniorFlowReport, getSeniorPowerReport } from '@/api/report';

const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { device_type } = toRefs<any>(proxy?.useDict('device_type'));

const riverChartRef = ref<HTMLDivElement>();
const treemapChartRef = ref<HTMLDivElement>();
const flowChartRef = ref<HTMLDivElement>();
let riverChart: echarts.ECharts | undefined;
let treemapChart: echarts.ECharts | undefined;
let flowChart: echarts.ECharts | undefined;

const riverLoading = ref(false);
const treemapLoading = ref(false);
const flowLoading = ref(false);
const riverEmpty = ref(true);
const treemapEmpty = ref(true);
const flowEmpty = ref(true);
const riverShowGroup = ref(false);
const treemapShowGroup = ref(false);
const reportType = ref<string | number>('2');
const valueName = ref('功率');
const flowValueName = ref('用电');
const unit = ref('kW');
const flowUnit = ref('kWh');
const timeRange = ref<string[]>([]);
const defaultTime: [Date, Date] = [new Date(2000, 0, 1, 0, 0, 0), new Date(2000, 0, 1, 23, 59, 59)];

function pad(value: number) {
  return String(value).padStart(2, '0');
}

function formatDateTime(date: Date) {
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}

function initDefaultRange() {
  const end = new Date();
  const start = new Date(end.getTime() - 24 * 60 * 60 * 1000);
  timeRange.value = [formatDateTime(start), formatDateTime(end)];
}

function queryParams(showGroup: boolean) {
  return {
    beginTime: timeRange.value[0],
    endTime: timeRange.value[1],
    showGroup,
    reportType: reportType.value
  };
}

function initCharts() {
  if (riverChartRef.value && !riverChart) {
    riverChart = echarts.init(riverChartRef.value, 'macarons');
  }
  if (treemapChartRef.value && !treemapChart) {
    treemapChart = echarts.init(treemapChartRef.value, 'macarons');
  }
  if (flowChartRef.value && !flowChart) {
    flowChart = echarts.init(flowChartRef.value, 'macarons');
  }
}

function renderRiver(data: Array<[string, number, string]>) {
  initCharts();
  riverEmpty.value = !data.length;
  riverChart?.setOption(
    {
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'line',
          lineStyle: {
            color: 'rgba(0,0,0,0.2)',
            width: 1
          }
        },
        valueFormatter: (value: unknown) => `${Number(value || 0).toFixed(2)} ${unit.value}`
      },
      legend: {
        type: 'scroll',
        top: 0
      },
      singleAxis: {
        top: 52,
        bottom: 40,
        type: 'time',
        axisPointer: {
          animation: true
        }
      },
      series: [
        {
          type: 'themeRiver',
          emphasis: {
            itemStyle: {
              shadowBlur: 12,
              shadowColor: 'rgba(0,0,0,0.2)'
            }
          },
          data
        }
      ]
    },
    true
  );
}

function renderTreemap(data: any[]) {
  initCharts();
  treemapEmpty.value = !data.length;
  treemapChart?.setOption(
    {
      tooltip: {
        formatter: (info: any) => {
          const value = Number(info.value || 0).toFixed(2);
          return `${info.name}<br/>${valueName.value}合计：${value} ${unit.value}`;
        }
      },
      series: [
        {
          type: 'treemap',
          roam: true,
          nodeClick: 'zoomToNode',
          breadcrumb: {
            show: true
          },
          label: {
            show: true,
            formatter: '{b}'
          },
          upperLabel: {
            show: true,
            height: 24
          },
          itemStyle: {
            borderColor: '#fff',
            borderWidth: 1,
            gapWidth: 1
          },
          levels: [
            {
              itemStyle: {
                borderWidth: 0,
                gapWidth: 4
              }
            },
            {
              itemStyle: {
                gapWidth: 2
              }
            }
          ],
          data
        }
      ]
    },
    true
  );
}

function renderFlow(data: { nodes: Array<{ name: string; value?: number }>; links: Array<{ source: string; target: string; value: number }> }) {
  initCharts();
  const nodes = data?.nodes || [];
  const links = data?.links || [];
  flowEmpty.value = !links.length;
  flowChart?.setOption(
    {
      tooltip: {
        trigger: 'item',
        formatter: (info: any) => {
          if (info.dataType === 'edge') {
            return `${info.data.source} → ${info.data.target}<br/>${flowValueName.value}：${Number(info.data.value || 0).toFixed(2)} ${flowUnit.value}`;
          }
          return `${info.name}<br/>${flowValueName.value}：${Number(info.data?.value || 0).toFixed(2)} ${flowUnit.value}`;
        }
      },
      series: [
        {
          type: 'sankey',
          data: nodes,
          links,
          draggable: true,
          nodeWidth: 18,
          nodeGap: 12,
          layoutIterations: 64,
          emphasis: {
            focus: 'adjacency'
          },
          lineStyle: {
            color: 'gradient',
            curveness: 0.5,
            opacity: 0.35
          },
          label: {
            color: '#303133',
            formatter: (params: any) => {
              const value = Number(params.data?.value || 0).toFixed(2);
              return `${params.name}\n${value} ${flowUnit.value}`;
            }
          }
        }
      ]
    },
    true
  );
}

async function loadRiver() {
  if (!timeRange.value.length) {
    renderRiver([]);
    return;
  }
  riverLoading.value = true;
  try {
    const res = await getSeniorPowerReport(queryParams(riverShowGroup.value));
    valueName.value = res.data.valueName || valueName.value;
    unit.value = res.data.unit || unit.value;
    renderRiver(res.data.riverData || []);
  } finally {
    riverLoading.value = false;
  }
}

async function loadTreemap() {
  if (!timeRange.value.length) {
    renderTreemap([]);
    return;
  }
  treemapLoading.value = true;
  try {
    const res = await getSeniorPowerReport(queryParams(treemapShowGroup.value));
    valueName.value = res.data.valueName || valueName.value;
    unit.value = res.data.unit || unit.value;
    renderTreemap(res.data.treemapData || []);
  } finally {
    treemapLoading.value = false;
  }
}

async function loadFlow() {
  if (!timeRange.value.length) {
    renderFlow({ nodes: [], links: [] });
    return;
  }
  flowLoading.value = true;
  try {
    const res = await getSeniorFlowReport(queryParams(false));
    flowValueName.value = res.data.valueName || flowValueName.value;
    flowUnit.value = res.data.unit || flowUnit.value;
    renderFlow(res.data.sankeyData || { nodes: [], links: [] });
  } finally {
    flowLoading.value = false;
  }
}

async function reloadAll() {
  await Promise.all([loadRiver(), loadTreemap(), loadFlow()]);
}

function handleTimeChange() {
  reloadAll();
}

async function resetQuery() {
  initDefaultRange();
  reportType.value = '2';
  riverShowGroup.value = false;
  treemapShowGroup.value = false;
  await reloadAll();
}

function resizeCharts() {
  riverChart?.resize();
  treemapChart?.resize();
  flowChart?.resize();
}

onMounted(async () => {
  initDefaultRange();
  await nextTick();
  initCharts();
  await reloadAll();
  window.addEventListener('resize', resizeCharts);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeCharts);
  riverChart?.dispose();
  treemapChart?.dispose();
  flowChart?.dispose();
  riverChart = undefined;
  treemapChart = undefined;
  flowChart = undefined;
});
</script>

<style scoped>
.filter-card {
  margin-bottom: 12px;
}

.type-select {
  width: 140px;
}

.chart-card {
  margin-bottom: 12px;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.chart-wrap {
  position: relative;
  min-height: 520px;
}

.chart {
  width: 100%;
  height: 520px;
}

.chart-empty {
  position: absolute;
  inset: 80px 0 0;
  pointer-events: none;
}

@media (max-width: 900px) {
  .card-header {
    align-items: flex-start;
    flex-direction: column;
  }

  .chart {
    height: 420px;
  }
}
</style>
