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

echarts.use([
  PieChart,
  BarChart,
  LineChart,
  GridComponent,
  TitleComponent,
  LegendComponent,
  TooltipComponent,
  DataZoomComponent,
  CanvasRenderer
]);
import { getDashboard, getTrend, getWashDeviceStatus } from "@/api/stat";
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";

defineOptions({
  name: "Dashboard"
});

const homeLineRef = ref();
const homePieRef = ref();
const { dataTheme } = useDataThemeChange();

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

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

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) => {
  const diffTime = Math.abs(end.getTime() - start.getTime());
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
};

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

// 品牌衍生图表色板
const CHART_BAR = "#4DA89D";
const CHART_LINE = "#C83A35";
const CHART_GRID = "#EBEBEB";

const PIE_COLORS = [
  "#C83A35",
  "#4DA89D",
  "#E5A350",
  "#8B7EC8",
  "#5BA0D9",
  "#8E8E8E"
];

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,
    dispose: [null, "", undefined]
  },
  metrics: {
    registeredMembers: { value: "0", label: "今日注册会员", icon: "ri/user-add-line" },
    todayIncome: { value: "0", label: "今日收益金额", icon: "ri/money-dollar-circle-line" },
    consumptionAmount: { value: "0", label: "今日消费总额", icon: "ri/shopping-cart-2-line" },
    avgOrderPrice: { value: "0", label: "订单均价", icon: "ri/calculator-line" },
    todayOrders: { value: "0", label: "今日订单数量", icon: "ri/file-list-3-line" },
    avgDuration: { value: "0", label: "洗车平均时长", icon: "ri/timer-line" }
  },
  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.global.dispose.some((b: any) => b === 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 xAxis = dataList.map(k => k.startTime);
  const option = {
    backgroundColor: state.charts.bgColor,
    title: {
      text: "洗车数据走势图",
      x: "left",
      textStyle: { fontSize: "15", color: state.charts.color }
    },
    grid: { top: 70, right: 0, bottom: 30, left: 50 },
    tooltip: { trigger: "axis" },
    legend: { data: ["洗车量", "总金额"], right: 20 },
    xAxis: {
      data: xAxis
    },
    yAxis: [
      {
        type: "value",
        name: "费用/元  洗车量/次",
        position: "left",
        splitLine: { show: true, lineStyle: { type: "dashed", color: CHART_GRID } }
      }
    ],
    series: [
      {
        name: "洗车量",
        type: "bar",
        barWidth: 10,
        symbolSize: 6,
        symbol: "circle",
        smooth: true,
        data: dataList.map(k => k.totalOrders),
        lineStyle: { color: CHART_BAR },
        itemStyle: { color: CHART_BAR, borderColor: CHART_BAR, barBorderRadius: 5 }
      },
      {
        name: "总金额",
        type: "line",
        symbolSize: 6,
        symbol: "circle",
        smooth: true,
        data: dataList.map(k => fmtMoney(k.totalAmount)),
        lineStyle: { color: CHART_LINE },
        itemStyle: { color: CHART_LINE, borderColor: CHART_LINE }
      }
    ]
  };
  state.global.homeChartOne.setOption(option);
  state.myCharts.push(state.global.homeChartOne);
};

const initPieChart = (dataMap: any) => {
  if (!state.global.dispose.some((b: any) => b === 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 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: "洗车设备状态",
      x: "left",
      textStyle: { fontSize: "15", color: state.charts.color }
    },
    tooltip: { trigger: "item", formatter: "{b} <br/> {c}" },
    legend: {
      type: "scroll",
      orient: "vertical",
      right: "0%",
      left: "65%",
      top: "center",
      itemWidth: 14,
      itemHeight: 14,
      data: getname,
      textStyle: { color: state.charts.color }
    },
    series: [
      {
        type: "pie",
        radius: ["82", dataTheme.value ? "50" : "102"],
        center: ["32%", "50%"],
        itemStyle: {
          color: (params: any) => PIE_COLORS[params.dataIndex % PIE_COLORS.length]
        },
        label: { show: false },
        labelLine: { show: false },
        data: data
      }
    ]
  };
  state.global.homeChartTwo.setOption(option);
  state.myCharts.push(state.global.homeChartTwo);
};

const initEchartsResizeFun = () => {
  nextTick(() => {
    for (let i = 0; i < state.myCharts.length; i++) {
      setTimeout(() => {
        state.myCharts[i]?.resize();
      }, i * 200);
    }
  });
};

const initEchartsResize = () => {
  window.addEventListener("resize", initEchartsResizeFun);
};

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.registeredMembers.value = String(data.todayRegisteredMembers || 0);
      state.metrics.todayIncome.value = fmtMoney(data.todayIncome || 0);
      state.metrics.consumptionAmount.value = fmtMoney(data.todayConsumptionAmount || 0);
      state.metrics.avgOrderPrice.value = fmtMoney(data.avgOrderPrice || 0);
      state.metrics.todayOrders.value = String(data.todayWashOrders || 0);
      state.metrics.avgDuration.value = ((data.avgOrderDuration || 0) / 60).toFixed(1);
    }
  });
};

onMounted(() => {
  const currentStationId = Session.get("currentStationId");
  if (currentStationId) {
    state.currentStationId = currentStationId;
    initEchartsResize();
    loadStationStat();
    loadStationStatToday();
    loadCurrentEquipmentStatus();
  } else {
    initEchartsResize();
  }
});

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

watch(
  () => dataTheme.value,
  (isDark) => {
    nextTick(() => {
      state.charts.theme = isDark ? "dark" : "";
      state.charts.bgColor = isDark ? "transparent" : "";
      state.charts.color = isDark ? "#C8C8C8" : "#303133";
      setTimeout(() => loadStationStat(), 500);
      setTimeout(() => loadCurrentEquipmentStatus(), 700);
    });
  }
);

const featuredMetrics = computed(() => [
  state.metrics.todayIncome,
  state.metrics.todayOrders
]);

const secondaryMetrics = computed(() => [
  state.metrics.consumptionAmount,
  state.metrics.avgOrderPrice,
  state.metrics.registeredMembers,
  state.metrics.avgDuration
]);

const isMoneyMetric = (label: string) => {
  return label.includes("金额") || label.includes("收益") || label.includes("均价") || label.includes("消费");
};
</script>

<template>
  <div class="dashboard-container">
    <!-- 未选择站点提醒 -->
    <el-alert
      v-if="!state.currentStationId"
      title="未选择站点"
      type="warning"
      description="请通过右上角站点选择器切换到要查看的门店，选择后将自动加载统计数据"
      show-icon
      closable
      class="mb-4"
    />

    <!-- 核心指标 -->
    <div class="featured-row">
      <div
        v-for="(metric, idx) in featuredMetrics"
        :key="idx"
        class="featured-card"
        :class="idx === 0 ? 'featured-primary' : 'featured-secondary'"
      >
        <div class="featured-icon">
          <component :is="useRenderIcon(metric.icon)" />
        </div>
        <div class="featured-body">
          <div class="featured-value">
            {{ metric.value }}
            <span v-if="isMoneyMetric(metric.label)" class="featured-unit">元</span>
            <span v-else class="featured-unit">笔</span>
          </div>
          <div class="featured-label">{{ metric.label }}</div>
        </div>
      </div>
    </div>

    <!-- 次要指标 -->
    <div class="secondary-row">
      <div
        v-for="(metric, idx) in secondaryMetrics"
        :key="idx"
        class="secondary-card"
      >
        <div class="secondary-icon">
          <component :is="useRenderIcon(metric.icon)" />
        </div>
        <div class="secondary-body">
          <div class="secondary-value">
            {{ metric.value }}
            <span v-if="isMoneyMetric(metric.label)" class="secondary-unit">元</span>
            <span v-else-if="metric.label.includes('时长')" class="secondary-unit">分钟</span>
            <span v-else class="secondary-unit">人</span>
          </div>
          <div class="secondary-label">{{ metric.label }}</div>
        </div>
      </div>
    </div>

    <!-- 图表区域 -->
    <el-row :gutter="15">
      <el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16">
        <el-card class="chart-card">
          <template #header>
            <div class="chart-header">
              <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"
              />
              <div class="chart-summary">
                总收益:
                <el-tag type="success" size="small">{{ fmtMoney(state.homeOneExtra.totalIncome) }}元</el-tag>
                总订单:
                <el-tag type="danger" size="small">{{ state.homeOneExtra.totalWashOrders }}笔</el-tag>
              </div>
            </div>
          </template>
          <div class="chart-wrapper" ref="homeLineRef" />
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
        <el-card class="chart-card">
          <div class="chart-wrapper" ref="homePieRef" />
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

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

// 核心指标行
.featured-row {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 15px;
  margin-bottom: 15px;

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
  }
}

.featured-card {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 24px 28px;
  border-radius: 4px;
  background: var(--el-bg-color);

  &.featured-primary {
    box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
    border-top: 3px solid var(--el-color-primary);
  }

  &.featured-secondary {
    box-shadow: 0 1px 3px rgb(0 0 0 / 6%);
  }

  .featured-icon {
    font-size: 40px;
    color: var(--el-color-primary);
    opacity: 0.85;
    flex-shrink: 0;
  }

  .featured-body {
    .featured-value {
      font-size: 36px;
      font-weight: 700;
      line-height: 1.2;
      color: var(--el-text-color-primary);
      letter-spacing: -0.5px;
    }

    .featured-unit {
      font-size: 16px;
      font-weight: 500;
      color: var(--el-text-color-secondary);
      margin-left: 4px;
    }

    .featured-label {
      margin-top: 6px;
      font-size: 14px;
      font-weight: 500;
      color: var(--el-text-color-secondary);
    }
  }
}

// 次要指标行
.secondary-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 15px;
  margin-bottom: 15px;

  @media (max-width: 992px) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (max-width: 640px) {
    grid-template-columns: 1fr;
  }
}

.secondary-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  border-radius: 4px;
  background: var(--el-bg-color);
  box-shadow: 0 1px 2px rgb(0 0 0 / 4%);

  .secondary-icon {
    font-size: 28px;
    color: var(--el-text-color-placeholder);
    flex-shrink: 0;
  }

  .secondary-body {
    min-width: 0;

    .secondary-value {
      font-size: 22px;
      font-weight: 600;
      line-height: 1.3;
      color: var(--el-text-color-primary);
    }

    .secondary-unit {
      font-size: 12px;
      font-weight: 500;
      color: var(--el-text-color-secondary);
      margin-left: 2px;
    }

    .secondary-label {
      margin-top: 2px;
      font-size: 13px;
      color: var(--el-text-color-secondary);
    }
  }
}

// 图表
.chart-card {
  margin-bottom: 15px;

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

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

      .el-tag {
        margin: 0 4px;
      }
    }
  }

  .chart-wrapper {
    height: 350px;
    width: 100%;
  }
}

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

  .featured-card {
    padding: 18px 20px;

    .featured-value {
      font-size: 28px;
    }
  }
}
</style>
