import { Suspense, lazy, type ComponentType, useEffect } from "react";
import { Route, Switch, useLocation } from "wouter";

import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import ErrorBoundary from "./components/ErrorBoundary";
import DashboardLayout from "./components/DashboardLayout";
import { ThemeProvider, useTheme } from "./contexts/ThemeContext";
import {
  getBackgroundScopeAliases,
  getBackgroundScopeForPath,
  isDecorationScopeActive,
  resolveBackgroundBlurForScope,
  resolveBackgroundImageForScope,
  resolveBackgroundOverlayOpacityForScope,
  resolveBackgroundPositionForScope,
  resolveBackgroundPresentationModeForScope,
} from "./lib/appearanceScopes";

const UserOperatingTour = lazy(() => import("@/components/UserOperatingTour"));
const NotFound = lazy(() => import("@/pages/NotFound"));
const Home = lazy(() => import("@/pages/Home"));
const Dashboard = lazy(() => import("@/pages/Dashboard"));
const Profile = lazy(() => import("@/pages/Profile"));
const Documents = lazy(() => import("@/pages/Documents"));
const NewRequest = lazy(() => import("@/pages/NewRequest"));
const Requests = lazy(() => import("@/pages/Requests"));
const RequestDetail = lazy(() => import("@/pages/RequestDetail"));
const EditRequest = lazy(() => import("@/pages/EditRequest"));
const Admin = lazy(() => import("@/pages/Admin"));
const FAQ = lazy(() => import("@/pages/FAQ"));
const ReservationSalle = lazy(() => import("@/pages/ReservationSalle"));
const Login = lazy(() => import("@/pages/Login"));
const DemandeMaterielEvenementiel = lazy(() => import("@/pages/DemandeMaterielEvenementiel"));
const AssociationDirectoryPortal = lazy(() => import("@/pages/AssociationDirectoryPortal"));
const AssociationInvitation = lazy(() => import("@/pages/AssociationInvitation"));
const AssociationMapPublic = lazy(() => import("@/pages/AssociationMapPublic"));
const AssociationPublicProfile = lazy(() => import("@/pages/AssociationPublicProfile"));
const MaterialReturnUpload = lazy(() => import("@/pages/MaterialReturnUpload"));
const MaterialReturnFinalPdfView = lazy(() => import("@/pages/MaterialReturnFinalPdfView"));
const MaterialConventionDownload = lazy(() => import("@/pages/MaterialConventionDownload"));
const SalleWorkflowDocumentDownload = lazy(() => import("@/pages/SalleWorkflowDocumentDownload"));
const StatsReportArchiveView = lazy(() => import("@/pages/StatsReportArchiveView"));
const TerrainMissions = lazy(() => import("@/pages/TerrainMissions"));
const PrivacyPolicy = lazy(() => import("@/pages/PrivacyPolicy"));
const LegalNotice = lazy(() => import("@/pages/LegalNotice"));
const CookiesPolicy = lazy(() => import("@/pages/CookiesPolicy"));
const TermsOfService = lazy(() => import("@/pages/TermsOfService"));

function PageLoader({ compact = false }: { compact?: boolean }) {
  return (
    <div className={compact ? "flex min-h-[40vh] items-center justify-center p-6" : "flex min-h-screen items-center justify-center p-6"}>
      <div className="flex flex-col items-center gap-3 text-center">
        <div className="h-10 w-10 animate-spin rounded-full border-4 border-primary/20 border-t-primary" />
        <p className="text-sm text-muted-foreground">Chargement de l’interface...</p>
      </div>
    </div>
  );
}

function withRouteSuspense<T extends object>(Component: ComponentType<T>) {
  return function SuspendedRoute(props: T) {
    return (
      <Suspense fallback={<PageLoader />}>
        <Component {...props} />
      </Suspense>
    );
  };
}

function withDashboardLayout<T extends object>(Component: ComponentType<T>) {
  return function DashboardRoute(props: T) {
    return (
      <DashboardLayout>
        <Suspense fallback={<PageLoader compact />}>
          <Component {...props} />
        </Suspense>
      </DashboardLayout>
    );
  };
}

const HomeRoute = withRouteSuspense(Home);
const LoginRoute = withRouteSuspense(Login);
const InvitationRoute = withRouteSuspense(AssociationInvitation);
const MaterialReturnFinalPdfRoute = withRouteSuspense(MaterialReturnFinalPdfView);
const MaterialReturnUploadRoute = withRouteSuspense(MaterialReturnUpload);
const TerrainMissionsRoute = withRouteSuspense(TerrainMissions);
const AssociationDirectoryRoute = withRouteSuspense(AssociationDirectoryPortal);
const AssociationMapRoute = withRouteSuspense(AssociationMapPublic);
const AssociationPublicProfileRoute = withRouteSuspense(AssociationPublicProfile);
const DashboardHomeRoute = withRouteSuspense(Dashboard);
const DashboardProfileRoute = withDashboardLayout(Profile);
const DashboardDocumentsRoute = withDashboardLayout(Documents);
const DashboardNewRequestRoute = withDashboardLayout(NewRequest);
const DashboardReservationSalleRoute = withDashboardLayout(ReservationSalle);
const DashboardMaterialRoute = withDashboardLayout(DemandeMaterielEvenementiel);
const DashboardDirectoryRoute = withDashboardLayout(AssociationDirectoryPortal);
const DashboardRequestsRoute = withDashboardLayout(Requests);
const DashboardRequestDetailRoute = withDashboardLayout(RequestDetail);
const DashboardEditRequestRoute = withDashboardLayout(EditRequest);
const MaterialConventionRoute = withRouteSuspense(MaterialConventionDownload);
const SalleWorkflowDocumentRoute = withRouteSuspense(SalleWorkflowDocumentDownload);
const StatsReportArchiveRoute = withRouteSuspense(StatsReportArchiveView);
const AdminRoute = withDashboardLayout(Admin);
const FAQRoute = withRouteSuspense(FAQ);
const PrivacyPolicyRoute = withRouteSuspense(PrivacyPolicy);
const LegalNoticeRoute = withRouteSuspense(LegalNotice);
const CookiesPolicyRoute = withRouteSuspense(CookiesPolicy);
const TermsOfServiceRoute = withRouteSuspense(TermsOfService);
const NotFoundRoute = withRouteSuspense(NotFound);

function AppearanceDecorationLayer() {
  const [location] = useLocation();
  const { appearance } = useTheme();
  const scope = getBackgroundScopeForPath(location);
  const decorativeElements = (appearance.decorativeElements || []).filter(
    (entry) => entry.imageUrl && entry.layer === "background" && isDecorationScopeActive(entry.scope, scope),
  );

  if (!appearance.backgroundEnabled || decorativeElements.length === 0) {
    return null;
  }

  return (
    <div className="portal-decorations-layer" aria-hidden="true">
      {decorativeElements.map((entry) => (
        <img
          key={entry.id}
          src={entry.imageUrl}
          alt=""
          className="portal-decoration-item"
          style={{
            width: `${entry.widthPercent}%`,
            top: `${entry.topPercent}%`,
            left: `${entry.leftPercent}%`,
            opacity: entry.opacity / 100,
            filter: `blur(${entry.blurRadius}px)`,
          }}
        />
      ))}
    </div>
  );
}

function AppearanceScopeBridge() {
  const [location] = useLocation();
  const { appearance, resolvedTheme } = useTheme();

  useEffect(() => {
    const root = document.documentElement;
    const scope = getBackgroundScopeForPath(location);
    const resolvedBackgroundImage = resolveBackgroundImageForScope(scope, appearance);
    const resolvedBackgroundOverlayOpacity = resolveBackgroundOverlayOpacityForScope(scope, appearance);
    const resolvedBackgroundPosition = resolveBackgroundPositionForScope(scope, appearance);
    const resolvedBackgroundBlur = resolveBackgroundBlurForScope(scope, appearance);
    const resolvedBackgroundPresentationMode = resolveBackgroundPresentationModeForScope(scope, appearance);
    const applies =
      appearance.backgroundEnabled &&
      getBackgroundScopeAliases(scope).some((candidate) =>
        appearance.backgroundTargets.includes(candidate as typeof appearance.backgroundTargets[number])
      );
    root.style.setProperty(
      "--portal-background-image",
      applies && resolvedBackgroundImage ? `url("${resolvedBackgroundImage}")` : "none"
    );
    root.style.setProperty(
      "--portal-background-overlay",
      resolvedTheme === "dark"
        ? `rgba(6, 12, 18, ${resolvedBackgroundOverlayOpacity / 100})`
        : `rgba(247, 250, 252, ${resolvedBackgroundOverlayOpacity / 100})`
    );
    root.style.setProperty("--portal-background-position", resolvedBackgroundPosition);
    root.style.setProperty("--portal-background-blur", `${resolvedBackgroundBlur}px`);
    root.style.setProperty("--portal-background-presentation-mode", resolvedBackgroundPresentationMode);
    root.style.setProperty(
      "--portal-background-center-overlay",
      resolvedBackgroundPresentationMode === "edge_frame"
        ? (resolvedTheme === "dark" ? "rgba(6, 12, 18, 0.84)" : "rgba(255, 255, 255, 0.88)")
        : (resolvedTheme === "dark" ? "rgba(6, 12, 18, 0.16)" : "rgba(255, 255, 255, 0.12)")
    );
    root.style.setProperty(
      "--portal-background-edge-strength",
      resolvedBackgroundPresentationMode === "edge_frame"
        ? (resolvedTheme === "dark" ? "0.98" : "0.94")
        : (resolvedTheme === "dark" ? "0.28" : "0.22")
    );
    root.dataset.portalBackgroundScope = scope;
    root.dataset.portalBackgroundActive = applies ? "true" : "false";
    root.dataset.portalBackgroundPresentationMode = resolvedBackgroundPresentationMode;
  }, [
    appearance.backgroundEnabled,
    appearance.backgroundImageUrl,
    appearance.backgroundMode,
    appearance.backgroundOverlayOpacity,
    appearance.backgroundBlurRadius,
    appearance.backgroundPresentationMode,
    appearance.backgroundTargetImageUrls,
    appearance.backgroundTargetBlurRadii,
    appearance.backgroundTargetOverlayOpacities,
    appearance.backgroundTargetPositions,
    appearance.backgroundTargetPresentationModes,
    appearance.backgroundTargets,
    location,
    resolvedTheme,
  ]);

  return null;
}

function Router() {
  return (
    <Switch>
      <Route path="/" component={HomeRoute} />
      <Route path="/login" component={LoginRoute} />
      <Route path="/invite/:token" component={InvitationRoute} />
      <Route path="/materiel/restitution/final-pdf" component={MaterialReturnFinalPdfRoute} />
      <Route path="/materiel/restitution/:token" component={MaterialReturnUploadRoute} />
      <Route path="/terrain" component={TerrainMissionsRoute} />
      <Route path="/associations" component={AssociationDirectoryRoute} />
      <Route path="/associations/carte" component={AssociationMapRoute} />
      <Route path="/associations/:id" component={AssociationPublicProfileRoute} />
      <Route path="/dashboard" component={DashboardHomeRoute} />
      <Route path="/dashboard/profile" component={DashboardProfileRoute} />
      <Route path="/dashboard/documents" component={DashboardDocumentsRoute} />
      <Route path="/dashboard/requests/new" component={DashboardNewRequestRoute} />
      <Route path="/dashboard/reservation-salle" component={DashboardReservationSalleRoute} />
      <Route path="/dashboard/materiel-evenementiel" component={DashboardMaterialRoute} />
      <Route path="/dashboard/associations" component={DashboardDirectoryRoute} />
      <Route path="/dashboard/requests/:id/edit" component={DashboardEditRequestRoute} />
      <Route path="/dashboard/requests/:id/material-convention" component={MaterialConventionRoute} />
      <Route path="/dashboard/requests/:id/salle-document/:documentType" component={SalleWorkflowDocumentRoute} />
      <Route path="/admin/stats-report" component={StatsReportArchiveRoute} />
      <Route path="/dashboard/requests/:id" component={DashboardRequestDetailRoute} />
      <Route path="/dashboard/requests" component={DashboardRequestsRoute} />
      <Route path="/admin" component={AdminRoute} />
      <Route path="/faq" component={FAQRoute} />
      <Route path="/confidentialite" component={PrivacyPolicyRoute} />
      <Route path="/mentions-legales" component={LegalNoticeRoute} />
      <Route path="/cookies" component={CookiesPolicyRoute} />
      <Route path="/cgu" component={TermsOfServiceRoute} />
      <Route path="/404" component={NotFoundRoute} />
      <Route component={NotFoundRoute} />
    </Switch>
  );
}

function App() {
  return (
    <ErrorBoundary>
      <ThemeProvider defaultTheme="light">
        <TooltipProvider>
          <Toaster />
          <AppearanceScopeBridge />
          <AppearanceDecorationLayer />
          <Router />
          <Suspense fallback={null}>
            <UserOperatingTour />
          </Suspense>
        </TooltipProvider>
      </ThemeProvider>
    </ErrorBoundary>
  );
}

export default App;
