<script setup lang="ts">
import { markRaw, nextTick, onActivated, onMounted, onBeforeUnmount, reactive, ref, watch } from "vue";
import * as echarts from "echarts/core";
import { PieChart, BarChart, LineChart } from "echarts/charts";
import {
  GridComponent,
  TitleComponent,
  LegendComponent,
  TooltipComponent
} from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

echarts.use([
  PieChart, BarChart, LineChart,
  GridComponent, TitleComponent, LegendComponent, TooltipComponent,
  CanvasRenderer
]);
import { getDashboard, getTrend, getWashDeviceStatus } from "@/api/stat";
import { emitter } from "@/utils/mitt";

defineOptions({ name: "Dashboard" });

const homeLineRef = ref();
const homePieRef = ref();

const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);

const fmtMoney = (value: number) => {
  if (!value) return "¥0.00";
  return `¥${(value / 100).toFixed(2)}`;
};

const fmtNumber = (value: any) => {
  if (value === null || value === undefined) return "0";
  return String(value);
};

const formatDate = (date: Date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};

const dateDiff = (start: Date, end: Date) => {
  return Math.ceil(Math.abs(end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
};

const Session = {
  get: (key: string) => {
    const value = sessionStorage.getItem(key);
    return value ? JSON.parse(value) : null;
  }
};

const state = reactive({
  currentStationId: null as string | null,
  dateRange: [formatDate(start), formatDate(end)] as [string, string],
  global: {
    homeChartOne: null as any,
    homeChartTwo: null as any
  },
  metrics: [
    { key: "registeredMembers", value: "0", label: "今日注册会员数", unit: "人", color: "#5470C6" },
    { key: "todayIncome", value: "0", label: "今日收益金额", unit: "元", color: "#91CC75" },
    { key: "consumptionAmount", value: "0", label: "今日消费总额", unit: "元", color: "#FAC858" },
    { key: "avgOrderPrice", value: "0", label: "订单平均消费", unit: "元", color: "#EE6666" },
    { key: "todayOrders", value: "0", label: "今日订单数量", unit: "笔", color: "#73C0DE" },
    { key: "avgDuration", value: "0", label: "洗车平均时长", unit: "分钟", color: "#8B7EC8" }
  ] as { key: string; value: string; label: string; unit: string; color: string }[],
  myCharts: [] as any[],
  charts: {
    theme: "",
    bgColor: "",
    color: "#303133"
  },
  homeOneExtra: {
    totalIncome: 0,
    totalWashOrders: 0
  }
});

const shortcuts = [
  {
    text: "近7天",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
      return [start, end];
    }
  },
  {
    text: "近30天",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
      return [start, end];
    }
  },
  {
    text: "近90天",
    value: () => {
      const end = new Date();
      const start = new Date();
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
      return [start, end];
    }
  }
];

const initLineChart = (dataList: Array<any>) => {
  if (!state.myCharts.includes(state.global.homeChartOne)) {
    state.global.homeChartOne?.dispose();
  }
  state.global.homeChartOne = markRaw(echarts.init(homeLineRef.value, state.charts.theme));

  dataList.forEach(item => {
    item.startTime = item.statTime.slice(0, 3).join("-");
    item.seq = Number(item.statTime.join(""));
  });

  state.homeOneExtra.totalIncome = dataList.reduce((k, v) => k + v.totalAmount, 0);
  state.homeOneExtra.totalWashOrders = dataList.reduce((k, v) => k + v.totalOrders, 0);

  dataList.sort((a, b) => a.seq - b.seq);

  const option = {
    backgroundColor: state.charts.bgColor,
    title: {
      text: "洗车数据走势图",
      left: 0,
      top: 0,
      textStyle: { fontSize: 15, color: state.charts.color }
    },
    grid: { top: 70, right: 80, bottom: 30, left: 60 },
    tooltip: {
      trigger: "axis",
      formatter: (params: any) => {
        const bar = params.find((p: any) => p.seriesName === "洗车量");
        const line = params.find((p: any) => p.seriesName === "总金额");
        const barVal = bar ? `${bar.value} 次` : "";
        const lineVal = line ? `¥${line.value}` : "";
        return `${params[0].axisValue}<br/>${barVal}<br/>${lineVal}`;
      }
    },
    legend: { data: ["洗车量", "总金额"], right: 10, top: 5 },
    xAxis: {
      data: dataList.map(k => k.startTime),
      axisLine: { lineStyle: { color: state.charts.color } }
    },
    yAxis: [
      {
        type: "value",
        name: "洗车量/次",
        position: "left",
        axisLabel: { color: "#68a7a0" },
        splitLine: { show: true, lineStyle: { type: "dashed", color: "#f0f0f0" } }
      },
      {
        type: "value",
        name: "费用/元",
        position: "right",
        axisLabel: { color: "#409EFF" },
        splitLine: { show: false }
      }
    ],
    series: [
      {
        name: "洗车量",
        type: "bar",
        barWidth: 10,
        yAxisIndex: 0,
        data: dataList.map(k => k.totalOrders),
        itemStyle: {
          color: "#68a7a0",
          borderColor: "#68a7a0",
          barBorderRadius: 5
        }
      },
      {
        name: "总金额",
        type: "line",
        symbolSize: 6,
        symbol: "circle",
        smooth: true,
        yAxisIndex: 1,
        data: dataList.map(k => (k.totalAmount / 100).toFixed(2)),
        lineStyle: { color: "#409EFF" },
        itemStyle: { color: "#409EFF", borderColor: "#409EFF" }
      }
    ]
  };
  state.global.homeChartOne.setOption(option);
  state.myCharts.push(state.global.homeChartOne);
};

const initPieChart = (dataMap: any) => {
  if (!state.myCharts.includes(state.global.homeChartTwo)) {
    state.global.homeChartTwo?.dispose();
  }
  state.global.homeChartTwo = markRaw(echarts.init(homePieRef.value, state.charts.theme));

  const sessionDicts = Session.get("dicts");
  let dicts: any[] = [];
  if (sessionDicts) {
    dicts = sessionDicts["WashDevice.state"] || [];
  }
  if (!dicts.length) return;

  const getname = dicts.map(k => k.name);
  const colorList = ["#6B6F75", "#36C78B", "#e9ee8e", "#ffa496", "#E790E8", "#363638"];
  const data: any[] = [];

  for (let i = 0; i < getname.length; i++) {
    const dict = dicts.find(k => k.name === getname[i]);
    data.push({ name: getname[i], value: dataMap[`${dict?.value}`] || 0 });
  }

  const option = {
    backgroundColor: state.charts.bgColor,
    title: {
      text: "洗车设备状态",
      left: 0,
      textStyle: { fontSize: 15, color: state.charts.color }
    },
    tooltip: { trigger: "item", formatter: "{b}<br/>{c} 台" },
    legend: {
      type: "scroll",
      orient: "vertical",
      right: 0,
      left: "62%",
      top: "center",
      itemWidth: 14,
      itemHeight: 14,
      data: getname,
      textStyle: { color: state.charts.color }
    },
    series: [
      {
        type: "pie",
        radius: ["82", "102"],
        center: ["30%", "50%"],
        itemStyle: {
          color: (params: any) => colorList[params.dataIndex % colorList.length]
        },
        label: { show: false },
        labelLine: { show: false },
        data
      }
    ]
  };
  state.global.homeChartTwo.setOption(option);
  state.myCharts.push(state.global.homeChartTwo);
};

const initEchartsResize = () => {
  nextTick(() => {
    for (let i = 0; i < state.myCharts.length; i++) {
      state.myCharts[i]?.resize();
    }
  });
};

const loadCurrentEquipmentStatus = () => {
  getWashDeviceStatus(state.currentStationId || undefined).then((res: any) => {
    initPieChart(res?.data || res || {});
  });
};

const loadStationStat = () => {
  const start = state.dateRange[0];
  const end = state.dateRange[1];
  const size = dateDiff(new Date(start), new Date(end)) + 1;

  getTrend({
    startTime: start,
    endTime: end,
    type: "day",
    pageSize: size,
    stationId: state.currentStationId || undefined
  }).then((res: any) => {
    initLineChart(res?.data || res);
  });
};

const loadStationStatToday = () => {
  getDashboard(state.currentStationId || undefined).then((res: any) => {
    const data = res?.data || res;
    if (data) {
      state.metrics[0].value = fmtNumber(data.todayRegisteredMembers);
      state.metrics[1].value = fmtMoney(data.todayIncome);
      state.metrics[2].value = fmtMoney(data.todayConsumptionAmount);
      state.metrics[3].value = fmtMoney(data.avgOrderPrice);
      state.metrics[4].value = fmtNumber(data.todayWashOrders);
      state.metrics[5].value = ((data.avgOrderDuration || 0) / 60).toFixed(1);
    }
  });
};

const loadAll = () => {
  loadStationStat();
  loadStationStatToday();
  loadCurrentEquipmentStatus();
};

onMounted(() => {
  emitter.on("stationChangeRefresh", (stationId) => {
    state.currentStationId = stationId;
    state.myCharts = [];
    nextTick(() => loadAll());
  });

  const currentStationId = Session.get("currentStationId");
  if (currentStationId) {
    state.currentStationId = currentStationId;
    loadAll();
  }
  window.addEventListener("resize", initEchartsResize);
});

onBeforeUnmount(() => {
  emitter.off("stationChangeRefresh");
  window.removeEventListener("resize", initEchartsResize);
});

onActivated(() => {
  initEchartsResize();
});

watch(
  () => state.charts.theme,
  () => {
    nextTick(() => {
      state.myCharts = [];
      setTimeout(() => loadStationStat(), 300);
      setTimeout(() => loadCurrentEquipmentStatus(), 500);
    });
  }
);
</script>

<template>
  <div class="dashboard-container">
    <!-- 未选择站点  -->
    <el-alert
      v-if="!state.currentStationId"
      title="未选择站点"
      type="warning"
      description="请通过右上角站点选择器切换到要查看的门店"
      show-icon
      closable
      class="mb15"
    />

    <!-- 6指标卡片  -->
    <el-row :gutter="15" class="metrics-row">
      <el-col
        v-for="(m, idx) in state.metrics"
        :key="m.key"
        :xs="12" :sm="8" :md="4" :lg="4" :xl="4"
      >
        <div class="metric-card">
          <div class="metric-value" :style="{ color: m.color }">{{ m.value }}</div>
          <div class="metric-label">{{ m.label }}</div>
        </div>
      </el-col>
    </el-row>

    <!-- 走势图 + 饼图 -->
    <el-row :gutter="15">
      <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16">
        <div class="chart-panel">
          <div class="chart-toolbar">
            <el-date-picker
              @change="loadStationStat"
              value-format="YYYY-MM-DD"
              v-model="state.dateRange"
              type="daterange"
              unlink-panels
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              :shortcuts="shortcuts"
              style="width: 280px"
            />
            <div class="chart-summary">
              总收益：
              <el-tag type="success" effect="plain" size="small">{{ fmtMoney(state.homeOneExtra.totalIncome) }}元</el-tag>
              总订单：
              <el-tag type="danger" effect="plain" size="small">{{ state.homeOneExtra.totalWashOrders }}笔</el-tag>
            </div>
          </div>
          <div class="chart-body" ref="homeLineRef" />
        </div>
      </el-col>
      <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
        <div class="chart-panel">
          <div class="chart-body" ref="homePieRef" />
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<style scoped lang="scss">
.dashboard-container {
  padding: 20px;
}

// 指标卡片
.metrics-row {
  margin-bottom: 15px;
}

.metric-card {
  height: 120px;
  border-radius: 6px;
  padding: 20px;
  margin-bottom: 0;
  background: #fff;
  border: 1px solid var(--el-border-color-lighter);
  transition: box-shadow 0.3s;

  &:hover {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
  }

  .metric-value {
    font-size: 30px;
    font-weight: 700;
    line-height: 1.3;
    letter-spacing: -0.5px;
  }

  .metric-label {
    margin-top: 8px;
    font-size: 14px;
    color: var(--el-text-color-secondary);
  }
}

// 图表面板
.chart-panel {
  width: 100%;
  background: #fff;
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
  padding: 20px;
  margin-bottom: 15px;
  transition: box-shadow 0.3s;

  &:hover {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
  }

  .chart-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 10px;

    .chart-summary {
      font-size: 14px;
      color: var(--el-text-color-secondary);
    }
  }

  .chart-body {
    height: 380px;
    width: 100%;
  }
}
</style>
