<script setup lang="ts">
import { ref, onMounted, onUnmounted, reactive } from "vue";
import * as echarts from "echarts";
import { getRepurchaseOverview, getRepurchaseDistribution, getRepurchaseTrend, getRepurchaseUsers } from "@/api/statistics";
import type { EChartsOption } from "echarts";

defineOptions({
  name: "RepurchaseStatistics"
});

const loading = ref(false);
const dateRange = ref<[Date, Date]>([
  new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
  new Date()
]);
const activeShortcut = ref("30d");

const shortcuts = [
  { key: "today", label: "今日" },
  { key: "week", label: "本周" },
  { key: "month", label: "本月" },
  { key: "30d", label: "近30天" }
];

const queryParams = reactive({
  page: 1,
  pageSize: 10,
  shopId: null as number | null,
  userLayer: "",
  minOrderCount: null as number | null,
  sortBy: "totalAmount",
  sortOrder: "desc"
});

const overviewData = ref({
  totalUsers: 0,
  newUsers: 0,
  repurchaseUsers: 0,
  repurchaseRate: 0,
  avgOrderAmount: 0,
  avgPurchaseCount: 0,
  ltv: 0
});

const tableData = ref<any[]>([]);
const total = ref(0);

const layerChartRef = ref<HTMLElement | null>(null);
const intervalChartRef = ref<HTMLElement | null>(null);
const trendChartRef = ref<HTMLElement | null>(null);
let layerChart: echarts.ECharts | null = null;
let intervalChart: echarts.ECharts | null = null;
let trendChart: echarts.ECharts | null = null;

function formatDate(date: Date): string { return date.toISOString().split("T")[0]; }

function setDateShortcut(type: string) {
  activeShortcut.value = type;
  const today = new Date(); today.setHours(23, 59, 59, 999);
  let start: Date;
  switch (type) {
    case "today": start = new Date(); start.setHours(0, 0, 0, 0); break;
    case "week": start = new Date(today); start.setDate(today.getDate() - 6); start.setHours(0, 0, 0, 0); break;
    case "month": start = new Date(today.getFullYear(), today.getMonth(), 1); break;
    case "30d": default: start = new Date(today); start.setDate(today.getDate() - 29); start.setHours(0, 0, 0, 0); break;
  }
  dateRange.value = [start, today];
  fetchAll();
}

function handleDateChange() { activeShortcut.value = ""; fetchAll(); }

function fetchAll() {
  fetchOverview();
  fetchDistribution();
  fetchTrend();
  fetchUserList();
}

async function fetchOverview() {
  try {
    const params = { startDate: formatDate(dateRange.value[0]), endDate: formatDate(dateRange.value[1]) };
    const res = await getRepurchaseOverview(params);
    if (res.code === 200 && res.data) overviewData.value = res.data;
  } catch (e) { console.error(e); }
}

async function fetchDistribution() {
  try {
    const baseParams = { startDate: formatDate(dateRange.value[0]), endDate: formatDate(dateRange.value[1]) };
    const layerRes = await getRepurchaseDistribution({ ...baseParams, type: "layer" });
    if (layerRes.code === 200 && layerRes.data) initLayerChart(layerRes.data.distribution);
    const intervalRes = await getRepurchaseDistribution({ ...baseParams, type: "interval" });
    if (intervalRes.code === 200 && intervalRes.data) initIntervalChart(intervalRes.data.distribution);
  } catch (e) { console.error(e); }
}

async function fetchTrend() {
  try {
    const params = { startDate: formatDate(dateRange.value[0]), endDate: formatDate(dateRange.value[1]) };
    const res = await getRepurchaseTrend(params);
    if (res.code === 200 && res.data) initTrendChart(res.data);
  } catch (e) { console.error(e); }
}

async function fetchUserList() {
  loading.value = true;
  try {
    const params: any = { ...queryParams, startDate: formatDate(dateRange.value[0]), endDate: formatDate(dateRange.value[1]) };
    const res = await getRepurchaseUsers(params);
    if (res.code === 200 && res.data) {
      tableData.value = res.data.list || [];
      total.value = Number(res.data.total) || 0;
    }
  } catch (e) { console.error(e); } finally { loading.value = false; }
}

function initLayerChart(distribution: any) {
  if (!layerChartRef.value) return;
  layerChart?.dispose();
  layerChart = echarts.init(layerChartRef.value);
  const chartData = Object.entries(distribution || {}).map(([name, value]) => ({ name, value }));
  const option: EChartsOption = {
    tooltip: { trigger: "item", formatter: "{b}: {c} ({d}%)" },
    legend: { bottom: "0%", left: "center", textStyle: { fontSize: 11 } },
    series: [{
      name: "用户层级", type: "pie", radius: ["45%", "72%"], avoidLabelOverlap: false,
      itemStyle: { borderRadius: 6, borderColor: "#fff", borderWidth: 2 },
      label: { show: false }, emphasis: { label: { show: true, fontSize: 14, fontWeight: "bold" } }, labelLine: { show: false },
      data: chartData.map((item: any, i: number) => ({ ...item, itemStyle: { color: ["#409eff", "#67c23a", "#e6a23c", "#f56c6c"][i % 4] } }))
    }]
  };
  layerChart.setOption(option);
}

function initIntervalChart(distribution: any) {
  if (!intervalChartRef.value) return;
  intervalChart?.dispose();
  intervalChart = echarts.init(intervalChartRef.value);
  const categories = Object.keys(distribution || {});
  const values = Object.values(distribution || {});
  const option: EChartsOption = {
    tooltip: { trigger: "axis", axisPointer: { type: "shadow" } },
    grid: { left: "3%", right: "4%", bottom: "3%", top: "8%", containLabel: true },
    xAxis: { type: "category", data: categories, axisLabel: { rotate: 30, fontSize: 10 } },
    yAxis: { type: "value", name: "用户数" },
    series: [{ name: "用户数", type: "bar", data: values, barWidth: "50%", itemStyle: { borderRadius: [4, 4, 0, 0], color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: "#83bff6" }, { offset: 1, color: "#188df0" }]) } }]
  };
  intervalChart.setOption(option);
}

function initTrendChart(data: any) {
  if (!trendChartRef.value) return;
  trendChart?.dispose();
  trendChart = echarts.init(trendChartRef.value);
  const option: EChartsOption = {
    tooltip: { trigger: "axis", backgroundColor: "#fff", borderColor: "#e5e7eb", textStyle: { color: "#333" } },
    grid: { left: "3%", right: "4%", bottom: "5%", top: "8%", containLabel: true },
    xAxis: { type: "category", data: data.dates || [], axisLabel: { rotate: 45, fontSize: 10 } },
    yAxis: { type: "value", name: "复购率(%)", max: 100 },
    series: [{ name: "复购率", type: "line", smooth: true, data: data.series?.[0]?.data || [], symbol: "circle", symbolSize: 4, lineStyle: { color: "#722ed1", width: 2 }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: "rgba(114,46,209,0.25)" }, { offset: 1, color: "rgba(114,46,209,0.02)" }]) } }]
  };
  trendChart.setOption(option);
}

function handleSearch() { queryParams.page = 1; fetchUserList(); }
function handleReset() { queryParams.shopId = null; queryParams.userLayer = ""; queryParams.minOrderCount = null; queryParams.page = 1; fetchUserList(); }
function handleSortChange({ prop, order }: any) { queryParams.sortBy = prop || "totalAmount"; queryParams.sortOrder = order === "ascending" ? "asc" : "desc"; fetchUserList(); }
function handlePageChange(page: number) { queryParams.page = page; fetchUserList(); }
function handleSizeChange(size: number) { queryParams.pageSize = size; queryParams.page = 1; fetchUserList(); }

function getUserLayerTagType(layer: string): "info" | "success" | "warning" | "danger" {
  switch (layer) {
    case "new": return "info";
    case "active": return "success";
    case "loyal": return "warning";
    case "churn": return "danger";
    default: return "info";
  }
}

function resizeCharts() { layerChart?.resize(); intervalChart?.resize(); trendChart?.resize(); }

onMounted(() => {
  fetchAll();
  window.addEventListener("resize", resizeCharts);
});
onUnmounted(() => {
  window.removeEventListener("resize", resizeCharts);
  layerChart?.dispose();
  intervalChart?.dispose();
  trendChart?.dispose();
});
</script>

<template>
  <div class="repurchase-statistics">
    <div class="toolbar">
      <h2 class="page-title">用户复购统计</h2>
      <div class="toolbar-right">
        <div class="date-shortcuts">
          <el-button v-for="s in shortcuts" :key="s.key" :type="activeShortcut === s.key ? 'primary' : 'default'" size="small" @click="setDateShortcut(s.key)">{{ s.label }}</el-button>
        </div>
        <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD" size="small" @change="handleDateChange" />
      </div>
    </div>

    <div v-loading="loading" class="page-body">
      <el-row :gutter="16" class="kpi-row">
        <el-col :xs="12" :sm="6" :lg="6">
          <div class="kpi-card kpi-blue"><div class="kpi-label">总用户数</div><div class="kpi-value">{{ (overviewData.totalUsers || 0).toLocaleString() }}</div></div>
        </el-col>
        <el-col :xs="12" :sm="6" :lg="6">
          <div class="kpi-card kpi-green"><div class="kpi-label">复购用户数</div><div class="kpi-value">{{ (overviewData.repurchaseUsers || 0).toLocaleString() }}</div></div>
        </el-col>
        <el-col :xs="12" :sm="6" :lg="6">
          <div class="kpi-card kpi-purple"><div class="kpi-label">复购率</div><div class="kpi-value">{{ overviewData.repurchaseRate || 0 }}%</div></div>
        </el-col>
        <el-col :xs="12" :sm="6" :lg="6">
          <div class="kpi-card kpi-orange"><div class="kpi-label">用户LTV</div><div class="kpi-value">¥{{ (overviewData.ltv || 0).toLocaleString() }}</div></div>
        </el-col>
      </el-row>

      <el-row :gutter="16" class="kpi-row">
        <el-col :xs="12" :sm="8" :lg="8">
          <div class="kpi-card kpi-cyan"><div class="kpi-label">新用户数</div><div class="kpi-value">{{ (overviewData.newUsers || 0).toLocaleString() }}</div></div>
        </el-col>
        <el-col :xs="12" :sm="8" :lg="8">
          <div class="kpi-card kpi-teal"><div class="kpi-label">平均客单价</div><div class="kpi-value">¥{{ (overviewData.avgOrderAmount || 0).toLocaleString() }}</div></div>
        </el-col>
        <el-col :xs="12" :sm="8" :lg="8">
          <div class="kpi-card kpi-indigo"><div class="kpi-label">平均购买次数</div><div class="kpi-value">{{ overviewData.avgPurchaseCount || 0 }}</div></div>
        </el-col>
      </el-row>

      <el-row :gutter="16" class="chart-row">
        <el-col :span="8">
          <div class="chart-box"><div class="chart-title">用户分层分布</div><div ref="layerChartRef" class="chart-container"></div></div>
        </el-col>
        <el-col :span="8">
          <div class="chart-box"><div class="chart-title">复购间隔分布</div><div ref="intervalChartRef" class="chart-container"></div></div>
        </el-col>
        <el-col :span="8">
          <div class="chart-box"><div class="chart-title">复购率趋势</div><div ref="trendChartRef" class="chart-container"></div></div>
        </el-col>
      </el-row>

      <div class="table-box">
        <div class="table-header">
          <span class="table-title">用户复购明细</span>
          <div class="table-actions">
            <el-select v-model="queryParams.userLayer" placeholder="用户层级" clearable size="small" style="width: 120px">
              <el-option label="新用户" value="new" />
              <el-option label="活跃用户" value="active" />
              <el-option label="忠诚用户" value="loyal" />
              <el-option label="流失用户" value="churn" />
            </el-select>
            <el-input-number v-model="queryParams.minOrderCount" placeholder="最小购买次数" :min="1" controls-position="right" size="small" style="width: 140px" />
            <el-button type="primary" size="small" @click="handleSearch">搜索</el-button>
            <el-button size="small" @click="handleReset">重置</el-button>
          </div>
        </div>
        <el-table :data="tableData" stripe v-loading="loading" @sort-change="handleSortChange">
          <el-table-column prop="nickname" label="用户昵称" min-width="120" fixed="left" show-overflow-tooltip />
          <el-table-column prop="phone" label="手机号" width="120" />
          <el-table-column prop="userLayerLabel" label="用户层级" width="100" align="center">
            <template #default="{ row }">
              <el-tag :type="getUserLayerTagType(row.userLayer)" size="small">{{ row.userLayerLabel }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="orderCount" label="购买次数" width="90" align="right" sortable="custom" />
          <el-table-column prop="totalAmount" label="累计消费" width="120" align="right" sortable="custom">
            <template #default="{ row }">¥{{ (row.totalAmount || 0).toLocaleString() }}</template>
          </el-table-column>
          <el-table-column prop="avgOrderAmount" label="平均客单价" width="110" align="right">
            <template #default="{ row }">¥{{ (row.avgOrderAmount || 0).toLocaleString() }}</template>
          </el-table-column>
          <el-table-column prop="firstOrderDate" label="首次下单" width="110" />
          <el-table-column prop="lastOrderDate" label="最近下单" width="110" />
          <el-table-column prop="repurchaseDays" label="复购间隔(天)" width="110" align="right" />
        </el-table>
        <div class="table-footer">
          <el-pagination
            v-model:current-page="queryParams.page"
            v-model:page-size="queryParams.pageSize"
            :page-sizes="[10, 20, 50, 100]"
            :total="total"
            layout="total, sizes, prev, pager, next, jumper"
            background small
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.repurchase-statistics {
  padding: 16px 20px;
  background-color: #f5f7fa;
  min-height: calc(100vh - 120px);
}

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

  .page-title {
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #1d2129;
  }

  .toolbar-right {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
  }

  .date-shortcuts {
    display: flex;
    gap: 4px;
  }
}

.page-body { min-height: 400px; }

.kpi-row { margin-bottom: 12px; }

.kpi-card {
  background: #fff;
  border-radius: 8px;
  padding: 16px 20px;
  height: 100%;
  border-left: 4px solid #409eff;
  transition: box-shadow 0.2s;

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

  &.kpi-blue { border-left-color: #409eff; }
  &.kpi-green { border-left-color: #67c23a; }
  &.kpi-purple { border-left-color: #722ed1; }
  &.kpi-orange { border-left-color: #fa8c16; }
  &.kpi-cyan { border-left-color: #13c2c2; }
  &.kpi-teal { border-left-color: #52c41a; }
  &.kpi-indigo { border-left-color: #597ef7; }

  .kpi-label {
    font-size: 13px;
    color: #86909c;
    margin-bottom: 6px;
  }

  .kpi-value {
    font-size: 22px;
    font-weight: 700;
    color: #1d2129;
    line-height: 1.2;
  }
}

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

.chart-box {
  background: #fff;
  border-radius: 8px;
  padding: 16px;
  height: 340px;

  .chart-title {
    font-size: 14px;
    font-weight: 600;
    color: #1d2129;
    margin-bottom: 8px;
  }

  .chart-container {
    width: 100%;
    height: calc(100% - 26px);
  }
}

.table-box {
  background: #fff;
  border-radius: 8px;
  padding: 16px;

  .table-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
  }

  .table-title {
    font-size: 14px;
    font-weight: 600;
    color: #1d2129;
  }

  .table-actions {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .table-footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 16px;
  }
}

@media (max-width: 768px) {
  .kpi-value { font-size: 18px !important; }
  .chart-box { height: 280px; }
}
</style>
