<script lang="ts" setup>
/**
 * 管理驾驶舱合并卡（超管/系统管理员）：平台总览 + 待办中心整合为一张卡
 * 为什么合并：两个模块都是「今日经营快照」，拆成两张卡会让首屏纵向过长；
 * 合并后放在工作台顶部左列，与右列公告构成一行，信息密度更高
 * 数据仍走 workbench/platform-overview 与 workbench/todo-center 两个接口并行拉取
 */
import type { PlatformOverviewResult, TodoCenterItem } from '../api';

import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';

import { IconifyIcon as VbenIcon } from '@vben/icons';

import { getPlatformOverviewApi, getTodoCenterApi } from '../api';
import StatChip from './StatChip.vue';

interface Props {
  /** 总览分区标题（来自布局下发的 platform_overview.title） */
  overviewTitle: string;
  /** 待办分区标题（来自布局下发的 todo_center.title），未配置时兜底「待办中心」 */
  todoTitle?: string;
}
const props = withDefaults(defineProps<Props>(), {
  todoTitle: '待办中心',
});

/** 待办 code → 图标映射（后端只下发 code，图标属于前端展示细节） */
const TODO_ICON_MAP: Record<string, string> = {
  prescription_pending: 'lucide:shield-check',
  withdraw_pending: 'lucide:banknote',
  store_input_pending: 'lucide:store',
  wait_delivery: 'lucide:package',
  refunding: 'lucide:rotate-ccw',
};

const router = useRouter();
const overview = ref<null | PlatformOverviewResult>(null);
const todoItems = ref<TodoCenterItem[]>([]);
const loading = ref(true);
const error = ref(false);

/** 待办全部清零时展示鼓励空态，而不是一排 0 */
const allClear = computed(
  () => todoItems.value.length > 0 && todoItems.value.every((it) => it.count <= 0),
);

/**
 * 并行拉取总览与待办；任一失败进入整卡错误态可重试
 * 为什么整卡而不是分区错误：两个接口来自同一后端服务，同挂同恢复，分区错误徒增复杂度
 */
async function fetchAll() {
  loading.value = true;
  error.value = false;
  try {
    const [ov, todo] = await Promise.all([
      getPlatformOverviewApi(),
      getTodoCenterApi(),
    ]);
    overview.value = ov;
    todoItems.value = todo.items || [];
  } catch {
    error.value = true;
  } finally {
    loading.value = false;
  }
}

/** 跳转指定路由（失败静默，避免无权限菜单时报错） */
function go(path: string) {
  if (!path) return;
  router.push(path).catch(() => {});
}

onMounted(fetchAll);
</script>

<template>
  <div class="admin-hub">
    <!-- 总览分区头：标题 + 今日说明 + 整卡刷新 -->
    <div class="admin-hub__head">
      <span class="admin-hub__title-bar"></span>
      <span class="admin-hub__title">{{ props.overviewTitle }}</span>
      <span class="admin-hub__subtitle">今日</span>
      <button
        type="button"
        class="admin-hub__refresh"
        :class="{ 'is-loading': loading }"
        :disabled="loading"
        aria-label="刷新"
        @click="fetchAll"
      >
        <VbenIcon icon="lucide:refresh-cw" />
      </button>
    </div>

    <!-- 加载骨架：总览与待办两组芯片占位，避免布局跳动 -->
    <template v-if="loading">
      <div class="admin-hub__chips" aria-label="加载中">
        <div v-for="n in 4" :key="n" class="hub-skeleton">
          <div class="sk sk-icon"></div>
          <div class="sk-lines">
            <div class="sk sk-value"></div>
            <div class="sk sk-label"></div>
          </div>
        </div>
      </div>
      <div class="admin-hub__divider"></div>
      <div class="admin-hub__chips" aria-label="加载中">
        <div v-for="n in 5" :key="n" class="hub-skeleton">
          <div class="sk sk-icon"></div>
          <div class="sk-lines">
            <div class="sk sk-value"></div>
            <div class="sk sk-label"></div>
          </div>
        </div>
      </div>
    </template>

    <!-- 失败态：整卡重试 -->
    <div v-else-if="error" class="admin-hub__error">
      <VbenIcon icon="lucide:cloud-off" class="admin-hub__error-icon" />
      <span>数据加载失败</span>
      <button type="button" class="admin-hub__retry" @click="fetchAll">
        重试
      </button>
    </div>

    <template v-else>
      <!-- 平台总览：四个统计芯片撑满一行 -->
      <div v-if="overview" class="admin-hub__chips">
        <StatChip
          :value="overview.order_count"
          icon="lucide:shopping-cart"
          label="今日订单"
          @click="go('/order/product-order')"
        />
        <StatChip
          :value="`¥${overview.revenue}`"
          icon="lucide:banknote"
          label="今日营业额"
          @click="go('/order/product-order')"
        />
        <StatChip
          :value="overview.register_count"
          icon="lucide:stethoscope"
          label="今日挂号"
          @click="go('/business/register/list')"
        />
        <StatChip
          :value="overview.store_input_count"
          icon="lucide:store"
          label="新增门店录入"
          @click="go('/system/store-input')"
        />
      </div>

      <div class="admin-hub__divider"></div>

      <!-- 待办中心分区 -->
      <div class="admin-hub__sub-head">
        <span class="admin-hub__title-bar admin-hub__title-bar--sub"></span>
        <span class="admin-hub__sub-title">{{ props.todoTitle }}</span>
      </div>

      <div v-if="allClear" class="admin-hub__clear">
        <VbenIcon icon="lucide:party-popper" class="admin-hub__clear-icon" />
        <span>今日无待办，全部处理完毕</span>
      </div>

      <!-- 待办改用统计芯片（与总览同视觉），count>0 高亮提示优先处理 -->
      <div v-else class="admin-hub__chips">
        <StatChip
          v-for="item in todoItems"
          :key="item.code"
          :value="item.count > 999 ? '999+' : item.count"
          :label="item.label"
          :icon="TODO_ICON_MAP[item.code] || 'lucide:list-todo'"
          :highlight="item.count > 0"
          @click="go(item.path)"
        />
      </div>
    </template>

    <!-- 卡底公告轮播条：父级按布局配置注入（NoticeTicker），数据源独立不受本卡 loading 影响 -->
    <slot name="notice"></slot>
  </div>
</template>

<style scoped>
.admin-hub {
  height: 100%;
  padding: 18px 20px;
  background: hsl(var(--card));
  border: 1px solid hsl(var(--border) / 0.7);
  border-radius: 12px;
}

.admin-hub__head {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}

.admin-hub__title-bar {
  width: 3px;
  height: 14px;
  background: linear-gradient(180deg, hsl(var(--primary)), hsl(var(--primary) / 0.4));
  border-radius: 2px;
}

.admin-hub__title-bar--sub {
  height: 12px;
  opacity: 0.7;
}

.admin-hub__title {
  font-size: 15px;
  font-weight: 650;
  color: hsl(var(--foreground));
  letter-spacing: -0.01em;
}

.admin-hub__subtitle {
  font-size: 12px;
  color: hsl(var(--muted-foreground));
}

/* 刷新按钮：靠右，hover 才显主色 */
.admin-hub__refresh {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  margin-left: auto;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: hsl(var(--muted-foreground));
  cursor: pointer;
  transition:
    color 0.15s ease,
    background 0.15s ease;
}

.admin-hub__refresh:hover:not(:disabled) {
  color: hsl(var(--primary));
  background: hsl(var(--primary) / 0.08);
}

.admin-hub__refresh :deep(svg) {
  width: 14px;
  height: 14px;
}

.admin-hub__refresh.is-loading :deep(svg) {
  animation: hub-spin 0.8s linear infinite;
}

/* 统计芯片区（总览与待办共用）：芯片等分撑满一行，放不下自动换行 */
.admin-hub__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.admin-hub__chips :deep(.stat-chip) {
  flex: 1;
  min-width: 128px;
}

.admin-hub__divider {
  height: 1px;
  margin: 14px 0;
  background: hsl(var(--border) / 0.6);
}

.admin-hub__sub-head {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 10px;
}

.admin-hub__sub-title {
  font-size: 13.5px;
  font-weight: 600;
  color: hsl(var(--foreground));
}

/* 空态：全部清零 */
.admin-hub__clear {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 14px 4px;
  font-size: 13px;
  color: hsl(var(--muted-foreground));
}

.admin-hub__clear-icon {
  width: 18px;
  height: 18px;
  color: hsl(var(--primary));
}

/* ===== 骨架占位 ===== */
.hub-skeleton {
  display: flex;
  gap: 12px;
  align-items: center;
  flex: 1;
  min-width: 128px;
  padding: 14px 16px;
  border: 1px solid hsl(var(--border) / 0.5);
  border-radius: 12px;
}

.sk {
  border-radius: 8px;
  background: linear-gradient(
    90deg,
    hsl(var(--muted) / 0.5) 25%,
    hsl(var(--muted) / 0.3) 50%,
    hsl(var(--muted) / 0.5) 75%
  );
  background-size: 200% 100%;
  animation: hub-shimmer 1.4s ease-in-out infinite;
}

.sk-icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
}

.sk-lines {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.sk-value {
  width: 56px;
  height: 18px;
}

.sk-label {
  width: 40px;
  height: 10px;
}

/* ===== 失败态 ===== */
.admin-hub__error {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 14px 4px;
  font-size: 13px;
  color: hsl(var(--muted-foreground));
}

.admin-hub__error-icon {
  width: 16px;
  height: 16px;
}

.admin-hub__retry {
  height: 26px;
  padding: 0 12px;
  border: 1px solid hsl(var(--primary) / 0.35);
  border-radius: 999px;
  background: hsl(var(--primary) / 0.06);
  color: hsl(var(--primary));
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.admin-hub__retry:hover {
  background: hsl(var(--primary) / 0.12);
}

@keyframes hub-spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes hub-shimmer {
  0% {
    background-position: 200% 0;
  }

  100% {
    background-position: -200% 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sk,
  .admin-hub__refresh.is-loading :deep(svg) {
    animation: none;
    transition: none;
  }
}
</style>
