import React from "react";
import * as ReactDOMClient from "react-dom/client";
const { createRoot } = ReactDOMClient;
import App from "./App.tsx";
import "./index.css";

// ---- Duplicate React instance detection ----
// If multiple copies of React are bundled, hooks throw "dispatcher is null".
// Detect mismatches early and render a clear, actionable error in the preview.
function detectReactDuplicates(): string | null {
  const issues: string[] = [];

  const w = window as unknown as Record<string, unknown>;
  const prev = w.__LOVABLE_REACT_INSTANCE__ as typeof React | undefined;
  if (prev && prev !== React) {
    issues.push("Multiple React instances detected on window (duplicate copies bundled).");
  } else {
    w.__LOVABLE_REACT_INSTANCE__ = React;
  }

  // Internals shared between React and ReactDOM must be the same object.
  const reactInternals = (React as unknown as Record<string, unknown>)
    .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  const domInternals = (ReactDOMClient as unknown as Record<string, unknown>)
    .__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
  if (reactInternals && domInternals && reactInternals !== domInternals) {
    issues.push(
      "React and ReactDOM are using different internal modules (duplicate React bundle).",
    );
  }

  return issues.length ? issues.join(" ") : null;
}

function renderFatalError(message: string) {
  const root = document.getElementById("root");
  if (!root) return;
  root.innerHTML = `
    <div style="min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;font-family:ui-sans-serif,system-ui,sans-serif;background:#0f172a;color:#f8fafc;">
      <div style="max-width:560px;border:1px solid #ef4444;border-radius:12px;padding:24px;background:#1e293b;">
        <h1 style="margin:0 0 12px;font-size:20px;color:#fca5a5;">Duplicate React instance detected</h1>
        <p style="margin:0 0 12px;line-height:1.5;font-size:14px;">${message}</p>
        <p style="margin:0;line-height:1.5;font-size:13px;color:#cbd5e1;">
          Fix: ensure only one copy of <code>react</code> and <code>react-dom</code> is installed.
          Try clearing <code>node_modules/.vite</code> and reinstalling dependencies.
        </p>
      </div>
    </div>`;
}

// ---- Runtime error overlay with auto-diagnosis ----
type Diagnosis = { title: string; hint: string };

function diagnoseError(message: string, stack: string): Diagnosis {
  const blob = `${message}\n${stack}`.toLowerCase();

  if (
    blob.includes("dispatcher.usecontext") ||
    blob.includes("dispatcher.useeffect") ||
    blob.includes("dispatcher.usestate") ||
    blob.includes("dispatcher is null") ||
    blob.includes("invalid hook call")
  ) {
    return {
      title: "Likely cause: duplicate React instance",
      hint:
        "Two copies of react/react-dom are being bundled, so hook dispatcher is null. " +
        "Clear node_modules/.vite, ensure only one react + react-dom in package.json, " +
        "and check vite.config.ts dedupe: ['react','react-dom'].",
    };
  }

  if (
    blob.includes("usetheme") ||
    blob.includes("themeprovider") ||
    blob.includes("next-themes") ||
    (blob.includes("theme") && blob.includes("context"))
  ) {
    return {
      title: "Likely cause: theming provider conflict",
      hint:
        "A component is calling useTheme() outside a ThemeProvider, or two theme " +
        "providers are mounted. Wrap the app in a single ThemeProvider and remove " +
        "any stale next-themes imports.",
    };
  }

  if (blob.includes("queryclient") || blob.includes("queryclientprovider")) {
    return {
      title: "Likely cause: missing QueryClientProvider",
      hint:
        "A component still uses @tanstack/react-query. This project replaced it " +
        "with useSimpleQuery — switch the offending import.",
    };
  }

  return {
    title: "Unrecognized runtime error",
    hint: "Check the stack trace below and the browser console for more detail.",
  };
}

function escapeHtml(s: string) {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

let overlayShown = false;
function showErrorOverlay(message: string, stack: string) {
  if (overlayShown) return;
  overlayShown = true;

  const { title, hint } = diagnoseError(message, stack);
  const id = "__lovable_error_overlay__";
  document.getElementById(id)?.remove();

  const el = document.createElement("div");
  el.id = id;
  el.setAttribute(
    "style",
    "position:fixed;inset:0;z-index:2147483647;background:rgba(15,23,42,.92);" +
      "display:flex;align-items:flex-start;justify-content:center;padding:24px;overflow:auto;" +
      "font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:#f8fafc;",
  );
  el.innerHTML = `
    <div style="max-width:760px;width:100%;border:1px solid #ef4444;border-radius:12px;
                padding:20px;background:#1e293b;box-shadow:0 20px 60px rgba(0,0,0,.5);">
      <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
        <strong style="color:#fca5a5;font-size:16px;">Runtime error</strong>
        <button id="${id}_close" style="background:transparent;border:1px solid #475569;
                color:#cbd5e1;border-radius:6px;padding:4px 10px;cursor:pointer;font-size:12px;">
          Dismiss
        </button>
      </div>
      <div style="background:#0f172a;border-radius:8px;padding:12px;margin-bottom:14px;
                  font-size:13px;line-height:1.5;color:#fecaca;white-space:pre-wrap;
                  word-break:break-word;">${escapeHtml(message) || "(no message)"}</div>
      <div style="border-left:3px solid #f59e0b;padding:8px 12px;margin-bottom:14px;
                  background:rgba(245,158,11,.08);border-radius:0 6px 6px 0;">
        <div style="color:#fcd34d;font-size:13px;font-weight:600;margin-bottom:4px;
                    font-family:ui-sans-serif,system-ui,sans-serif;">${escapeHtml(title)}</div>
        <div style="color:#fde68a;font-size:12px;line-height:1.5;
                    font-family:ui-sans-serif,system-ui,sans-serif;">${escapeHtml(hint)}</div>
      </div>
      <details style="font-size:12px;color:#94a3b8;">
        <summary style="cursor:pointer;color:#cbd5e1;margin-bottom:6px;">Stack trace</summary>
        <pre style="margin:0;padding:12px;background:#0f172a;border-radius:6px;
                    overflow:auto;max-height:300px;font-size:11px;line-height:1.5;
                    color:#cbd5e1;white-space:pre-wrap;word-break:break-word;">${escapeHtml(stack) || "(no stack)"}</pre>
      </details>
    </div>`;
  document.body.appendChild(el);
  document.getElementById(`${id}_close`)?.addEventListener("click", () => {
    el.remove();
    overlayShown = false;
  });
}

// Catch cross-origin script errors (e.g. third-party scripts) to prevent blank screens
const isOpaqueScriptError = (event: ErrorEvent) => {
  const message = (event.message || "").trim();
  const filename = (event.filename || "").trim();
  return message === "Script error." || filename.length === 0 || filename === "Unknown file";
};

window.addEventListener(
  "error",
  (event) => {
    if (isOpaqueScriptError(event)) {
      event.preventDefault();
      event.stopImmediatePropagation();
      console.warn("Suppressed opaque script error from third-party script:", event.message);
      return;
    }
    showErrorOverlay(event.message || String(event.error), event.error?.stack ?? "");
  },
  true,
);

// Catch unhandled promise rejections globally
window.addEventListener("unhandledrejection", (event) => {
  console.warn("Unhandled promise rejection:", event.reason);
  const reason = event.reason;
  const msg = reason instanceof Error ? reason.message : String(reason ?? "");
  const stack = reason instanceof Error ? reason.stack ?? "" : "";
  showErrorOverlay(msg, stack);
  event.preventDefault();
});

const duplicateIssue = detectReactDuplicates();
if (duplicateIssue) {
  console.error("[React duplicate check]", duplicateIssue);
  renderFatalError(duplicateIssue);
} else {
  createRoot(document.getElementById("root")!).render(<App />);
}
