/* Wellpaged Builder — app.jsx
   Drives the 5-step intake flow (Theme → Brand → Story → Socials → Review) with a
   persistent Back/Next footer, a live device preview, and the real publish flow:
   Turnstile-gated POST /api/publish → poll the deployed path → flip to Live. */
const { useState: uS } = React;

function Builder() {
  const [stepIdx, setStepIdx] = uS(0);
  const [maxIdx, setMaxIdx] = uS(0);
  const [theme, setTheme] = uS("soft");
  const [status, setStatus] = uS("draft");
  const [showDialog, setShowDialog] = uS(false);
  const [toast, setToast] = uS(null);
  const [tsToken, setTsToken] = uS(null);

  const [profile, setProfile] = uS({
    name: "Rissa", initial: "R", handle: "rissa", category: "ASMR & Sleep",
    tagline: "Soft sounds. Deep sleep.",
    about: "I make ASMR to help people fall asleep. New triggers and long-form sessions every week — come rest with me.",
  });
  const [links, setLinks] = uS([
    { label: "Watch the latest LIVE", url: "https://tiktok.com/@relaxwithrissa", feat: true },
    { label: "Listen to the sleep playlist", url: "https://open.spotify.com/", feat: false },
    { label: "Book a sponsored integration", url: "mailto:hi@rissa.com", feat: false },
  ]);
  const [socials, setSocials] = uS([
    { platform: "tiktok", handle: "@relaxwithrissa", on: true },
    { platform: "instagram", handle: "@relaxwithrissa", on: true },
    { platform: "youtube", handle: "@relaxwithrissa", on: true },
    { platform: "x", handle: "", on: false },
  ]);

  const step = STEPS[stepIdx].id;
  const last = STEPS.length - 1;

  const flashToast = (msg, type = "success", ms = 8000) => { setToast({ msg, type }); setTimeout(() => setToast(null), ms); };

  const goTo = (id) => {
    const i = STEPS.findIndex((s) => s.id === id);
    if (i < 0) return;
    setStepIdx(i);
    setMaxIdx((m) => Math.max(m, i));
    if (i === last) setStatus((s) => (s === "live" || s === "building" ? s : "staged"));
  };
  const goNext = () => {
    if (stepIdx === last) { setTsToken(null); setShowDialog(true); return; }
    goTo(STEPS[stepIdx + 1].id);
  };
  const goBack = () => { if (stepIdx > 0) goTo(STEPS[stepIdx - 1].id); };

  // gate Next on the brand step (need a name + a valid-length handle)
  const h = (profile.handle || "").toLowerCase();
  const handleOk = h.length >= 3 && h.length <= 40 && !h.startsWith("-") && !h.endsWith("-");
  const canNext = step === "brand" ? !!(profile.name.trim() && handleOk) : true;
  const nextLabel = stepIdx === last ? "Build & publish →" : "Next →";

  // After a build is queued the page deploys at the same origin /<slug>/, so we can
  // poll it directly (no CORS) and flip to "live" once it answers.
  const pollLive = (path, url) => {
    const started = Date.now();
    const tick = () => {
      if (Date.now() - started > 240000) { flashToast("Still building — your page will appear shortly. Check the admin.", "info", 9000); return; }
      fetch(path + "?_=" + Date.now(), { method: "HEAD", cache: "no-store" })
        .then((r) => { if (r.ok) { setStatus("live"); flashToast("You're live at " + url, "success", 9000); } else setTimeout(tick, 5000); })
        .catch(() => setTimeout(tick, 5000));
    };
    setTimeout(tick, 5000);
  };

  const doPublish = () => {
    if (!tsToken) { flashToast("Please complete the verification check first.", "error"); return; }
    setShowDialog(false);
    setStatus("building");
    fetch("/api/publish", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ slug: profile.handle, clientName: profile.name, theme, profile, links, socials, turnstileToken: tsToken }),
    })
      .then((r) => r.json().then((d) => ({ ok: r.ok, d })).catch(() => ({ ok: r.ok, d: {} })))
      .then(({ ok, d }) => {
        if (!ok) { setStatus("staged"); flashToast(d && d.error ? "Couldn't start the build: " + d.error : "Couldn't start the build.", "error"); return; }
        const path = d.path || ("/" + profile.handle + "/");
        const url = d.url || (profile.handle + ".wellpaged.com");
        flashToast("Build queued — Claude is building your page. Live shortly at " + url, "success", 9000);
        pollLive(path, url);
      })
      .catch(() => { setStatus("staged"); flashToast("Couldn't reach the build engine.", "error"); });
  };

  return (
    <div className="builder">
      <div className="editor">
        <TopBar status={status} />
        <Stepper current={step} maxReached={STEPS[maxIdx].id} onGo={goTo} />
        <div className="stepbody">
          {step === "theme" && <ThemePicker value={theme} onChange={setTheme} />}
          {step === "brand" && <BrandForm profile={profile} onChange={setProfile} />}
          {step === "story" && <StoryForm profile={profile} links={links} onProfile={setProfile} onLinks={setLinks} />}
          {step === "socials" && <SocialsForm socials={socials} onChange={setSocials} />}
          {step === "review" && <ReviewStep profile={profile} theme={theme} socials={socials} />}
        </div>
        <StepNav stepIndex={stepIdx} total={STEPS.length} canNext={canNext}
                 nextLabel={nextLabel} onBack={goBack} onNext={goNext} />
      </div>
      <DevicePreview theme={theme} profile={profile} links={links} socials={socials} status={status} />
      {showDialog && <PublishDialog handle={profile.handle || "yourname"} token={tsToken} onToken={setTsToken} onConfirm={doPublish} onClose={() => setShowDialog(false)} />}
      {toast && <div className={"toast " + toast.type}><span className="s">{toast.type === "error" ? "Error" : toast.type === "info" ? "Heads up" : "Live ♡"}</span>{toast.msg}</div>}
    </div>
  );
}
ReactDOM.createRoot(document.getElementById("root")).render(<Builder />);
