// app.jsx - root app, page routing, tweaks panel wiring

// Origins allowed to drive the builder "edit mode" via postMessage. The edit-mode protocol
// is a trusted authoring channel, so it must never accept messages from (or broadcast state
// to) arbitrary embedding pages. Add your builder/preview origin(s) here; localhost covers
// local development. If none match in production, edit mode simply stays off.
const EDIT_MODE_ORIGINS = [
  "http://localhost:3000",
  "http://127.0.0.1:3000",
  // "https://your-builder-origin.example",
];

// Post a message to every trusted parent origin instead of the "*" wildcard, so edit-mode
// state is never leaked to an untrusted page that framed us.
function postToEditModeParents(message) {
  if (window.parent === window) return;
  for (const origin of EDIT_MODE_ORIGINS) {
    try { window.parent.postMessage(message, origin); } catch (_) { /* origin mismatch */ }
  }
}

function TweaksPanel({ tweaks, setTweaks, visible }) {
  if (!visible) return null;
  const set = (k, v) => {
    setTweaks(t => {
      const next = { ...t, [k]: v };
      postToEditModeParents({ type: "__edit_mode_set_keys", edits: { [k]: v } });
      return next;
    });
  };
  return (
    <div className="tweaks-panel">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
        <Mono style={{ color: "var(--accent)", fontSize: 11, letterSpacing: "0.12em" }}>◆ TWEAKS</Mono>
        <Mono style={{ color: "var(--fg-dim)", fontSize: 10 }}>live · persisted</Mono>
      </div>

      <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
        <div>
          <Label>HERO VARIANT</Label>
          <div style={{ display: "flex", gap: 4, marginTop: 8 }}>
            {[["live-soc", "Live SOC"], ["world-map", "Map"], ["editorial", "Editorial"]].map(([v, l]) => (
              <button key={v} onClick={() => set("heroVariant", v)}
                style={{
                  flex: 1,
                  padding: "8px 6px",
                  fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.06em",
                  border: "1px solid " + (tweaks.heroVariant === v ? "var(--accent)" : "var(--line)"),
                  background: tweaks.heroVariant === v ? "var(--accent)" : "transparent",
                  color: tweaks.heroVariant === v ? "#000" : "var(--fg-mute)",
                }}>{l}</button>
            ))}
          </div>
        </div>

        <div>
          <div style={{ display: "flex", justifyContent: "space-between" }}>
            <Label>ACCENT HUE</Label>
            <Mono style={{ fontSize: 11, color: "var(--accent)" }}>{tweaks.accentHue}°</Mono>
          </div>
          <input type="range" min={0} max={360} step={5} value={tweaks.accentHue}
            onChange={e => set("accentHue", Number(e.target.value))}
            style={{ width: "100%", marginTop: 6, accentColor: `oklch(0.82 0.17 ${tweaks.accentHue})` }} />
        </div>

        <Toggle label="SHOW TICKER"    v={tweaks.showTicker}    set={v => set("showTicker", v)} />
        <Toggle label="DENSE LAYOUT"   v={tweaks.denseLayout}   set={v => set("denseLayout", v)} />
        <Toggle label="MONO HEADLINES" v={tweaks.monoHeadlines} set={v => set("monoHeadlines", v)} />
      </div>
    </div>
  );
}

const Toggle = ({ label, v, set }) => (
  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
    <Label>{label}</Label>
    <button onClick={() => set(!v)}
      style={{
        width: 38, height: 20, borderRadius: 10,
        background: v ? "var(--accent)" : "var(--line)",
        position: "relative", transition: "background 160ms",
      }}>
      <span style={{
        position: "absolute", top: 2,
        left: v ? 20 : 2,
        width: 16, height: 16, borderRadius: "50%",
        background: v ? "#000" : "var(--fg)",
        transition: "left 160ms",
      }} />
    </button>
  </div>
);

// Extract page id from URL path: /about → "about", / → "home", /pricing → "pricing"
function getPageFromPath() {
  // Handle 404.html redirect: /?p=/about → "about"
  const params = new URLSearchParams(window.location.search);
  const redirected = params.get("p");
  if (redirected) {
    const clean = redirected.replace(/^\//, "").replace(/\.html$/, "").replace(/\/$/, "");
    const allPages = [...PAGES.map(p => p.id), "privacy", "terms", "download-community"];
    // Validate against the allowlist BEFORE touching the address bar. Writing the raw,
    // attacker-controlled ?p= value via replaceState first let any path be displayed under
    // the real origin (URL-bar spoofing / phishing aid). Only ever reflect a known page.
    if (clean && clean !== "index" && allPages.includes(clean)) {
      window.history.replaceState(null, "", "/" + clean);
      return clean;
    }
    window.history.replaceState(null, "", "/");
    return "home";
  }

  let path = window.location.pathname.replace(/^\//, "").replace(/\.html$/, "").replace(/\/$/, "");
  // Also support hash fallback for backwards compat
  if (!path && window.location.hash) path = window.location.hash.replace("#", "");
  if (!path || path === "index") return "home";
  const allPages = [...PAGES.map(p => p.id), "privacy", "terms", "download-community"];
  return allPages.includes(path) ? path : "home";
}

function App() {
  const [page, setPageState] = React.useState(getPageFromPath);
  const [tweaks, setTweaks] = React.useState(window.__TWEAKS__);
  const [tweaksVisible, setTweaksVisible] = React.useState(false);

  const setPage = React.useCallback((newPage) => {
    setPageState(newPage);
    const url = newPage === "home" ? "/" : "/" + newPage;
    window.history.pushState({ page: newPage }, "", url);
  }, []);

  // Handle browser back/forward
  React.useEffect(() => {
    const onPop = () => setPageState(getPageFromPath());
    window.addEventListener("popstate", onPop);
    return () => window.removeEventListener("popstate", onPop);
  }, []);

  React.useEffect(() => {
    window.scrollTo(0, 0);
    // Update document title
    const label = PAGES.find(p => p.id === page)?.label || page;
    document.title = page === "home"
      ? "Secure Sleuths - Security for Indian Startups"
      : label + " - Secure Sleuths";
  }, [page]);

  // Apply accent hue live
  React.useEffect(() => {
    document.documentElement.style.setProperty("--accent",   `oklch(0.82 0.17 ${tweaks.accentHue})`);
    document.documentElement.style.setProperty("--accent-d", `oklch(0.68 0.17 ${tweaks.accentHue})`);
  }, [tweaks.accentHue]);

  // Apply mono headline
  React.useEffect(() => {
    const id = "mono-headlines-style";
    let el = document.getElementById(id);
    if (tweaks.monoHeadlines) {
      if (!el) {
        el = document.createElement("style");
        el.id = id;
        document.head.appendChild(el);
      }
      el.textContent = `.serif { font-family: var(--mono) !important; font-style: normal !important; letter-spacing: -0.04em !important; }`;
    } else if (el) el.remove();
  }, [tweaks.monoHeadlines]);

  // Dense layout
  React.useEffect(() => {
    const id = "dense-layout-style";
    let el = document.getElementById(id);
    if (tweaks.denseLayout) {
      if (!el) {
        el = document.createElement("style");
        el.id = id;
        document.head.appendChild(el);
      }
      el.textContent = `section { padding-top: 40px !important; padding-bottom: 40px !important; }`;
    } else if (el) el.remove();
  }, [tweaks.denseLayout]);

  // Cross-component nav via custom event
  React.useEffect(() => {
    const on = (e) => setPage(e.detail);
    window.addEventListener("nav", on);
    return () => window.removeEventListener("nav", on);
  }, []);

  // Edit mode protocol
  React.useEffect(() => {
    const on = (e) => {
      // Only honor edit-mode control messages from a trusted builder origin sent by our
      // actual parent frame. Without this check any page that embeds us (the site has no
      // frame-ancestors restriction) could toggle the authoring panel cross-origin.
      if (!EDIT_MODE_ORIGINS.includes(e.origin)) return;
      if (e.source !== window.parent) return;
      if (e.data?.type === "__activate_edit_mode")   setTweaksVisible(true);
      if (e.data?.type === "__deactivate_edit_mode") setTweaksVisible(false);
    };
    window.addEventListener("message", on);
    // announce after listener is live (only to trusted parent origins, never "*")
    postToEditModeParents({ type: "__edit_mode_available" });
    return () => window.removeEventListener("message", on);
  }, []);

  const P = {
    home:        HomePage,
    platform:    PlatformPage,
    services:    ServicesPage,
    methodology: MethodologyPage,
    pricing:     PricingPage,
    training:    TrainingPage,
    cases:       CasesPage,
    about:       AboutPage,
    blog:        BlogPage,
    contact:     ContactPage,
    partners:    PartnersPage,
    "early-access": EarlyAccessPage,
    "download-community": DownloadCommunityPage,
    privacy:     PrivacyPage,
    terms:       TermsPage,
  }[page] || HomePage;

  return (
    <RouteCtx.Provider value={{ route: page, go: setPage }}>
      <div data-screen-label={PAGES.find(p => p.id === page)?.label || page}>
        <TopNav />
        <main id="main-content" role="main">
          <P setPage={setPage} tweaks={tweaks} />
        </main>
        <Footer />
        <TweaksPanel tweaks={tweaks} setTweaks={setTweaks} visible={tweaksVisible} />
      </div>
    </RouteCtx.Provider>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
