import {useCallback, useEffect, useState} from 'react';

import {
  formatAdminApiError,
  getAdminMe,
  isAdminApiError,
  loginAdmin,
} from '../api/adminApiClient';
import type {
  AdminSessionPayload,
  ProfileInviteCodeAdminResponse,
  ProfileRedeemCodeAdminResponse,
  ProfileTaskConfigAdminResponse,
} from '../api/adminApiTypes';
import {
  clearStoredAdminToken,
  getStoredAdminToken,
  setStoredAdminToken,
} from '../auth/adminAuthStore';
import {AdminCreationEntrySwitchPage} from '../pages/AdminCreationEntrySwitchPage';
import {AdminDebugHttpPage} from '../pages/AdminDebugHttpPage';
import {AdminDatabaseTablesPage} from '../pages/AdminDatabaseTablesPage';
import {AdminInviteCodePage} from '../pages/AdminInviteCodePage';
import {AdminLoginPage} from '../pages/AdminLoginPage';
import {AdminOverviewPage} from '../pages/AdminOverviewPage';
import {AdminRedeemCodePage} from '../pages/AdminRedeemCodePage';
import {AdminTaskConfigPage} from '../pages/AdminTaskConfigPage';
import {AdminTrackingEventsPage} from '../pages/AdminTrackingEventsPage';
import {AdminShell} from './AdminShell';
import type {AdminRouteId} from './adminRoutes';
import {resolveAdminRoute, routeHash} from './adminRoutes';

type SessionStatus = 'checking' | 'guest' | 'authenticated';

export function AdminApp() {
  const [status, setStatus] = useState<SessionStatus>('checking');
  const [admin, setAdmin] = useState<AdminSessionPayload | null>(null);
  const [token, setToken] = useState('');
  const [routeId, setRouteId] = useState<AdminRouteId>(() =>
    resolveAdminRoute(window.location.hash),
  );
  const [loginNotice, setLoginNotice] = useState('');
  // 兑换码页会随页签切换卸载，最近操作记录需要放在会话层保留。
  const [redeemResult, setRedeemResult] =
    useState<ProfileRedeemCodeAdminResponse | null>(null);
  const [inviteResult, setInviteResult] =
    useState<ProfileInviteCodeAdminResponse | null>(null);
  const [taskConfigResult, setTaskConfigResult] =
    useState<ProfileTaskConfigAdminResponse | null>(null);

  const clearSession = useCallback((message = '') => {
    clearStoredAdminToken();
    setToken('');
    setAdmin(null);
    setRedeemResult(null);
    setInviteResult(null);
    setTaskConfigResult(null);
    setStatus('guest');
    setLoginNotice(message);
  }, []);

  useEffect(() => {
    let isMounted = true;
    const storedToken = getStoredAdminToken();

    if (!storedToken) {
      setStatus('guest');
      return;
    }

    void getAdminMe(storedToken)
      .then((response) => {
        if (!isMounted) {
          return;
        }

        setToken(storedToken);
        setAdmin(response.admin);
        setStatus('authenticated');
      })
      .catch((error: unknown) => {
        if (!isMounted) {
          return;
        }

        clearStoredAdminToken();
        setToken('');
        setAdmin(null);
        setStatus('guest');
        setLoginNotice(
          isAdminApiError(error) && error.status === 401
            ? '登录状态已失效'
            : formatAdminApiError(error),
        );
      });

    return () => {
      isMounted = false;
    };
  }, []);

  useEffect(() => {
    const handleHashChange = () => {
      setRouteId(resolveAdminRoute(window.location.hash));
    };

    window.addEventListener('hashchange', handleHashChange);
    return () => window.removeEventListener('hashchange', handleHashChange);
  }, []);

  const handleRouteChange = useCallback((nextRouteId: AdminRouteId) => {
    setRouteId(nextRouteId);
    const nextHash = routeHash(nextRouteId);
    if (window.location.hash !== nextHash) {
      window.location.hash = nextHash;
    }
  }, []);

  const handleLogin = useCallback(async (username: string, password: string) => {
    const response = await loginAdmin(username, password);
    setStoredAdminToken(response.token);
    setToken(response.token);
    setAdmin(response.admin);
    setRedeemResult(null);
    setInviteResult(null);
    setTaskConfigResult(null);
    setLoginNotice('');
    setStatus('authenticated');
  }, []);

  const handleUnauthorized = useCallback(
    (message = '登录状态已失效') => {
      clearSession(message);
    },
    [clearSession],
  );

  const handleLogout = useCallback(() => {
    clearSession('');
  }, [clearSession]);

  if (status === 'checking') {
    return (
      <main className="admin-loading-screen">
        <div className="admin-loading-mark" />
        <span>正在校验会话</span>
      </main>
    );
  }

  if (status === 'guest' || !admin || !token) {
    return <AdminLoginPage notice={loginNotice} onLogin={handleLogin} />;
  }

  return (
    <AdminShell
      admin={admin}
      routeId={routeId}
      onLogout={handleLogout}
      onRouteChange={handleRouteChange}
    >
      {routeId === 'overview' ? (
        <AdminOverviewPage token={token} onUnauthorized={handleUnauthorized} />
      ) : null}
      {routeId === 'tables' ? (
        <AdminDatabaseTablesPage
          token={token}
          onUnauthorized={handleUnauthorized}
        />
      ) : null}
      {routeId === 'debug' ? (
        <AdminDebugHttpPage token={token} onUnauthorized={handleUnauthorized} />
      ) : null}
      {routeId === 'tracking' ? (
        <AdminTrackingEventsPage
          token={token}
          onUnauthorized={handleUnauthorized}
        />
      ) : null}
      {routeId === 'redeem' ? (
        <AdminRedeemCodePage
          result={redeemResult}
          token={token}
          onUnauthorized={handleUnauthorized}
          onResultChange={setRedeemResult}
        />
      ) : null}
      {routeId === 'invite' ? (
        <AdminInviteCodePage
          result={inviteResult}
          token={token}
          onUnauthorized={handleUnauthorized}
          onResultChange={setInviteResult}
        />
      ) : null}
      {routeId === 'creation-entry' ? (
        <AdminCreationEntrySwitchPage
          token={token}
          onUnauthorized={handleUnauthorized}
        />
      ) : null}
      {routeId === 'tasks' ? (
        <AdminTaskConfigPage
          result={taskConfigResult}
          token={token}
          onUnauthorized={handleUnauthorized}
          onResultChange={setTaskConfigResult}
        />
      ) : null}
    </AdminShell>
  );
}
