import { createRouter, createWebHistory } from 'vue-router';
import { useAuthStore } from '../stores/auth';
import { useSmokeTestsAllowed } from '../composables/useSmokeTestsAllowed';
import { hydrateStaffSession } from '../utils/session-hydrate';
import { reconcileStaffSessionFromToken } from '../stores/auth';
import { AdminPerm } from '../constants/permissions';
import { adminCanAccess, firstAdminFallback } from '../utils/admin-access';

/** Paths denied for specific admin roles (SUPER_ADMIN bypasses). */
const ROLE_ROUTE_DENY: Record<string, string[]> = {
  '/finance-logs': ['MATCH_ADMIN'],
  '/cashback': ['MATCH_ADMIN', 'SUPPORT'],
};

function pathDeniedForRole(path: string, role?: string): boolean {
  if (!role || role === 'SUPER_ADMIN') return false;
  const base = path.split('?')[0];
  for (const [prefix, roles] of Object.entries(ROLE_ROUTE_DENY)) {
    if ((base === prefix || base.startsWith(`${prefix}/`)) && roles.includes(role)) {
      return true;
    }
  }
  return false;
}

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/login', component: () => import('../views/Login.vue'), meta: { public: true } },
    {
      path: '/',
      component: () => import('../layouts/ManageLayout.vue'),
      meta: { auth: true },
      children: [
        {
          path: '',
          component: () => import('../views/HomeEntry.vue'),
          meta: { permissions: [AdminPerm.reports] },
          children: [
            {
              path: '',
              component: () => import('../views/dashboard/DashboardMatches.vue'),
            },
            {
              path: 'dashboard/players',
              component: () => import('../views/dashboard/DashboardPlayers.vue'),
            },
          ],
        },
        {
          path: 'invites',
          redirect: '/users',
        },
        {
          path: 'users',
          component: () => import('../views/AgentManager.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.usersView, AdminPerm.agentsView] },
          children: [
            {
              path: 'agents/:agentId/players',
              name: 'admin-agent-direct-players',
              component: () => import('../views/agent/AgentDirectPlayersView.vue'),
            },
            {
              path: 'settings',
              name: 'admin-global-settings',
              component: () => import('../views/agent/GlobalSettingsView.vue'),
            },
          ],
        },
        {
          path: 'finance-logs',
          component: () => import('../views/FinanceLogs.vue'),
          meta: { permissions: [AdminPerm.reports] },
        },
        {
          path: 'agent-credit-transactions',
          redirect: (to) => ({
            path: '/finance-logs',
            query: { ...to.query, tab: 'credit' },
          }),
        },
        {
          path: 'agents',
          redirect: '/users',
        },
        {
          path: 'matches',
          component: () => import('../views/Matches.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
          children: [
            {
              path: 'leagues/:leagueId',
              name: 'admin-league-matches',
              component: () => import('../views/matches/LeagueMatchesPage.vue'),
            },
          ],
        },
        {
          path: 'matches/outrights',
          component: () => import('../views/MatchesOutrights.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
          children: [
            {
              path: 'leagues/:leagueId',
              name: 'admin-league-outrights',
              component: () => import('../views/matches/LeagueOutrightsPage.vue'),
            },
          ],
        },
        {
          path: 'matches/market-templates',
          component: () => import('../views/MarketTemplates.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
        },
        {
          path: 'matches/audit-logs',
          component: () => import('../views/MatchesAudit.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
        },
        {
          path: 'matches/:matchId/edit',
          name: 'admin-match-edit',
          component: () => import('../views/matches/MatchEventEditor.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
        },
        {
          path: 'matches/:matchId/markets',
          name: 'admin-match-markets',
          component: () => import('../views/matches/MatchMarketsPage.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
        },
        { path: 'outrights', redirect: '/matches/outrights' },
        {
          path: 'outrights/:matchId/edit',
          name: 'admin-outright-edit',
          component: () => import('../views/outrights/OutrightEditRedirect.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.matches] },
        },
        { path: 'world-cup-outright', redirect: '/matches/outrights' },
        {
          path: 'bets',
          component: () => import('../views/Bets.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.bets] },
        },
        {
          path: 'settlement/:id',
          component: () => import('../views/Settlement.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.settlement, AdminPerm.matches] },
        },
        {
          path: 'cashback',
          component: () => import('../views/Cashback.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.cashback] },
        },
        {
          path: 'contents',
          component: () => import('../views/Contents.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.content] },
        },
        {
          path: 'audit',
          component: () => import('../views/Audit.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.audit] },
        },
        {
          path: 'smoke-tests',
          component: () => import('../views/SmokeTests.vue'),
          meta: { adminOnly: true, smokeTestsOnly: true, permissions: [AdminPerm.settings] },
        },
        {
          path: 'media',
          component: () => import('../views/MediaLibrary.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.content, AdminPerm.matches] },
        },
        {
          path: 'payment-methods',
          redirect: (to) => ({
            path: '/deposit',
            query: { ...to.query, tab: 'methods' },
          }),
        },
        {
          path: 'deposit-orders',
          redirect: '/deposit',
        },
        {
          path: 'deposit',
          component: () => import('../views/DepositManage.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.depositManage, AdminPerm.depositReview] },
        },
        {
          path: 'staff',
          component: () => import('../views/StaffManage.vue'),
          meta: { adminOnly: true, permissions: [AdminPerm.settings] },
        },
        {
          path: 'my-players',
          component: () => import('../views/agent/Players.vue'),
          meta: { agentOnly: true },
        },
        {
          path: 'sub-agents',
          redirect: '/my-players',
        },
        {
          path: 'my-bets',
          component: () => import('../views/agent/Bets.vue'),
          meta: { agentOnly: true },
        },
      ],
    },
  ],
});

router.beforeEach(async (to) => {
  const auth = useAuthStore();
  const hasToken = !!auth.token.value;

  if (hasToken) {
    reconcileStaffSessionFromToken();
    // 后台刷新 session，不阻塞路由切换；401 由 api 拦截器处理
    void hydrateStaffSession();
  }

  const hasUser = !!auth.user.value?.userType;

  if (to.meta.public) {
    if (hasToken && hasUser) return '/';
    return true;
  }

  if (!hasToken || !hasUser) {
    auth.clearStaffSession();
    return { path: '/login', query: { redirect: to.fullPath } };
  }

  if (to.meta.adminOnly && !auth.isAdmin.value) {
    return '/';
  }

  if (auth.isAdmin.value && to.meta.permissions) {
    const required = to.meta.permissions as string[];
    const role = auth.user.value?.role;
    const permissions = auth.user.value?.permissions;
    if (pathDeniedForRole(to.path, role)) {
      const fallback = firstAdminFallback(role, permissions);
      if (fallback && to.path !== fallback) return fallback;
    }
    if (!adminCanAccess(role, permissions, required)) {
      const fallback = firstAdminFallback(role, permissions);
      if (!fallback) {
        return true;
      }
      if (to.path !== fallback) return fallback;
    }
  }

  if (to.path.startsWith('/dashboard/') && !auth.isAdmin.value) {
    return '/';
  }

  if (to.meta.agentOnly && !auth.isAgent.value) {
    return '/';
  }

  if (to.meta.tier1AgentOnly && !auth.isTier1Agent.value) {
    return '/';
  }

  if (to.meta.smokeTestsOnly) {
    const { allowed } = useSmokeTestsAllowed();
    if (allowed.value === false) return '/';
  }

  return true;
});

/** 发版后旧 index.html 可能引用已不存在的 hash chunk，自动刷新一次拉最新入口。 */
function isLazyChunkLoadError(err: unknown): boolean {
  const msg = err instanceof Error ? err.message : String(err ?? '');
  return (
    msg.includes('Failed to fetch dynamically imported module') ||
    msg.includes('Importing a module script failed') ||
    msg.includes('error loading dynamically imported module')
  );
}

const CHUNK_RELOAD_FLAG = 'admin:chunk-reload';

router.onError((error, to) => {
  if (!isLazyChunkLoadError(error)) throw error;
  const target = to.fullPath || '/';
  if (!sessionStorage.getItem(CHUNK_RELOAD_FLAG)) {
    sessionStorage.setItem(CHUNK_RELOAD_FLAG, target);
    window.location.assign(target);
    return;
  }
  sessionStorage.removeItem(CHUNK_RELOAD_FLAG);
  throw error;
});

export default router;
