// ✅ FIX: Prevent "removeChild" crash caused by third-party scripts/extensions
// modifying DOM nodes that React also manages (e.g. <head> via react-helmet-async).
// This is a well-known React issue: https://github.com/facebook/react/issues/11538
if (typeof Node !== 'undefined') {
  const origRemoveChild = Node.prototype.removeChild;
  Node.prototype.removeChild = function <T extends Node>(child: T): T {
    if (child.parentNode !== this) {
      console.warn('[DOM-FIX] Prevented removeChild crash — node was already moved/removed');
      return child;
    }
    return origRemoveChild.call(this, child) as T;
  };

  const origInsertBefore = Node.prototype.insertBefore;
  Node.prototype.insertBefore = function <T extends Node>(newNode: T, refNode: Node | null): T {
    if (refNode && refNode.parentNode !== this) {
      console.warn('[DOM-FIX] Prevented insertBefore crash — ref node was already moved/removed');
      return newNode;
    }
    return origInsertBefore.call(this, newNode, refNode) as T;
  };
}

import "./index.css";

const RUNTIME_RECOVERY_KEY = '__runtime_recovery_attempted_v3__';

declare global {
  interface Window {
    __setLoadingStatus?: (status: string, detail?: string) => void;
  }
}

let shouldSkipReactBoot = false;

const setLoadingStatus = (status: string, detail?: string) => {
  if (typeof window !== 'undefined') {
    window.__setLoadingStatus?.(status, detail);
  }
};

const isLovablePreview = (() => {
  if (typeof window === 'undefined') return false;
  try {
    const host = window.location.hostname;
    return host.includes('id-preview--') || host.includes('lovableproject.com') || host.includes('lovable.app') || window.self !== window.top;
  } catch {
    return true;
  }
})();

const cleanupPreviewServiceWorkers = async () => {
  if (!isLovablePreview || typeof navigator === 'undefined' || !('serviceWorker' in navigator)) return;
  try {
    setLoadingStatus('Preview SW-cache opruimen', 'Controle op oude service workers gestart');
    const registrations = await navigator.serviceWorker.getRegistrations();
    await Promise.all(registrations.map((registration) => registration.unregister()));
    if ('caches' in window) {
      const keys = await caches.keys();
      await Promise.all(keys.map((key) => caches.delete(key)));
    }
    setLoadingStatus('Preview SW-cache gecontroleerd', registrations.length ? `${registrations.length} service worker(s) verwijderd` : 'Retries/herstarts: geen oude service workers gevonden');
  } catch {
    setLoadingStatus('Preview SW-cache controle mislukt', 'Doorgaan zonder reload; app boot blijft actief');
  }
};

setLoadingStatus('main.tsx geladen', 'React bootstrap wordt voorbereid');
const previewCleanupPromise = cleanupPreviewServiceWorkers();

if (typeof window !== 'undefined') {
  const legacyReportPdfMatch = window.location.pathname.match(/^\/reports\/.*\.pdf$/i);
  if (legacyReportPdfMatch) {
    shouldSkipReactBoot = true;
    const url = new URL(window.location.href);
    url.pathname = '/en/sci-report';
    url.searchParams.set('v', '20260420');
    window.location.replace(`${url.pathname}?${url.searchParams.toString()}${url.hash}`);
  }

  const sciRouteMatch = window.location.pathname.match(/^\/(?:(?<lang>[a-z]{2})\/)?(?<slug>sci-report|green-ai-report|duurzaamheidsrapport)\/?$/i);

  if (!shouldSkipReactBoot && sciRouteMatch) {
    const lang = sciRouteMatch.groups?.lang || 'en';
    const targetPath = `/${lang}/sci-report`;
    const url = new URL(window.location.href);
    const needsCanonicalPath = url.pathname !== targetPath;
    const needsVersion = url.searchParams.get('v') !== '20260420b';

    if (needsCanonicalPath || needsVersion) {
      shouldSkipReactBoot = true;
      url.pathname = targetPath;
      url.searchParams.set('v', '20260420b');
      window.location.replace(`${url.pathname}?${url.searchParams.toString()}${url.hash}`);
    }
  }
}

// ✅ EMERGENCY SW CLEAR: Add ?clear-sw=1 to URL to force-clear service workers and caches
// Runs on mobile by default; forced on any device when chunk recovery is active
if (typeof window !== 'undefined') {
  const params = new URLSearchParams(window.location.search);
  const hasClearSw = params.has('clear-sw');
  const hasChunkRecover = params.has('chunk-recover');

  if (hasClearSw || hasChunkRecover) {
    const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
    const shouldForce = hasChunkRecover || isMobile;

    if (shouldForce) {
      shouldSkipReactBoot = true;
      console.log('[SW-CLEAR] Emergency service worker cleanup initiated...');

      // Unregister all service workers
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.getRegistrations().then(registrations => {
          registrations.forEach(reg => {
            reg.unregister();
            console.log('[SW-CLEAR] Unregistered:', reg.scope);
          });
        });
      }

      // Clear all caches
      if ('caches' in window) {
        caches.keys().then(keys => {
          keys.forEach(key => {
            caches.delete(key);
            console.log('[SW-CLEAR] Deleted cache:', key);
          });
        });
      }

      console.log('[SW-CLEAR] Done. Redirecting without query...');

      // Remove query string and reload
      setTimeout(() => {
        window.location.replace(window.location.pathname);
      }, 500);
    }
  }
}

// ✅ SILENT ONE-TIME iOS SW CLEANUP: Proactively clear historical SW/cache on iOS devices
// Only runs once per device, only on iOS, only if SWs exist, no reload required
if (typeof window !== 'undefined') {
  const isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent);
  const cleanupDone = (() => {
    try { return localStorage.getItem('ios_sw_cleanup_done') === '1'; } 
    catch { return true; } // If localStorage fails, skip cleanup
  })();
  
  if (isIOS && !cleanupDone && 'serviceWorker' in navigator) {
    navigator.serviceWorker.getRegistrations().then(registrations => {
      if (registrations.length > 0) {
        // Unregister all SWs
        registrations.forEach(reg => reg.unregister());
        // Clear all caches
        if ('caches' in window) {
          caches.keys().then(keys => keys.forEach(k => caches.delete(k)));
        }
      }
      // Mark as done regardless of whether there were SWs
      try { localStorage.setItem('ios_sw_cleanup_done', '1'); } catch { /* noop */ }
    }).catch(() => {
      // If SW check fails, mark as done to prevent retry loops
      try { localStorage.setItem('ios_sw_cleanup_done', '1'); } catch { /* noop */ }
    });
  }
}

// ✅ iOS CRASH DEBUGGING: Temporary error logging for production diagnosis
// Only active on iOS devices - logs uncaught errors to console for debugging
if (typeof window !== 'undefined') {
  const isIOS = /iPhone|iPad|iPod/.test(navigator.userAgent);
  if (isIOS) {
    window.onerror = (message, source, lineno, colno, error) => {
      console.error('[iOS-ERROR]', { message, source, lineno, colno, stack: error?.stack });
      return false; // Don't suppress the error
    };
    window.onunhandledrejection = (event) => {
      console.error('[iOS-PROMISE-ERROR]', { reason: event.reason, stack: event.reason?.stack });
    };
  }
}

// ✅ RUNTIME LOAD RECOVERY: auto-recover once from stale cached Vite/React chunk failures
if (typeof window !== 'undefined') {
  const runtimeRecoveryPattern = /Importing a module script failed|Failed to fetch dynamically imported module|Loading chunk [\d]+ failed|Invalid hook call|dispatcher\.use(?:Effect|State|Reducer|Memo|Callback|Ref)|null is not an object \(evaluating 'dispatcher\.|Cannot read properties of null \(reading 'use/i;

  const getReasonMessage = (reason: unknown): string => {
    if (typeof reason === 'string') return reason;
    if (reason && typeof reason === 'object' && 'message' in reason) {
      return String((reason as { message?: unknown }).message ?? '');
    }
    return '';
  };

  const triggerRecovery = () => {
    if (sessionStorage.getItem(RUNTIME_RECOVERY_KEY) === '1') return;
    sessionStorage.setItem(RUNTIME_RECOVERY_KEY, '1');
    setLoadingStatus('Runtime recovery gestart', 'Retry 1/1: caches en service workers worden opgeschoond');

    const url = new URL(window.location.href);
    url.searchParams.set('clear-sw', '1');
    url.searchParams.set('chunk-recover', '1');
    window.location.replace(`${url.pathname}?${url.searchParams.toString()}${url.hash}`);
  };

  window.addEventListener('error', (event) => {
    const message = event?.message ? String(event.message) : '';
    if (runtimeRecoveryPattern.test(message)) {
      console.warn('[RUNTIME-RECOVERY] Detected stale chunk/React runtime mismatch. Triggering recovery reload.');
      triggerRecovery();
    }
  });

  window.addEventListener('unhandledrejection', (event) => {
    const message = getReasonMessage(event.reason);
    if (runtimeRecoveryPattern.test(message)) {
      console.warn('[RUNTIME-RECOVERY] Detected runtime import rejection. Triggering recovery reload.');
      triggerRecovery();
    }
  });

  // If recovery succeeded and app booted with the flag in URL, clear marker for future updates.
  if (new URLSearchParams(window.location.search).has('chunk-recover')) {
    sessionStorage.removeItem(RUNTIME_RECOVERY_KEY);
  }
}

// Disable legacy PWA behavior in production and actively clean up stale service workers.
// This prevents old cached app shells from serving outdated pages like the legacy SCI report.
if (import.meta.env.PROD && typeof window !== 'undefined' && 'serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistrations().then((registrations) => {
    registrations.forEach((registration) => {
      registration.unregister();
    });
  }).catch(() => {
    // no-op
  });

  if ('caches' in window) {
    caches.keys().then((keys) => {
      keys.forEach((key) => {
        caches.delete(key);
      });
    }).catch(() => {
      // no-op
    });
  }
}

const bootReactApp = async () => {
  await previewCleanupPromise;
  setLoadingStatus('React modules laden', 'ReactDOM en App worden na cache-cleanup geïmporteerd');
  const [{ default: ReactDOM }, { default: App }] = await Promise.all([
    import('react-dom/client'),
    import('./App.tsx'),
  ]);

  setLoadingStatus('React render gestart', 'App component wordt gemount');
  ReactDOM.createRoot(document.getElementById("root")!).render(<App />);

  requestAnimationFrame(() => {
    requestAnimationFrame(() => {
      setLoadingStatus('React render voltooid', 'Loader wordt verwijderd');
      if (typeof window !== 'undefined' && (window as any).__removeLoadingShell) {
        (window as any).__removeLoadingShell();
      }
    });
  });
};

if (!shouldSkipReactBoot) {
  void bootReactApp().catch((error) => {
    console.error('[BOOT] React boot failed:', error);
    const message = error instanceof Error ? error.message : String(error ?? '');
    if (typeof window !== 'undefined' && /Importing a module script failed|Failed to fetch dynamically imported module|Invalid hook call|dispatcher\.use|Cannot read properties of null \(reading 'use/i.test(message)) {
      if (sessionStorage.getItem(RUNTIME_RECOVERY_KEY) !== '1') {
        sessionStorage.setItem(RUNTIME_RECOVERY_KEY, '1');
        const url = new URL(window.location.href);
        url.searchParams.set('clear-sw', '1');
        url.searchParams.set('chunk-recover', '1');
        window.location.replace(`${url.pathname}?${url.searchParams.toString()}${url.hash}`);
      }
    }
  });
}
