import { createRoot } from "react-dom/client";
import "./index.css";
import { bootTheme } from "./lib/themeApp";
import { installDataTipPortal } from "./lib/dataTipPortal";
import { installAntiClone } from "./lib/antiClone";
import { installSupabaseUserHeader } from "./lib/installSupabaseUserHeader";


const SB_AUTH_KEY_PREFIX = "sb-";
const SB_AUTH_KEY_SUFFIX = "-auth-token";


function installSessionScopedSupabaseAuthStorage() {
  if (typeof window === "undefined") return;
  const proto = Storage.prototype as Storage & { __myapotekSessionScopedSbAuth?: boolean };
  if (proto.__myapotekSessionScopedSbAuth) return;

  const isSbAuthKey = (key: unknown) =>
    typeof key === "string" && key.startsWith(SB_AUTH_KEY_PREFIX) && key.endsWith(SB_AUTH_KEY_SUFFIX);
  const originalGetItem = Storage.prototype.getItem;
  const originalSetItem = Storage.prototype.setItem;
  const originalRemoveItem = Storage.prototype.removeItem;

  Storage.prototype.getItem = function (key: string) {
    if (this === window.localStorage && isSbAuthKey(key)) {
      return originalGetItem.call(window.sessionStorage, key) ?? originalGetItem.call(window.localStorage, key);
    }
    return originalGetItem.call(this, key);
  };

  Storage.prototype.setItem = function (key: string, value: string) {
    if (this === window.localStorage && isSbAuthKey(key)) {
      originalSetItem.call(window.sessionStorage, key, value);
      originalRemoveItem.call(window.localStorage, key);
      return;
    }
    return originalSetItem.call(this, key, value);
  };

  Storage.prototype.removeItem = function (key: string) {
    if (this === window.localStorage && isSbAuthKey(key)) {
      const hadLegacyLocalValue = originalGetItem.call(window.localStorage, key) !== null;
      originalRemoveItem.call(window.localStorage, key);
      if (!hadLegacyLocalValue) {
        originalRemoveItem.call(window.sessionStorage, key);
      }
      return;
    }
    return originalRemoveItem.call(this, key);
  };

  proto.__myapotekSessionScopedSbAuth = true;
}


function installSupabaseAuthLockBypass() {
  // HANYA pasang bypass saat berjalan di dalam iframe same-origin
  // (mis. Simulator HP di SetupSoMobile / BagikanPosMobile). Di tab utama
  // Web Locks Supabase WAJIB tetap aktif — locks itu yang men-serialize
  // panggilan refresh token. Tanpa locks, beberapa refresh paralel
  // (authKeepAlive interval + heartbeat tick + onAuthStateChange + query
  // bursts saat buka halaman berat) akan memakai refresh
  // token yang sama → server balas `refresh_token_not_found` →
  // heartbeat menganggap sesi mati → user dipaksa login ulang.
  let inIframe = false;
  try { inIframe = window.self !== window.top; } catch { inIframe = true; }
  if (!inIframe) return;
  const locks = (navigator as any)?.locks;
  if (!locks?.request || (locks as any).__myapotekAuthBypass) return;
  const originalRequest = locks.request.bind(locks);
  locks.request = (name: string, optionsOrCallback: any, maybeCallback?: any) => {
    const callback = typeof optionsOrCallback === "function" ? optionsOrCallback : maybeCallback;
    if (typeof name === "string" && name.startsWith("lock:sb-") && name.endsWith("-auth-token") && typeof callback === "function") {
      return Promise.resolve(callback({ name, mode: "exclusive" }));
    }
    return originalRequest(name, optionsOrCallback, maybeCallback);
  };
  (locks as any).__myapotekAuthBypass = true;
}

// Suppress benign "ResizeObserver loop completed with undelivered notifications" warnings.
// This is a known browser quirk fired by libraries (Radix, charts) and is not an actual error.
function installResizeObserverErrorSuppressor() {
  const RESIZE_MSG = "ResizeObserver loop";
  const onError = (e: ErrorEvent) => {
    if (e.message && e.message.includes(RESIZE_MSG)) {
      e.stopImmediatePropagation();
      e.preventDefault();
      // Hide red overlay (Vite/webpack dev overlays)
      const overlays = document.querySelectorAll<HTMLElement>(
        "vite-error-overlay, #webpack-dev-server-client-overlay, .__vite-error-overlay__"
      );
      overlays.forEach((o) => (o.style.display = "none"));
    }
  };
  const onRejection = (e: PromiseRejectionEvent) => {
    const msg = String((e.reason as any)?.message || e.reason || "");
    if (msg.includes(RESIZE_MSG)) {
      e.stopImmediatePropagation();
      e.preventDefault();
    }
  };
  window.addEventListener("error", onError, true);
  window.addEventListener("unhandledrejection", onRejection, true);

  const origConsoleError = console.error.bind(console);
  console.error = (...args: any[]) => {
    if (args.some((a) => typeof a === "string" && a.includes(RESIZE_MSG))) return;
    origConsoleError(...args);
  };
}

installSessionScopedSupabaseAuthStorage();
installSupabaseUserHeader();
bootTheme();
installDataTipPortal();
if (window.location.pathname !== "/so-mobile") {
  installSupabaseAuthLockBypass();
}
installResizeObserverErrorSuppressor();
installAntiClone();

// Bersihkan tanda reload internal segera setelah boot — supaya pagehide berikutnya
// (yang benar2 user menutup browser) tetap menjalankan logout_session.
try { sessionStorage.removeItem("__internal_reload__"); } catch {}


// Guard: never register SW in iframe or preview hosts
const isInIframe = (() => {
  try {
    return window.self !== window.top;
  } catch (e) {
    return true;
  }
})();

const isPreviewHost =
  window.location.hostname.includes("id-preview--") ||
  window.location.hostname.includes("lovableproject.com");

if (isPreviewHost || isInIframe) {
  navigator.serviceWorker?.getRegistrations().then((registrations) => {
    registrations.forEach((r) => r.unregister());
  });
}

async function bootApp() {
  if (window.location.pathname === "/so-mobile") {
    try {
      const regs = await navigator.serviceWorker?.getRegistrations?.();
      await Promise.all((regs || []).map((r) => r.unregister()));
    } catch { /* ignore */ }
    const { default: SoMobileEntry } = await import("./SoMobileEntry.tsx");
    createRoot(document.getElementById("root")!).render(<SoMobileEntry />);
    return;
  }

  if (window.location.pathname !== "/so-mobile") {
    // PENTING: inherit sesi dari parent iframe HARUS sebelum modul apa pun
    // yang meng-import supabase client. SO Mobile publik melewati seluruh auth.
    await import("./lib/inheritIframeSession");
    const { installAuthKeepAlive } = await import("./lib/authKeepAlive");
    installAuthKeepAlive();
    const { installPwaRegistration } = await import("./lib/pwaRegistration");
    installPwaRegistration();
  }
  const { default: App } = await import("./App.tsx");
  createRoot(document.getElementById("root")!).render(<App />);
}

// Auto-reload sekali kalau dynamic import gagal (mis. dev server restart,
// chunk lama dihapus setelah deploy baru). Tanpa ini layar tetap putih.
const CHUNK_RELOAD_KEY = "__chunk_reload_attempted__";
function isChunkLoadError(reason: any) {
  const msg = String(reason?.message || reason || "");
  return (
    msg.includes("Failed to fetch dynamically imported module") ||
    msg.includes("Importing a module script failed") ||
    msg.includes("error loading dynamically imported module")
  );
}
window.addEventListener("unhandledrejection", (e) => {
  if (!isChunkLoadError(e.reason)) return;
  try {
    if (sessionStorage.getItem(CHUNK_RELOAD_KEY)) return;
    sessionStorage.setItem(CHUNK_RELOAD_KEY, "1");
  } catch {}
  window.location.reload();
});
window.addEventListener("load", () => {
  try { sessionStorage.removeItem(CHUNK_RELOAD_KEY); } catch {}
});

bootApp().catch((err) => {
  if (isChunkLoadError(err)) {
    try {
      if (!sessionStorage.getItem(CHUNK_RELOAD_KEY)) {
        sessionStorage.setItem(CHUNK_RELOAD_KEY, "1");
        window.location.reload();
        return;
      }
    } catch {}
  }
  console.error("bootApp failed:", err);
});
