import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import "./i18n";
import { initVersionSentinel } from "./lib/versionSentinel";

// =========================================================================
// CACHE BUSTING AGRESIVO (PWA NetworkFirst, sin polling, sin timers)
// =========================================================================
//
// Estrategia:
//  - El Service Worker (Workbox) usa NetworkFirst para JS/CSS/HTML, así
//    cualquier deploy nuevo se descarga apenas hay red.
//  - En cada `visibilitychange` -> visible y en cada `focus`, llamamos a
//    `registration.update()` (evento PASIVO, no es timer). Esto fuerza al
//    navegador a chequear si hay un SW nuevo cuando el usuario vuelve a
//    abrir la PWA desde la multitarea.
//  - Cuando el nuevo SW toma control (`controllerchange`), recargamos UNA
//    sola vez para entregar la versión nueva al instante.
if (typeof window !== "undefined" && "serviceWorker" in navigator) {
  const RELOAD_FLAG = "apartalux_sw_reload_ts";
  let refreshing = false;

  navigator.serviceWorker.addEventListener("controllerchange", () => {
    if (refreshing) return;
    try {
      const last = Number(sessionStorage.getItem(RELOAD_FLAG) || "0");
      if (Date.now() - last < 10_000) return;
      sessionStorage.setItem(RELOAD_FLAG, String(Date.now()));
    } catch {
      // ignore
    }
    refreshing = true;
    window.location.reload();
  });

  const checkForUpdates = () => {
    navigator.serviceWorker
      .getRegistrations()
      .then((regs) => regs.forEach((r) => r.update().catch(() => {})))
      .catch(() => {});
  };

  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") checkForUpdates();
  });
  window.addEventListener("focus", checkForUpdates);
  window.addEventListener("pageshow", (e) => {
    // bfcache restore (típico al volver a la PWA desde multitarea iOS/Android)
    if ((e as PageTransitionEvent).persisted) checkForUpdates();
  });
}

// 2) Interceptación de ChunkLoadError / vite:preloadError.
//    Cuando hay un nuevo deploy, los hashes de los chunks cambian. Si el usuario
//    tiene la pestaña abierta con una versión vieja en memoria y navega a un
//    componente lazy nuevo, Vite emite "vite:preloadError" o se rechaza la
//    promesa del import dinámico con "ChunkLoadError"/"Loading chunk ... failed".
//    Ante eso, limpiamos y recargamos UNA sola vez para traer código fresco.
if (typeof window !== "undefined") {
  const RELOAD_FLAG = "apartalux_chunk_reload_ts";

  const performHardReload = () => {
    try {
      // Evita loops: si ya recargamos hace menos de 10s, no insistas.
      const last = Number(sessionStorage.getItem(RELOAD_FLAG) || "0");
      if (Date.now() - last < 10_000) return;
      sessionStorage.setItem(RELOAD_FLAG, String(Date.now()));
    } catch {
      // ignore
    }

    try {
      // No usamos localStorage.clear() porque borraría sesión/tokens y preferencias.
      // Limpiamos sólo cachés del navegador relacionadas a assets.
      if ("caches" in window) {
        caches.keys().then((names) => Promise.all(names.map((n) => caches.delete(n)))).catch(() => {});
      }
    } catch {
      // ignore
    }

    window.location.reload();
  };

  // Vite dispara este evento cuando falla la precarga de un chunk lazy.
  window.addEventListener("vite:preloadError", (event) => {
    event.preventDefault?.();
    performHardReload();
  });

  // Fallback genérico para "Loading chunk X failed" / dynamic import error.
  const isChunkError = (msg: unknown) =>
    typeof msg === "string" &&
    (msg.includes("Failed to fetch dynamically imported module") ||
      msg.includes("Importing a module script failed") ||
      msg.includes("Loading chunk") ||
      msg.includes("ChunkLoadError"));

  window.addEventListener("error", (event) => {
    if (isChunkError(event.message) || isChunkError((event.error as Error)?.message)) {
      performHardReload();
    }
  });

  window.addEventListener("unhandledrejection", (event) => {
    const reason: any = event.reason;
    const msg = typeof reason === "string" ? reason : reason?.message;
    if (isChunkError(msg)) {
      performHardReload();
    }
  });
}

createRoot(document.getElementById("root")!).render(<App />);

// Centinela de versión: detecta nuevos deploys vía /version.json y recarga.
initVersionSentinel();

