// Main app — routes between pages and wires Tweaks
const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#2563d6",
  "density": "comfortable",
  "displayFont": "Instrument Serif"
}/*EDITMODE-END*/;

function App() {
  const savedLanguage = () => {
    try {
      const stored = window.localStorage.getItem("modelport-language");
      return getLanguage(stored).id;
    } catch (error) {
      return DEFAULT_LANGUAGE;
    }
  };

  const pageFromHash = () => {
    const h = window.location.hash.replace("#", "");
    if (h === "fit-result") return h;
    return NAV_PAGES.find(p => p.id === h) ? h : "home";
  };

  const [page, setPage] = useState(() => {
    return pageFromHash();
  });
  const [language, setLanguage] = useState(savedLanguage);
  const [answers, setAnswers] = useState({});
  const [result, setResult] = useState(null);

  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    const nextLanguage = getLanguage(language);
    document.documentElement.lang = nextLanguage.htmlLang;
    try {
      window.localStorage.setItem("modelport-language", nextLanguage.id);
    } catch (error) {
      // Browsers can disable storage; the in-memory picker still works.
    }
  }, [language]);

  // Sync URL hash
  useEffect(() => {
    const targetHash = "#" + page;
    if (window.location.hash !== targetHash) {
      window.location.hash = page;
    }
    window.scrollTo({ top: 0, behavior: "auto" });
  }, [page]);

  useEffect(() => {
    const onHashChange = () => {
      const nextPage = pageFromHash();
      setPage(current => current === nextPage ? current : nextPage);
    };
    window.addEventListener("hashchange", onHashChange);
    return () => window.removeEventListener("hashchange", onHashChange);
  }, []);

  // Add subtle reveal-on-scroll/entry animations for major page blocks.
  useEffect(() => {
    const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");

    const resetNode = (el) => {
      el.classList.remove("is-visible");
      el.removeAttribute("data-reveal");
      el.style.removeProperty("--reveal-delay");
    };

    const assignReveal = (selector, mode = "up", baseDelay = 0, step = 0) => {
      const nodes = document.querySelectorAll(selector);
      nodes.forEach((el, idx) => {
        if (el.dataset.reveal) return;
        if (reduceMotion.matches) {
          el.classList.add("is-visible");
          el.dataset.reveal = mode;
          el.style.setProperty("--reveal-delay", `${baseDelay}ms`);
          return;
        }

        el.dataset.reveal = mode;
        el.style.setProperty("--reveal-delay", `${baseDelay + idx * step}ms`);
      });
      return nodes;
    };

    document.querySelectorAll("[data-reveal]").forEach(resetNode);

    const revealCandidates = [
      ...assignReveal(".promo-banner", "up", 0),
      ...assignReveal(".hero-title", "up", 60),
      ...assignReveal(".hero-grid > .col", "up", 110, 70),
      ...assignReveal(".hero-visual", "soft", 140),
      ...assignReveal(".process-visual", "soft", 160),
      ...assignReveal(".pillar-grid > div", "up", 170, 90),
      ...assignReveal(".partner-grid .card", "up", 220, 80),
      ...assignReveal(".process-grid .row", "left", 200, 60),
      ...assignReveal(".pricing-flow-grid > div", "up", 80, 90),
      ...assignReveal(".fit-field-row", "up", 120, 70),
      ...assignReveal(".fit-result-grid > div", "up", 100, 90),
      ...assignReveal(".provider-card", "up", 80, 60),
      ...assignReveal(".provider-stat", "up", 160, 40),
      ...assignReveal(".model-detail-grid > div", "soft", 120, 65),
      ...assignReveal(".promo-shell", "soft", 0),
      ...assignReveal(".cmp > div", "up", 70, 80),
      ...assignReveal(".metric", "up", 80, 65),
      ...assignReveal(".dashboard-grid > .card", "up", 90, 80),
      ...assignReveal(".control-grid > .card", "up", 90, 70),
      ...assignReveal(".pilot-top-grid > .card", "up", 90, 80),
      ...assignReveal(".pilot-form-grid > .card", "up", 130, 70),
      ...assignReveal(".card-ink.cta-grid", "up", 180),
    ];

    if (reduceMotion.matches) {
      revealCandidates.forEach(el => el.classList.add("is-visible"));
      return;
    }

    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add("is-visible");
          observer.unobserve(entry.target);
        }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -10% 0px" });

    const showVisible = () => {
      revealCandidates.forEach((el) => {
        const r = el.getBoundingClientRect();
        if (r.top < window.innerHeight && r.bottom > 0) {
          el.classList.add("is-visible");
          observer.unobserve(el);
        }
      });
    };

    revealCandidates.forEach(el => observer.observe(el));
    const rafId = window.requestAnimationFrame(showVisible);

    return () => {
      window.cancelAnimationFrame(rafId);
      observer.disconnect();
    };
  }, [page]);

  // Apply tweak: accent
  useEffect(() => {
    document.documentElement.style.setProperty("--accent", tweaks.accent);
  }, [tweaks.accent]);

  // Apply tweak: density
  useEffect(() => {
    const d = tweaks.density;
    document.documentElement.style.setProperty("--max-w", d === "wide" ? "1360px" : d === "tight" ? "1120px" : "1240px");
  }, [tweaks.density]);

  // Apply tweak: display font
  useEffect(() => {
    const f = tweaks.displayFont;
    const map = {
      "Instrument Serif": "'Instrument Serif', 'Times New Roman', serif",
      "Fraunces": "'Fraunces', 'Times New Roman', serif",
      "Geist": "'Geist', system-ui, sans-serif",
      "DM Serif Display": "'DM Serif Display', serif",
    };
    document.documentElement.style.setProperty("--font-display", map[f] || map["Instrument Serif"]);
  }, [tweaks.displayFont]);

  // Edit mode protocol is handled by <TweaksPanel> itself — no need to wire it here.

  const go = (id) => {
    if (id === "fit") setResult(null); // restart fit check on nav
    setPage(id);
  };

  const submitFitCheck = () => {
    const r = recommend(answers);
    setResult(r);
    setPage("fit-result");
  };

  const restartFitCheck = () => {
    setResult(null);
    setPage("fit");
  };

  let content;
  if (page === "home")       content = <Home go={go} language={language} />;
  else if (page === "why")   content = <PageWhy go={go} language={language} />;
  else if (page === "fit")   content = <FitCheckForm answers={answers} setAnswers={setAnswers} onSubmit={submitFitCheck} language={language} />;
  else if (page === "fit-result") content = result
    ? <FitCheckResult answers={answers} result={result} go={go} restart={restartFitCheck} language={language} />
    : <FitCheckForm answers={answers} setAnswers={setAnswers} onSubmit={submitFitCheck} language={language} />;
  else if (page === "catalog")   content = <PageCatalog go={go} language={language} />;
  else if (page === "pricing")   content = <PagePricing go={go} language={language} />;
  else if (page === "overseas")  content = <PageOverseas go={go} language={language} />;
  else if (page === "dashboard") content = <PageDashboard go={go} language={language} />;
  else if (page === "pilot")     content = <PagePilot go={go} language={language} />;
  else content = <Home go={go} language={language} />;

  // Map "fit-result" highlight back to fit nav item
  const navPage = page === "fit-result" ? "fit" : page;

  return (
    <div>
      <Nav page={navPage} go={go} language={language} onLanguageChange={setLanguage} />
      {content}
      <Footer go={go} language={language} />

      <TweaksPanel>
          <TweakSection title="Brand">
            <TweakColor
              label="Accent"
              value={tweaks.accent}
              onChange={v => setTweak("accent", v)}
              options={["#2563d6", "#d65a3c", "#1f8a5b", "#7a5ae0", "#1a1a1a"]}
            />
            <TweakSelect
              label="Display font"
              value={tweaks.displayFont}
              onChange={v => setTweak("displayFont", v)}
              options={["Instrument Serif", "Fraunces", "DM Serif Display", "Geist"]}
            />
          </TweakSection>
          <TweakSection title="Layout">
            <TweakRadio
              label="Density"
              value={tweaks.density}
              onChange={v => setTweak("density", v)}
              options={["tight", "comfortable", "wide"]}
            />
          </TweakSection>
          <TweakSection title="Navigate">
            <div className="col" style={{ gap: 6 }}>
              {[
                "home",
                "why",
                "fit",
                "catalog",
                "pricing",
                "overseas",
                "dashboard",
                "pilot",
              ].map(id => {
                const navItem = NAV_PAGES.find(p => p.id === id);
                const label = navItem ? localizedLabel(navItem.label, language) : id;
                return (
                <button key={id}
                  className={"choice" + (navPage === id ? " on" : "")}
                  style={{ justifyContent: "flex-start" }}
                  onClick={() => go(id)}>
                  {label}
                </button>
              );})}
            </div>
            <TweakButton onClick={() => { go("fit"); setAnswers({}); setResult(null); }}>↺ Reset Fit Check</TweakButton>
            <TweakButton onClick={() => {
              setAnswers({
                workload: "Contract review",
                sensitivity: "Regulated",
                azure: "Azure blocked for this workload",
                deployment: "Must stay in Hong Kong",
                goal: "Overseas-ready model version",
                commercial: "Discounted bulk capacity",
              });
              const r = recommend({
                workload: "Contract review",
                sensitivity: "Regulated",
                azure: "Azure blocked for this workload",
                deployment: "Must stay in Hong Kong",
                goal: "Overseas-ready model version",
                commercial: "Discounted bulk capacity",
              });
              setResult(r);
              setPage("fit-result");
            }}>⚡ Demo: ModelPort result</TweakButton>
            <TweakButton onClick={() => {
              const a = {
                workload: "Customer service chatbot",
                sensitivity: "Public",
                azure: "Already use Azure",
                deployment: "Public cloud is fine",
                goal: "Best accuracy",
                commercial: "Pay-as-you-go",
              };
              setAnswers(a);
              setResult(recommend(a));
              setPage("fit-result");
            }}>⚡ Demo: Azure result</TweakButton>
            <TweakButton onClick={() => {
              const a = {
                workload: "Financial research assistant",
                sensitivity: "Confidential",
                azure: "Azure only for non-sensitive workloads",
                deployment: "Hybrid setup preferred",
                goal: "Vendor diversification",
                commercial: "Dedicated capacity",
              };
              setAnswers(a);
              setResult(recommend(a));
              setPage("fit-result");
            }}>⚡ Demo: Hybrid result</TweakButton>
          </TweakSection>
      </TweaksPanel>
    </div>
  );
}

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