<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';
import api from '../api';
import { formatAmount, formatAmountFull } from '../utils/format-amount';
import type { AdminDashboard } from './dashboard-types';
import EChartPanel from '../components/dashboard/EChartPanel.vue';
import { buildCombinedTrendOption, buildTriplePieOption } from '../utils/dashboard-charts';
import { betStatusLabel } from '../utils/bet-labels';

const stats = ref<AdminDashboard | null>(null);
const loading = ref(true);

onMounted(load);

async function load() {
  loading.value = true;
  try {
    const { data } = await api.get('/admin/dashboard');
    stats.value = data.data as AdminDashboard;
  } finally {
    loading.value = false;
  }
}

const s = computed(() => stats.value);

function fmtCount(val: number | undefined) {
  return (val ?? 0).toLocaleString('zh-CN', { maximumFractionDigits: 0 });
}

function formatTime(v: string) {
  return new Date(v).toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

function toNum(v: string | number | undefined) {
  const n = typeof v === 'number' ? v : parseFloat(v ?? '0');
  return Number.isFinite(n) ? n : 0;
}

function pctChange(today: string | number, yesterday: string | number) {
  const t = toNum(today);
  const y = toNum(yesterday);
  if (y === 0) return t > 0 ? '+100%' : '—';
  const p = ((t - y) / y) * 100;
  const sign = p > 0 ? '+' : '';
  return `${sign}${p.toFixed(1)}%`;
}

const trendLabels = computed(() => s.value?.trend7d?.map((d) => d.label) ?? []);

const mainTrendOption = computed(() =>
  buildCombinedTrendOption(
    trendLabels.value,
    [
      {
        name: '投注额',
        color: '#248f54',
        values: s.value?.trend7d?.map((d) => toNum(d.stake)) ?? [],
      },
      {
        name: '派彩',
        color: '#60a5fa',
        values: s.value?.trend7d?.map((d) => toNum(d.payout)) ?? [],
      },
      {
        name: '毛利',
        color: '#a78bfa',
        values: s.value?.trend7d?.map((d) => toNum(d.ggr)) ?? [],
      },
    ],
    s.value?.trend7d?.map((d) => d.betCount) ?? [],
  ),
);

const distributionOption = computed(() => {
  const m = s.value?.matches;
  const u = s.value?.users;
  const raw = s.value?.bets.todayByStatus ?? {};
  const betColors: Record<string, string> = {
    PENDING: '#fb923c',
    WON: '#248f54',
    LOST: '#f87171',
    VOID: '#6b7280',
    REFUNDED: '#60a5fa',
  };

  const matchSegs = m
    ? [
        { label: '草稿', value: m.draft, color: '#6b7280' },
        { label: '已发布', value: m.published, color: '#248f54' },
        { label: '已封盘', value: m.closed, color: '#60a5fa' },
        { label: '待结算', value: m.pendingSettlement, color: '#fb923c' },
        { label: '已结算', value: m.settled ?? 0, color: '#5eead4' },
      ].filter((x) => x.value > 0)
    : [];

  const betSegs = ['PENDING', 'WON', 'LOST', 'VOID', 'REFUNDED']
    .filter((k) => raw[k]?.count)
    .map((k) => ({
      label: betStatusLabel(k),
      value: raw[k].count,
      color: betColors[k] ?? '#888',
    }));

  const userSegs = u
    ? [
        { label: '正常玩家', value: u.playersActive, color: '#248f54' },
        { label: '停用', value: u.playersSuspended, color: '#f87171' },
        { label: '直属', value: u.playersDirect, color: '#60a5fa' },
        { label: '代理', value: u.agentsTotal, color: '#a78bfa' },
      ].filter((x) => x.value > 0)
    : [];

  return buildTriplePieOption([
    { title: '赛事', segments: matchSegs },
    { title: '今日注单', segments: betSegs },
    { title: '用户', segments: userSegs },
  ]);
});

const kpiPrimary = computed(() => {
  if (!s.value) return [];
  const t = s.value.today;
  const y = s.value.yesterday;
  return [
    { label: '今日投注笔数', value: fmtCount(t.betCount), sub: `昨日 ${fmtCount(y.betCount)}`, delta: pctChange(t.betCount, y.betCount) },
    { label: '今日投注额', value: formatAmount(t.stake), sub: formatAmountFull(t.stake), delta: pctChange(t.stake, y.stake) },
    { label: '今日派彩', value: formatAmount(t.payout), sub: `昨日 ${formatAmount(y.payout)}`, delta: pctChange(t.payout, y.payout) },
    { label: '今日毛利', value: formatAmount(t.ggr), sub: `昨日 ${formatAmount(y.ggr)}`, delta: pctChange(t.ggr, y.ggr) },
  ];
});

const kpiSecondary = computed(() => {
  if (!s.value) return [];
  return [
    { label: '玩家 / 代理', value: `${fmtCount(s.value.users.playersTotal)} / ${fmtCount(s.value.users.agentsTotal)}`, sub: `今日新增 ${fmtCount(s.value.today.newPlayers)} 人` },
    { label: '待结算', value: `${fmtCount(s.value.bets.pendingTotal)} 单`, sub: `${fmtCount(s.value.matches.pendingSettlement)} 场赛事` },
    { label: '玩家余额', value: formatAmount(s.value.wallets.totalAvailable), sub: `冻结 ${formatAmount(s.value.wallets.totalFrozen)}` },
    { label: '代理授信', value: formatAmount(s.value.agents.totalAvailableCredit), sub: `已用 ${formatAmount(s.value.agents.totalUsedCredit)}` },
  ];
});
</script>

<template>
  <div class="dashboard-page" v-loading="loading">
    <div class="page-header">
      <div>
        <h2 class="page-title">控制台</h2>
        <span class="page-desc">
          平台整体运行概况
          <template v-if="s?.generatedAt"> · 更新于 {{ formatTime(s.generatedAt) }}</template>
        </span>
      </div>
    </div>

    <template v-if="s">
      <el-card class="overview-board" shadow="never">
        <div class="board-head">
          <span class="board-title">整体概览</span>
          <span class="board-hint">一屏查看经营趋势与平台分布</span>
        </div>

        <div class="kpi-grid kpi-primary">
          <div v-for="item in kpiPrimary" :key="item.label" class="kpi-cell">
            <span class="kpi-label">{{ item.label }}</span>
            <span class="kpi-value">{{ item.value }}</span>
            <span class="kpi-sub">{{ item.sub }}</span>
            <span
              class="kpi-delta"
              :class="{ up: item.delta.startsWith('+'), down: item.delta.startsWith('-') }"
            >
              较昨日 {{ item.delta }}
            </span>
          </div>
        </div>

        <div class="kpi-grid kpi-secondary">
          <div v-for="item in kpiSecondary" :key="item.label" class="kpi-cell compact">
            <span class="kpi-label">{{ item.label }}</span>
            <span class="kpi-value sm">{{ item.value }}</span>
            <span class="kpi-sub">{{ item.sub }}</span>
          </div>
        </div>

        <div class="charts-stack">
          <EChartPanel
            title=""
            :option="mainTrendOption"
            height="300px"
            class="chart-main"
          />
          <div class="chart-main-caption">近 7 日经营趋势（金额折线 + 注单柱）</div>

          <EChartPanel title="" :option="distributionOption" height="200px" class="chart-dist" />
        </div>
      </el-card>
    </template>
  </div>
</template>

<style scoped>
.dashboard-page { padding-bottom: 32px; }
.page-header { margin-bottom: 20px; }
.page-title { font-size: 20px; font-weight: 700; color: #e0e0e0; margin: 0 0 4px; }
.page-desc { font-size: 13px; color: #666; }

.overview-board {
  border-radius: 14px;
  border: 1px solid #1e1e1e;
  background: linear-gradient(180deg, rgba(36, 143, 84, 0.06) 0%, rgba(0, 0, 0, 0) 120px);
  margin-bottom: 28px;
}
.overview-board :deep(.el-card__body) {
  padding: 20px 22px 16px;
}
.board-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 18px;
}
.board-title {
  font-size: 16px;
  font-weight: 700;
  color: #e8e8e8;
}
.board-hint {
  font-size: 12px;
  color: #555;
}

.kpi-grid {
  display: grid;
  gap: 10px;
  margin-bottom: 10px;
}
.kpi-primary {
  grid-template-columns: repeat(4, 1fr);
}
.kpi-secondary {
  grid-template-columns: repeat(4, 1fr);
  margin-bottom: 18px;
}
.kpi-cell {
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid #222;
  background: rgba(255, 255, 255, 0.03);
}
.kpi-cell.compact {
  padding: 10px 12px;
}
.kpi-label {
  display: block;
  font-size: 11px;
  color: #666;
  margin-bottom: 6px;
}
.kpi-value {
  display: block;
  font-size: 22px;
  font-weight: 800;
  color: var(--green-text);
  line-height: 1.15;
  letter-spacing: -0.5px;
}
.kpi-value.sm {
  font-size: 17px;
}
.kpi-sub {
  display: block;
  font-size: 11px;
  color: #555;
  margin-top: 4px;
}
.kpi-delta {
  display: inline-block;
  margin-top: 6px;
  font-size: 10px;
  font-weight: 600;
  color: #888;
  padding: 2px 6px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.04);
}
.kpi-delta.up { color: #4ade80; }
.kpi-delta.down { color: #f87171; }

.charts-stack {
  border-top: 1px solid #1a1a1a;
  padding-top: 12px;
}
.chart-main-caption {
  font-size: 11px;
  color: #555;
  text-align: center;
  margin: -8px 0 8px;
}
.charts-stack :deep(.chart-panel) {
  border: none;
  background: transparent;
  padding: 8px 0 0;
}
.charts-stack :deep(.chart-title:empty) {
  display: none;
}
.chart-dist {
  margin-top: 4px;
}

@media (max-width: 1200px) {
  .kpi-primary,
  .kpi-secondary {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 640px) {
  .kpi-primary,
  .kpi-secondary {
    grid-template-columns: 1fr;
  }
}

</style>
