import {
  createContext,
  lazy,
  Suspense,
  startTransition,
  useContext,
  useEffect,
  useCallback,
  useMemo,
  useState,
  type ReactNode,
} from 'react'
import {
  BrowserRouter,
  Navigate,
  Outlet,
  Route,
  Routes,
  useNavigate,
} from 'react-router-dom'
import { LoaderCircle } from 'lucide-react'
import { Toaster, toast } from 'sonner'

import { AppShell } from '@/components/app-shell'
import { adminApi, ApiError } from '@/lib/api'
import type { AdminSessionResponse } from '@/lib/types'
import { LoginPage } from '@/pages/login-page'

const DashboardPage = lazy(async () => {
  const mod = await import('@/pages/dashboard-page')
  return { default: mod.DashboardPage }
})
const AnalyticsPage = lazy(async () => {
  const mod = await import('@/pages/analytics-page')
  return { default: mod.AnalyticsPage }
})
const PostsPage = lazy(async () => {
  const mod = await import('@/pages/posts-page')
  return { default: mod.PostsPage }
})
const PostPreviewPage = lazy(async () => {
  const mod = await import('@/pages/post-preview-page')
  return { default: mod.PostPreviewPage }
})
const PostComparePage = lazy(async () => {
  const mod = await import('@/pages/post-compare-page')
  return { default: mod.PostComparePage }
})
const PostPolishPage = lazy(async () => {
  const mod = await import('@/pages/post-polish-page')
  return { default: mod.PostPolishPage }
})
const CategoriesPage = lazy(async () => {
  const mod = await import('@/pages/categories-page')
  return { default: mod.CategoriesPage }
})
const TagsPage = lazy(async () => {
  const mod = await import('@/pages/tags-page')
  return { default: mod.TagsPage }
})
const BackupsPage = lazy(async () => {
  const mod = await import('@/pages/backups-page')
  return { default: mod.BackupsPage }
})
const RevisionsPage = lazy(async () => {
  const mod = await import('@/pages/revisions-page')
  return { default: mod.RevisionsPage }
})
const CommentsPage = lazy(async () => {
  const mod = await import('@/pages/comments-page')
  return { default: mod.CommentsPage }
})
const FriendLinksPage = lazy(async () => {
  const mod = await import('@/pages/friend-links-page')
  return { default: mod.FriendLinksPage }
})
const MediaPage = lazy(async () => {
  const mod = await import('@/pages/media-page')
  return { default: mod.MediaPage }
})
const ReviewsPage = lazy(async () => {
  const mod = await import('@/pages/reviews-page')
  return { default: mod.ReviewsPage }
})
const SiteSettingsPage = lazy(async () => {
  const mod = await import('@/pages/site-settings-page')
  return { default: mod.SiteSettingsPage }
})
const SubscriptionsPage = lazy(async () => {
  const mod = await import('@/pages/subscriptions-page')
  return { default: mod.SubscriptionsPage }
})
const WorkersPage = lazy(async () => {
  const mod = await import('@/pages/workers-page')
  return { default: mod.WorkersPage }
})
const AuditPage = lazy(async () => {
  const mod = await import('@/pages/audit-page')
  return { default: mod.AuditPage }
})

type SessionContextValue = {
  session: AdminSessionResponse
  setSession: (session: AdminSessionResponse) => void
  refreshSession: () => Promise<void>
}

const SessionContext = createContext<SessionContextValue | null>(null)

function useSession() {
  const context = useContext(SessionContext)

  if (!context) {
    throw new Error('useSession must be used inside SessionContext')
  }

  return context
}

function AppLoadingScreen() {
  return (
    <div className="flex min-h-screen items-center justify-center bg-background px-6 text-foreground">
      <div className="flex max-w-md flex-col items-center gap-4 rounded-3xl border border-border/70 bg-card/80 px-8 py-10 text-center shadow-[0_24px_80px_rgba(15,23,42,0.18)] backdrop-blur">
        <div className="flex h-14 w-14 items-center justify-center rounded-2xl border border-primary/20 bg-primary/10 text-primary">
          <LoaderCircle className="h-6 w-6 animate-spin" />
        </div>
        <div className="space-y-2">
          <p className="text-xs uppercase tracking-[0.32em] text-muted-foreground">
            Termi 后台
          </p>
          <h1 className="text-2xl font-semibold tracking-tight">正在进入管理后台</h1>
          <p className="text-sm leading-6 text-muted-foreground">
            正在检查当前登录状态，并准备新的 React 管理工作台。
          </p>
        </div>
      </div>
    </div>
  )
}

function RouteLoadingScreen() {
  return (
    <div className="flex min-h-[320px] items-center justify-center rounded-3xl border border-border/70 bg-card/60 px-6 py-10 text-center text-muted-foreground">
      <div className="space-y-3">
        <div className="mx-auto flex h-12 w-12 items-center justify-center rounded-2xl border border-primary/20 bg-primary/10 text-primary">
          <LoaderCircle className="h-5 w-5 animate-spin" />
        </div>
        <div>
          <p className="text-sm font-medium text-foreground">正在加载页面模块</p>
          <p className="mt-1 text-sm">大型编辑器与工作台页面会按需加载。</p>
        </div>
      </div>
    </div>
  )
}

function LazyRoute({ children }: { children: ReactNode }) {
  return <Suspense fallback={<RouteLoadingScreen />}>{children}</Suspense>
}

function RequireAuth({ children }: { children: ReactNode }) {
  const { session } = useSession()

  if (!session.authenticated) {
    return <Navigate to="/login" replace />
  }

  return <>{children}</>
}

function PublicOnly() {
  const { session, setSession } = useSession()
  const navigate = useNavigate()
  const [submitting, setSubmitting] = useState(false)

  if (session.authenticated) {
    return <Navigate to="/" replace />
  }

  return (
    <LoginPage
      submitting={submitting}
      localLoginEnabled={session.local_login_enabled}
      proxyAuthEnabled={session.proxy_auth_enabled}
      onLogin={async (payload) => {
        try {
          setSubmitting(true)
          const nextSession = await adminApi.login(payload)
          startTransition(() => {
            setSession(nextSession)
          })
          toast.success('后台登录成功。')
          navigate('/', { replace: true })
        } catch (error) {
          toast.error(error instanceof ApiError ? error.message : '当前无法登录后台。')
        } finally {
          setSubmitting(false)
        }
      }}
    />
  )
}

function ProtectedLayout() {
  const { session, setSession } = useSession()
  const navigate = useNavigate()
  const [loggingOut, setLoggingOut] = useState(false)

  return (
    <AppShell
      username={session.username}
      email={session.email}
      authSource={session.auth_source}
      authProvider={session.auth_provider}
      loggingOut={loggingOut}
      canLogout={session.can_logout}
      onLogout={async () => {
        try {
          setLoggingOut(true)
          const nextSession = await adminApi.logout()
          startTransition(() => {
            setSession(nextSession)
          })
          toast.success('已退出后台。')
          navigate('/login', { replace: true })
        } catch (error) {
          toast.error(error instanceof ApiError ? error.message : '当前无法退出后台。')
        } finally {
          setLoggingOut(false)
        }
      }}
    >
      <Outlet />
    </AppShell>
  )
}

function AppRoutes() {
  return (
    <Routes>
      <Route path="/login" element={<PublicOnly />} />
      <Route
        path="/posts/preview"
        element={
          <RequireAuth>
            <LazyRoute>
              <PostPreviewPage />
            </LazyRoute>
          </RequireAuth>
        }
      />
      <Route
        path="/posts/:slug/preview"
        element={
          <RequireAuth>
            <LazyRoute>
              <PostPreviewPage />
            </LazyRoute>
          </RequireAuth>
        }
      />
      <Route
        path="/posts/compare"
        element={
          <RequireAuth>
            <LazyRoute>
              <PostComparePage />
            </LazyRoute>
          </RequireAuth>
        }
      />
      <Route
        path="/posts/:slug/compare"
        element={
          <RequireAuth>
            <LazyRoute>
              <PostComparePage />
            </LazyRoute>
          </RequireAuth>
        }
      />
      <Route
        path="/posts/polish"
        element={
          <RequireAuth>
            <LazyRoute>
              <PostPolishPage />
            </LazyRoute>
          </RequireAuth>
        }
      />
      <Route
        path="/"
        element={
          <RequireAuth>
            <ProtectedLayout />
          </RequireAuth>
        }
        >
        <Route
          index
          element={
            <LazyRoute>
              <DashboardPage />
            </LazyRoute>
          }
        />
        <Route
          path="analytics"
          element={
            <LazyRoute>
              <AnalyticsPage />
            </LazyRoute>
          }
        />
        <Route
          path="posts"
          element={
            <LazyRoute>
              <PostsPage />
            </LazyRoute>
          }
        />
        <Route
          path="posts/:slug"
          element={
            <LazyRoute>
              <PostsPage />
            </LazyRoute>
          }
        />
        <Route
          path="categories"
          element={
            <LazyRoute>
              <CategoriesPage />
            </LazyRoute>
          }
        />
        <Route
          path="tags"
          element={
            <LazyRoute>
              <TagsPage />
            </LazyRoute>
          }
        />
        <Route
          path="backups"
          element={
            <LazyRoute>
              <BackupsPage />
            </LazyRoute>
          }
        />
        <Route
          path="revisions"
          element={
            <LazyRoute>
              <RevisionsPage />
            </LazyRoute>
          }
        />
        <Route
          path="comments"
          element={
            <LazyRoute>
              <CommentsPage />
            </LazyRoute>
          }
        />
        <Route
          path="friend-links"
          element={
            <LazyRoute>
              <FriendLinksPage />
            </LazyRoute>
          }
        />
        <Route
          path="media"
          element={
            <LazyRoute>
              <MediaPage />
            </LazyRoute>
          }
        />
        <Route
          path="subscriptions"
          element={
            <LazyRoute>
              <SubscriptionsPage />
            </LazyRoute>
          }
        />
        <Route
          path="workers"
          element={
            <LazyRoute>
              <WorkersPage />
            </LazyRoute>
          }
        />
        <Route
          path="audit"
          element={
            <LazyRoute>
              <AuditPage />
            </LazyRoute>
          }
        />
        <Route
          path="reviews"
          element={
            <LazyRoute>
              <ReviewsPage />
            </LazyRoute>
          }
        />
        <Route
          path="settings"
          element={
            <LazyRoute>
              <SiteSettingsPage />
            </LazyRoute>
          }
        />
      </Route>
      <Route path="*" element={<Navigate to="/" replace />} />
    </Routes>
  )
}

export default function App() {
  const [session, setSession] = useState<AdminSessionResponse>({
    authenticated: false,
    username: null,
    email: null,
    auth_source: null,
    auth_provider: null,
    groups: [],
    proxy_auth_enabled: false,
    local_login_enabled: true,
    can_logout: false,
  })
  const [loading, setLoading] = useState(true)

  const refreshSession = useCallback(async () => {
    try {
      const nextSession = await adminApi.sessionStatus()
      startTransition(() => {
        setSession(nextSession)
      })
    } catch (error) {
      toast.error(
        error instanceof ApiError ? error.message : '当前无法连接后台会话接口。',
      )
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    void refreshSession()
  }, [refreshSession])

  const contextValue = useMemo<SessionContextValue>(
    () => ({
      session,
      setSession,
      refreshSession,
    }),
    [session, refreshSession],
  )

  const basename =
    ((import.meta.env.VITE_ADMIN_BASENAME as string | undefined)?.trim() || '').replace(
      /\/$/,
      '',
    ) || undefined

  if (loading) {
    return (
      <>
        <AppLoadingScreen />
        <Toaster richColors position="top-right" />
      </>
    )
  }

  return (
    <SessionContext.Provider value={contextValue}>
      <BrowserRouter basename={basename}>
        <AppRoutes />
      </BrowserRouter>
      <Toaster richColors position="top-right" />
    </SessionContext.Provider>
  )
}
