import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { initGlobalErrorHandlers } from "./lib/errorLogger";
import { initTrackingLoader } from "./lib/trackingLoader";
import { initServiceWorker } from "./lib/registerSW";
import { isInIframe as detectIframe, isLovablePreviewHost } from "./lib/runtimeEnv";

// Capture window.onerror + unhandledrejection globally
initGlobalErrorHandlers();

// Initialise consent-gated tracking loader. No tags are registered by
// default — see src/lib/trackingLoader.ts for how to add GA/Meta/etc.
initTrackingLoader();

const inIframe = detectIframe();
const inPreview = isLovablePreviewHost();

// Normalize static-hosting entry paths like /index or /index.html -> /
if (window.location.pathname === '/index' || window.location.pathname === '/index.html') {
  window.history.replaceState({}, '', `/${window.location.search}${window.location.hash}`);
}

// Pre-mount redirect: authenticated users with active access must never see
// the landing — not even for a frame. This runs synchronously before React
// mounts by reading the Supabase auth token straight from localStorage plus
// a small "has access" flag persisted by useAuth after the last check.
//
// Vite SPA on Lovable hosting has no server middleware, so this is the
// earliest safe hook: the browser has already loaded /index.html, but the
// React tree hasn't rendered yet.
(() => {
  try {
    const path = window.location.pathname;
    if (path !== '/' && path !== '/index' && path !== '/index.html') return;

    const hasAccess = localStorage.getItem('tdf_has_access') === '1';
    if (!hasAccess) return;

    // Locate the Supabase session token key. The client writes it as
    // `sb-<project-ref>-auth-token`; scan defensively in case the ref changes.
    let session: unknown = null;
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (!key || !key.startsWith('sb-') || !key.endsWith('-auth-token')) continue;
      const raw = localStorage.getItem(key);
      if (!raw) continue;
      try { session = JSON.parse(raw); break; } catch { /* ignore */ }
    }
    if (!session || typeof session !== 'object') return;

    const s = session as { access_token?: string; expires_at?: number };
    if (!s.access_token) return;
    // expires_at is unix seconds. Treat missing as valid (Supabase refresh handles it).
    if (typeof s.expires_at === 'number' && s.expires_at * 1000 < Date.now()) return;

    // If an OAuth flow saved a same-origin "next" path, honor it once.
    let target = '/dashboard';
    try {
      const next = sessionStorage.getItem('tdf_oauth_next');
      if (next && next.startsWith('/') && !next.startsWith('//')) {
        target = next;
      }
      sessionStorage.removeItem('tdf_oauth_next');
    } catch { /* ignore */ }
    window.history.replaceState({}, '', `${target}${window.location.search}${window.location.hash}`);
  } catch {
    /* storage blocked — fall through to normal render */
  }
})();

// Prevent service worker from interfering in preview/iframe contexts.
// Production / installed PWA: register via our wrapper so the in-app
// "Обновить" toast can skip-waiting + reload deterministically.
if (inPreview || inIframe) {
  navigator.serviceWorker?.getRegistrations().then((regs) => {
    regs.forEach((r) => r.unregister());
  });
} else {
  initServiceWorker();
}


// Auto-recover from stale chunk references after a deploy.
// Vite throws `vite:preloadError` when a dynamic import 404s (typical after
// a deploy renamed hashed chunks). We force ONE hard reload so the browser
// fetches the new index.html + manifest. A session flag prevents a loop.
window.addEventListener('vite:preloadError', (e) => {
  try {
    e.preventDefault();
    if (sessionStorage.getItem('__chunk_reloaded')) return;
    sessionStorage.setItem('__chunk_reloaded', '1');
    window.location.reload();
  } catch {
    /* storage unavailable — let Vite handle it */
  }
});
// Clear the guard once the app loads successfully so future preload errors
// (much later in the session) can also self-heal.
window.addEventListener('load', () => {
  setTimeout(() => {
    try { sessionStorage.removeItem('__chunk_reloaded'); } catch { /* ignore */ }
  }, 5000);
});

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