import { createRoot } from "react-dom/client";
import "./assets/styles/index.css";
// Font packages imported from JS (explicit /index.css paths) so Vite's
// asset pipeline resolves the internal url(./files/...woff2) refs and
// emits hashed font binaries to dist/assets.
import "@fontsource-variable/geist/index.css";
import "@fontsource-variable/geist-mono/index.css";
import "@fontsource-variable/inter/index.css";
import "@fontsource-variable/lexend/index.css";
import "@fontsource/poppins/index.css";
import "@fontsource/montserrat/index.css";
import "./libs/i18n.ts";

import { routeTree } from "./routeTree.gen";
import {
  QueryCache,
  QueryClient,
  QueryClientProvider,
} from "@tanstack/react-query";
import { AxiosError } from "axios";
import { handleServerError } from "./libs/handle-server-error.ts";
import { toast } from "sonner";
import { createRouter } from "@tanstack/react-router";
import { ThemeProvider } from "./context/theme-provider.tsx";
import { FontProvider } from "./context/font-provider.tsx";
import { LoadingProvider } from "./context/loading-provider.tsx";
import { AuthProvider } from "./context/auth-provider.tsx";
import { TimezoneProvider } from "./context/timezone-provider.tsx";
import App from "./App.tsx";
import { stopBlinkTabTitle } from "./libs/utils.ts";

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retry: (failureCount, error) => {
        if (import.meta.env.DEV) console.log({ failureCount, error });
        if (failureCount >= 0 && import.meta.env.DEV) return false;
        if (failureCount > 3 && import.meta.env.PROD) return false;

        return !(
          error instanceof AxiosError &&
          [401, 403].includes(error.response?.status ?? 0)
        );
      },
      staleTime: 5 * 60 * 1000,
      gcTime: 30 * 60 * 1000,
      refetchOnReconnect: true,
      refetchOnWindowFocus: false,
    },
    mutations: {
      onError: (error) => {
        handleServerError(error);

        if (error instanceof AxiosError) {
          if (error.response?.status === 304) {
            toast.error("Content not modified!");
          }
        }
      },
    },
  },
  queryCache: new QueryCache({
    onError: (error) => {
      window.dispatchEvent(new CustomEvent("query-error", { detail: error }));
    },
  }),
});

// Create a new router instance
const router = createRouter({
  routeTree,
  context: { queryClient, isAuth: undefined, role: undefined },
  defaultPreload: "intent",
});

// Register the router instance for type safety
declare module "@tanstack/react-router" {
  interface Register {
    router: typeof router;
  }
}
async function enableMocking() {
  // Chỉ bật mock nếu là môi trường dev và bạn muốn bật nó
  if (
    import.meta.env.MODE !== "development" ||
    import.meta.env.VITE_ENABLE_MOCK !== "true"
  ) {
    return;
  }

  const { worker } = await import("./apis/mocks/browser");
  return worker.start({
    onUnhandledRequest: "bypass", // Không cảnh báo nếu gọi các API thật khác
  });
}
enableMocking().then(() => {
  return createRoot(document.getElementById("root")!).render(
    <QueryClientProvider client={queryClient}>
      <ThemeProvider>
        <FontProvider>
          <LoadingProvider>
            <TimezoneProvider>
              <AuthProvider>
                <App router={router} />
              </AuthProvider>
            </TimezoneProvider>
          </LoadingProvider>
        </FontProvider>
      </ThemeProvider>
    </QueryClientProvider>,
  );
});
if (typeof window !== "undefined") {
  const stopBlink = () => {
    try {
      stopBlinkTabTitle();
    } catch (e) {
      console.error(e);
    }
  };

  window.addEventListener("focus", stopBlink);
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") stopBlink();
  });
  // fallback interactions if focus isn't triggered
  document.addEventListener("click", stopBlink);
  document.addEventListener("keydown", stopBlink);
  document.addEventListener("pointerdown", stopBlink);

  // Auto-reload khi chunk lazy-load fail sau deploy mới (shell cũ ref hash đã bị xoá).
  // Một lần / session để tránh reload-loop nếu lỗi do nguyên nhân khác.
  const RELOAD_FLAG = "__cdk_chunk_reloaded__";
  const isStaleChunkError = (msg?: string) => {
    if (!msg) return false;
    return (
      msg.includes("Failed to fetch dynamically imported module") ||
      msg.includes("Importing a module script failed") ||
      msg.includes("error loading dynamically imported module") ||
      /ChunkLoadError/i.test(msg)
    );
  };
  const reloadOnce = () => {
    if (sessionStorage.getItem(RELOAD_FLAG)) return;
    sessionStorage.setItem(RELOAD_FLAG, "1");
    window.location.reload();
  };
  window.addEventListener("error", (e) => {
    if (isStaleChunkError(e.message)) reloadOnce();
  });
  window.addEventListener("unhandledrejection", (e) => {
    const reason = e.reason;
    const msg =
      typeof reason === "string"
        ? reason
        : reason instanceof Error
          ? reason.message
          : String(reason ?? "");
    if (isStaleChunkError(msg)) reloadOnce();
  });
}
