import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App.tsx";
import "./index.css";
import { APP_VERSION, fetchRemoteVersion, getStoredVersion, setStoredVersion } from "./lib/version";
import { ErrorBoundary } from "./components/ErrorBoundary";
// Phase 6 (Option A — entry-chunk slimming, 2026-04-30):
// notificationSounds (113 LOC + supabase ringtone-pref query) and
// web-vitals-reporter (322 LOC) were being parsed in the entry chunk for
// EVERY visitor — including marketing /, /use-cases, /industries — even
// though only logged-in app users on /entity, /tradrrapp, /field-sales,
// /saasapp need the audio infra and only RUM contexts need the reporter.
// Both are now lazy-imported behind the existing isAppRoute / idle gate.

const isPreviewSession = typeof window !== "undefined" && window.location.search.includes("__lovable_token=");

// Version check - keep lightweight and non-blocking
async function checkForUpdates() {
  try {
    const remoteVersion = await fetchRemoteVersion();
    const storedVersion = getStoredVersion();

    console.log("[Update] Remote:", remoteVersion, "| Stored:", storedVersion, "| Code:", APP_VERSION);

    if (storedVersion !== APP_VERSION) {
      setStoredVersion(APP_VERSION);
    }

    if (remoteVersion && remoteVersion !== APP_VERSION) {
      console.log("[Update] Version mismatch detected. Prompting refresh.");
      window.dispatchEvent(new CustomEvent("app-version-mismatch", {
        detail: { remoteVersion, appVersion: APP_VERSION },
      }));
      return;
    }

    if (remoteVersion && remoteVersion !== storedVersion) {
      setStoredVersion(remoteVersion);
      console.log("[Update] Stored new version:", remoteVersion);
    }
  } catch (e) {
    console.log("[Update] Check failed:", e);
  }
}

async function recoverPreviewIfNeeded() {
  if (!isPreviewSession || !("serviceWorker" in navigator)) return;

  try {
    const regs = await navigator.serviceWorker.getRegistrations();
    await Promise.all(regs.map((r) => r.unregister()));

    if ("caches" in window) {
      const keys = await caches.keys();
      await Promise.all(keys.map((k) => caches.delete(k)));
    }

    console.log("[Preview] Cleared stale service workers/caches");
  } catch (e) {
    console.log("[Preview] Recovery skipped:", e);
  }
}

// ---- Audio unlock on first user gesture ----
let audioUnlocked = false;

function unlockAudioOnInteraction() {
  if (audioUnlocked) return;
  const handler = () => {
    if (audioUnlocked) return;
    // Play a silent audio element to satisfy autoplay policy
    const silent = new Audio('/notification.mp3');
    silent.volume = 0;
    silent.play().then(() => {
      silent.pause();
      audioUnlocked = true;
      console.log('[Audio] Unlocked via user gesture');
    }).catch(() => {});
    document.removeEventListener('click', handler);
    document.removeEventListener('touchstart', handler);
  };
  document.addEventListener('click', handler);
  document.addEventListener('touchstart', handler);
}

// ---- Service Worker push sound listener ----
function setupPushSoundListener() {
  if (!('serviceWorker' in navigator)) return;

  navigator.serviceWorker.addEventListener('message', (event) => {
    if (event.data?.type !== 'PUSH_RECEIVED') return;
    // Play custom ringtone only when app is visible (background playback is blocked by browsers).
    // When hidden/closed, the SW's showNotification with silent:false handles the OS sound.
    if (!document.hidden) {
      // Lazy: notificationSounds chunk only loads when a push actually fires.
      void import("./utils/notificationSounds").then((m) => m.playNotificationSound());
    }
  });
}

// Skip SW registration in preview sessions to avoid stale-cache hangs
if (!isPreviewSession && 'serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js', { scope: '/' })
    .then((reg) => {
      console.log('[SW] Registered with scope:', reg.scope);
    })
    .catch((err) => console.log('[SW] Registration failed:', err));

  // Diagnostic: confirm SW reaches "ready" state (controls push subscription readiness)
  navigator.serviceWorker.ready
    .then((reg) => console.log('[SW] Service worker ready. Active:', !!reg.active, 'Scope:', reg.scope))
    .catch((err) => console.log('[SW] Ready check failed:', err));
}

void recoverPreviewIfNeeded();

// Only set up notification audio infrastructure on app routes (not public website)
const isAppRoute = /^\/(entity|tradrrapp|field-sales|saasapp|login|signup)/.test(window.location.pathname);
if (isAppRoute) {
  unlockAudioOnInteraction();
  setupPushSoundListener();
  // Lazy: notificationSounds chunk stays out of the marketing entry chunk.
  void import("./utils/notificationSounds").then((m) => m.syncAdminRingtone());
}

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

if (!isPreviewSession) {
  // Wait for `load` so version + telemetry never compete with LCP rendering.
  const startBackgroundTasks = () => {
    const idle = (window as any).requestIdleCallback as
      | ((cb: () => void, opts?: { timeout: number }) => void)
      | undefined;
    const run = () => {
      setTimeout(checkForUpdates, 1500);
      // Lazy: web-vitals-reporter (322 LOC) only loads at idle, after LCP.
      void import("./lib/web-vitals-reporter").then((m) => m.initWebVitalsReporter());
    };
    if (idle) idle(run, { timeout: 5000 });
    else setTimeout(run, 2000);
  };
  if (document.readyState === "complete") {
    startBackgroundTasks();
  } else {
    window.addEventListener("load", startBackgroundTasks, { once: true });
  }
}
