<template>
  <div class="p-2 electricity-bill-page">
    <el-card shadow="hover">
      <el-form :inline="true" class="query-form">
        <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"
          />
        </el-form-item>
        <el-form-item label="时间间隔">
          <el-select v-model="query.interval" placeholder="请选择时间间隔" class="interval-select">
            <el-option v-for="item in intervalOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" @click="handleQuery">查询</el-button>
          <el-button icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <div v-loading="loading" class="chart-wrap">
        <div ref="chartRef" class="bill-chart"></div>
        <el-empty v-if="!loading && empty" class="chart-empty" description="暂无电费数据" />
      </div>

      <el-table v-loading="loading" border row-key="id" :data="tableRows" :tree-props="{ children: 'children' }" class="bill-table" height="420">
        <el-table-column prop="name" label="楼层/设备" fixed min-width="220" show-overflow-tooltip />
        <el-table-column label="用电瓦数" align="center">
          <el-table-column v-for="bucket in buckets" :key="`energy_${bucket.key}`" :label="bucket.label" align="right" min-width="130">
            <template #default="scope">
              {{ formatNumber(scope.row[`energy_${bucket.key}`]) }}
            </template>
          </el-table-column>
        </el-table-column>
        <el-table-column label="电费" align="center">
          <el-table-column v-for="bucket in buckets" :key="`fee_${bucket.key}`" :label="bucket.label" align="right" min-width="130">
            <template #default="scope">
              {{ formatMoney(scope.row[`fee_${bucket.key}`]) }}
            </template>
          </el-table-column>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script setup name="ElectricityBill" lang="ts">
import * as echarts from 'echarts';
import { getElectricityBill } from '@/api/electricityManagement/electricityBill';
import {
  ElectricityBillBucket,
  ElectricityBillInterval,
  ElectricityBillRow,
  ElectricityBillSeries
} from '@/api/electricityManagement/electricityBill/types';

const chartRef = ref<HTMLDivElement>();
let chartInstance: echarts.ECharts | undefined;

const loading = ref(false);
const empty = ref(true);
const timeRange = ref<string[]>([]);
const buckets = ref<ElectricityBillBucket[]>([]);
const tableRows = ref<ElectricityBillRow[]>([]);
const defaultTime: [Date, Date] = [new Date(2000, 0, 1, 0, 0, 0), new Date(2000, 0, 1, 23, 59, 59)];
const query = reactive({
  interval: 'hour' as ElectricityBillInterval
});
const intervalOptions: Array<{ label: string; value: ElectricityBillInterval }> = [
  { label: '分', value: 'minute' },
  { label: '时', value: 'hour' },
  { label: '日', value: 'day' },
  { label: '月', value: 'month' },
  { label: '班组', value: 'shift' }
];

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 initChart() {
  if (!chartRef.value) {
    return;
  }
  chartInstance = echarts.init(chartRef.value, 'macarons');
}

function renderChart(xAxis: string[], series: ElectricityBillSeries[]) {
  if (!chartInstance) {
    initChart();
  }
  empty.value = !xAxis.length || !series.some((item) => item.data.some((value) => Number(value) > 0));
  chartInstance?.setOption(
    {
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'shadow'
        },
        valueFormatter: (value: unknown) => formatMoney(value)
      },
      legend: {
        type: 'scroll',
        top: 0
      },
      grid: {
        top: 52,
        left: 58,
        right: 28,
        bottom: 52,
        containLabel: true
      },
      xAxis: {
        type: 'category',
        data: xAxis,
        axisLabel: {
          hideOverlap: true
        }
      },
      yAxis: {
        type: 'value',
        name: '电费'
      },
      dataZoom: [
        {
          type: 'inside'
        },
        {
          type: 'slider',
          height: 24,
          bottom: 10
        }
      ],
      series: series.map((item) => ({
        ...item,
        type: 'bar',
        stack: '设备电费',
        emphasis: {
          focus: 'series'
        }
      }))
    },
    true
  );
}

function formatNumber(value: unknown) {
  const numberValue = Number(value || 0);
  return Number.isFinite(numberValue) ? numberValue.toFixed(3) : '-';
}

function formatMoney(value: unknown) {
  const numberValue = Number(value || 0);
  return Number.isFinite(numberValue) ? numberValue.toFixed(2) : '-';
}

async function handleQuery() {
  if (!timeRange.value?.length) {
    return;
  }
  loading.value = true;
  try {
    const res = await getElectricityBill({
      beginTime: timeRange.value[0],
      endTime: timeRange.value[1],
      interval: query.interval
    });
    buckets.value = res.data.buckets || [];
    tableRows.value = res.data.tableRows || [];
    renderChart(
      buckets.value.map((item) => item.label),
      res.data.series || []
    );
  } finally {
    loading.value = false;
  }
}

async function resetQuery() {
  initDefaultRange();
  query.interval = 'hour';
  await handleQuery();
}

function resizeChart() {
  chartInstance?.resize();
}

onMounted(async () => {
  initDefaultRange();
  await nextTick();
  initChart();
  await handleQuery();
  window.addEventListener('resize', resizeChart);
});

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeChart);
  chartInstance?.dispose();
  chartInstance = undefined;
});
</script>

<style scoped>
.electricity-bill-page {
  min-height: 100%;
}

.query-form {
  margin-bottom: 12px;
}

.interval-select {
  width: 120px;
}

.chart-wrap {
  position: relative;
  min-height: 360px;
  margin-bottom: 14px;
}

.bill-chart {
  width: 100%;
  height: 360px;
}

.chart-empty {
  position: absolute;
  inset: 50px 0 0;
  background: rgba(255, 255, 255, 0.72);
}

.bill-table {
  width: 100%;
}
</style>
