<template>
  <el-config-provider>
    <AdminLoginPanel
      v-if="!adminSessionState.token"
      @authenticated="handleAuthenticated"
    />

    <main v-else-if="adminSessionState.ready && !restoreError" class="app-shell">
      <aside class="sidebar">
        <div class="brand">
          <div class="brand-mark">棋</div>
          <div>
            <h1>自助棋牌室</h1>
            <p>运营后台</p>
          </div>
        </div>

        <nav class="nav-list" aria-label="后台模块">
          <RouterLink
            v-for="item in visibleNavigation"
            :key="item.menuKey"
            :to="item.path"
            class="nav-item"
            active-class="active"
          >
            <component :is="navigationIcons[item.icon]" :size="18" />
            <span>{{ item.label }}</span>
          </RouterLink>
        </nav>
      </aside>

      <section class="workspace">
        <header class="topbar">
          <div>
            <p class="eyebrow">{{ route.meta.stage || 'M08-D' }}</p>
            <h2>{{ route.meta.title || '运营后台' }}</h2>
          </div>
          <div class="session-box">
            <div class="session-user">
              <span>{{ adminSessionState.user?.nickname?.slice(0, 1) || '管' }}</span>
              <div>
                <strong>{{ adminSessionState.user?.nickname || '管理员' }}</strong>
                <small>{{ adminSessionState.access.roles.join(' · ') || '已登录' }}</small>
              </div>
            </div>
            <el-tooltip content="安全退出" placement="bottom">
              <el-button :icon="LogOut" circle @click="handleLogout" />
            </el-tooltip>
          </div>
        </header>

        <el-alert
          v-if="routeLoadError"
          class="route-alert"
          type="error"
          show-icon
          :closable="false"
          title="页面资源加载失败"
          :description="routeLoadError"
        >
          <template #default>
            <el-button type="primary" plain @click="retryLazyRoute">重新加载</el-button>
          </template>
        </el-alert>

        <RouterView v-else v-slot="{ Component }">
          <Suspense>
            <component
              :is="Component"
              :session="session"
              @open-cleaning="openCleaning"
            />
            <template #fallback>
              <section class="route-state" aria-live="polite">
                <el-skeleton :rows="8" animated />
              </section>
            </template>
          </Suspense>
        </RouterView>
      </section>
    </main>

    <main v-else class="session-recovery" aria-live="polite">
      <section v-if="restoreError" class="session-recovery-card">
        <h1>暂时无法恢复后台会话</h1>
        <p>{{ restoreError }}</p>
        <div>
          <el-button type="primary" :loading="restoring" @click="restoreSession">重试</el-button>
          <el-button @click="clearSession">返回登录</el-button>
        </div>
      </section>
      <section v-else class="session-recovery-card">
        <el-skeleton :rows="4" animated />
        <p>正在安全恢复会话与权限菜单…</p>
      </section>
    </main>
  </el-config-provider>
</template>

<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, type Component } from 'vue';
import { ElMessage } from 'element-plus';
import {
  ClipboardList,
  Handshake,
  Images,
  LayoutDashboard,
  LogOut,
  PanelsTopLeft,
  RadioTower,
  ScrollText,
  Sparkles,
  Store,
  TicketCheck,
  UsersRound,
  WalletCards
} from '@lucide/vue';
import { useRoute } from 'vue-router';
import AdminLoginPanel from './components/AdminLoginPanel.vue';
import {
  clearStoredSession,
  getAdminMe,
  logoutAdmin,
  storeAdminSession,
  type ApiSession
} from './api';
import {
  ADMIN_NAVIGATION,
  firstAuthorizedPath,
  isNavigationAllowed,
  resolveAuthorizedPath,
  type AdminMenuKey
} from './navigation.mjs';
import { router } from './router';
import {
  adminSessionState,
  applyAdminIdentity,
  applyAdminSession,
  clearAdminSessionState
} from './session';
import type { AdminSessionPayload } from './types';

const route = useRoute();
const restoring = ref(false);
const restoreError = ref('');
const routeLoadError = ref('');
const session = computed<ApiSession>(() => ({ token: adminSessionState.token }));
const visibleNavigation = computed(() => ADMIN_NAVIGATION.filter(
  (item) => isNavigationAllowed(adminSessionState.access, item)
));
const navigationIcons: Record<string, Component> = {
  ClipboardList,
  Handshake,
  Images,
  LayoutDashboard,
  PanelsTopLeft,
  RadioTower,
  ScrollText,
  Sparkles,
  Store,
  TicketCheck,
  UsersRound,
  WalletCards
};

function handleAuthenticated(payload: AdminSessionPayload) {
  storeAdminSession(payload);
  applyAdminSession(payload);
  restoreError.value = '';
  void ensureAllowedRoute();
  ElMessage.success('登录成功');
}

async function handleLogout() {
  try {
    await logoutAdmin(session.value);
  } catch {
    // 本地令牌清理是退出动作的最终安全边界。
  }
  clearSession();
}

function clearSession() {
  clearStoredSession();
  clearAdminSessionState();
  restoreError.value = '';
  routeLoadError.value = '';
  void router.replace('/overview');
}

function handleRefreshed(event: Event) {
  applyAdminSession((event as CustomEvent<AdminSessionPayload>).detail);
  void ensureAllowedRoute();
}

async function restoreSession() {
  if (!adminSessionState.token || restoring.value) return;
  restoring.value = true;
  restoreError.value = '';
  adminSessionState.ready = false;
  try {
    const result = await getAdminMe(session.value);
    applyAdminIdentity(result.user, result.access);
    await ensureAllowedRoute();
  } catch (error) {
    if (!localStorage.getItem('qipai.admin.token')) {
      clearAdminSessionState();
    } else {
      restoreError.value = error instanceof Error
        ? `${error.message}。请检查网络后重试，或返回登录。`
        : '会话恢复失败，请检查网络后重试。';
      adminSessionState.ready = true;
    }
  } finally {
    restoring.value = false;
  }
}

async function ensureAllowedRoute() {
  const menuKey = route.meta.menuKey as AdminMenuKey | undefined;
  const target = menuKey
    ? resolveAuthorizedPath(adminSessionState.access, menuKey)
    : firstAuthorizedPath(adminSessionState.access);
  if (target && target !== route.path) await router.replace(target);
}

function openCleaning() {
  void router.push('/cleaning');
}

function retryLazyRoute() {
  window.location.reload();
}

const removeRouterErrorHandler = router.onError((error) => {
  routeLoadError.value = error instanceof Error
    ? `${error.message}。可重新加载页面恢复。`
    : '路由资源加载失败，可重新加载页面恢复。';
});
const removeAfterEach = router.afterEach((_to, _from, failure) => {
  if (!failure) routeLoadError.value = '';
});

onMounted(() => {
  window.addEventListener('qipai:admin-refreshed', handleRefreshed);
  window.addEventListener('qipai:admin-unauthorized', clearSession);
  if (adminSessionState.token) void restoreSession();
});

onBeforeUnmount(() => {
  window.removeEventListener('qipai:admin-refreshed', handleRefreshed);
  window.removeEventListener('qipai:admin-unauthorized', clearSession);
  removeRouterErrorHandler();
  removeAfterEach();
});
</script>
