import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import { routeTree } from "./routeTree.gen";
import { env } from "./lib/env";
import { api } from "./lib/api";
import { authStore } from "./lib/auth";
import type { AuthSession } from "@rubis/shared";

import "./styles/app.css";

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 30_000,
      gcTime: 5 * 60_000,
      retry: 1,
      refetchOnWindowFocus: false,
    },
    mutations: {
      retry: 0,
    },
  },
});

const router = createRouter({
  routeTree,
  context: { queryClient },
  defaultPreload: "intent",
  defaultPreloadStaleTime: 0,
});

declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}

async function enableMocking(): Promise<void> {
  // import.meta.env.DEV est un booléen statique : Vite tree-shake la branche
  // entière (et le chunk MSW avec) quand on build en mode production.
  if (!import.meta.env.DEV || !env.VITE_USE_MOCKS) return;
  const { worker } = await import("./mocks/browser");
  await worker.start({
    onUnhandledRequest: "bypass",
    serviceWorker: {
      url: "/mockServiceWorker.js",
    },
  });
  // eslint-disable-next-line no-console
  console.info(
    "%c[MSW]%c Mocks API actifs — VITE_USE_MOCKS=true",
    "background:#9F1239;color:white;padding:2px 6px;border-radius:3px;font-weight:600",
    "color:#8A7F76",
  );
}

/**
 * Tente de récupérer la session à partir du refresh token (cf. ADR-017).
 * Si le serveur (ou MSW) confirme une session valide → on rehydrate l'authStore
 * AVANT le 1er render, ce qui évite le flash redirect /login pour les users
 * déjà connectés.
 *
 * En mode dev avec MSW, la "session" persistée est en localStorage (cf.
 * mocks/sessionStore). En prod réel, c'est le cookie httpOnly côté Adonis.
 */
async function bootstrapSession(): Promise<void> {
  try {
    const session = await api.post<AuthSession>(
      "/api/v1/auth/refresh",
      undefined,
      { anonymous: true },
    );
    authStore.setSession(session.accessToken, session.user);
  } catch {
    // Pas de session valide → on reste anonyme. _app guard redirigera vers /login.
  }
}

function render(): void {
  const rootEl = document.getElementById("root");
  if (!rootEl) throw new Error("#root introuvable dans index.html");
  createRoot(rootEl).render(
    <StrictMode>
      <QueryClientProvider client={queryClient}>
        <RouterProvider router={router} />
      </QueryClientProvider>
    </StrictMode>,
  );
}

async function init(): Promise<void> {
  await enableMocking();
  await bootstrapSession();
  render();
}

void init();
