// Correspondence.jsx — verified-email signup for the Lulius correspondence list.
//
// Route:  #/correspondence           (optionally "?src=apply|careers" to tag
//                                     where the subscriber came from)
//
// Double-opt-in against the api (shares the apply flow's code machinery):
//   1. email + Turnstile → POST /api/correspondence/request-code
//   2. code              → POST /api/correspondence/confirm  (subscribed)
//
// Subscribers are stored on a private api-only volume; every message sent to
// the list carries a signed one-click unsubscribe link.

const { useState: useSCo, useEffect: useECo, useRef: useRCo } = React;

function CorrespondencePage({ onNavigate, source }) {
  // step: "email" | "code" | "done"
  const [step, setStep] = useSCo("email");
  const [busy, setBusy] = useSCo(false);
  const [errorMsg, setErrorMsg] = useSCo("");
  const [email, setEmail] = useSCo("");
  const [code, setCode] = useSCo("");
  const [already, setAlready] = useSCo(false);
  const [hpCheck, setHpCheck] = useSCo(false); // honeypot — must stay false
  const [turnstileToken, setTurnstileToken] = useSCo("");
  const [resendAt, setResendAt] = useSCo(0);
  const [tick, setTick] = useSCo(Date.now());
  const turnstileMountRef = useRCo(null);
  const turnstileWidgetIdRef = useRCo(null);

  // Turnstile lifecycle — same contract as Apply.jsx: the effect owns the
  // widget, removes it on step change/unmount, and a fresh widget (= fresh
  // single-use token) mounts wherever the current step renders the mount div.
  useECo(() => {
    if (step !== "email" && step !== "code") return;
    let cancelled = false;
    const mount = () => {
      if (cancelled || !turnstileMountRef.current || !window.turnstile) return;
      if (turnstileWidgetIdRef.current !== null) return;
      turnstileWidgetIdRef.current = window.turnstile.render(turnstileMountRef.current, {
        sitekey: window.TURNSTILE_SITE_KEY || "",
        theme: "dark",
        callback: (token) => setTurnstileToken(token),
        "error-callback": () => setTurnstileToken(""),
        "expired-callback": () => setTurnstileToken(""),
      });
    };
    let interval = null;
    if (window.turnstile) {
      mount();
    } else {
      interval = setInterval(() => {
        if (window.turnstile) { clearInterval(interval); mount(); }
      }, 150);
    }
    return () => {
      cancelled = true;
      if (interval) clearInterval(interval);
      if (turnstileWidgetIdRef.current !== null && window.turnstile) {
        try { window.turnstile.remove(turnstileWidgetIdRef.current); } catch (e) { /* gone */ }
      }
      turnstileWidgetIdRef.current = null;
      setTurnstileToken("");
    };
  }, [step]);

  useECo(() => {
    if (step !== "code") return;
    const i = setInterval(() => setTick(Date.now()), 1000);
    return () => clearInterval(i);
  }, [step]);
  const resendWait = Math.max(0, Math.ceil((resendAt - tick) / 1000));

  const fail = (msg) => { setErrorMsg(msg); setBusy(false); };
  const resetWidgetForFreshToken = () => {
    if (window.turnstile && turnstileWidgetIdRef.current !== null) {
      try { window.turnstile.reset(turnstileWidgetIdRef.current); } catch (e) { /* ignore */ }
    }
    setTurnstileToken("");
  };

  const requestCode = async () => {
    if (busy || !turnstileToken) return;
    setBusy(true);
    setErrorMsg("");
    try {
      const r = await fetch("/api/correspondence/request-code", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email, turnstileToken, _hp_check: hpCheck }),
      });
      const j = await r.json().catch(() => ({ ok: false, error: "Bad server response." }));
      if (r.ok && j.ok) {
        setResendAt(Date.now() + 60 * 1000);
        setTick(Date.now());
        setCode("");
        if (step === "email") setStep("code");
        else resetWidgetForFreshToken();
        setBusy(false);
      } else {
        resetWidgetForFreshToken();
        fail(j.error || "Something went wrong. Try again in a moment.");
      }
    } catch (err) {
      fail("Network error. Check your connection and try again.");
    }
  };

  const confirm = async () => {
    if (busy || code.length !== 6) return;
    setBusy(true);
    setErrorMsg("");
    try {
      const r = await fetch("/api/correspondence/confirm", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email, code, source: source || "direct" }),
      });
      const j = await r.json().catch(() => ({ ok: false, error: "Bad server response." }));
      if (r.ok && j.ok) {
        setAlready(!!j.already);
        setStep("done");
        setBusy(false);
      } else {
        fail(j.error || "Verification failed.");
      }
    } catch (err) {
      fail("Network error. Check your connection and try again.");
    }
  };

  const inputStyle = {
    background: "transparent",
    border: "none",
    borderBottom: "1px solid var(--line-2)",
    color: "var(--paper)",
    padding: "14px 0 12px",
    fontFamily: "var(--f-body)",
    fontSize: 16,
    width: "100%",
    outline: "none",
  };
  const labelStyle = {
    fontFamily: "var(--f-mono)", fontSize: 12, letterSpacing: ".14em",
    textTransform: "uppercase", color: "var(--mute)",
    display: "block", marginBottom: 8,
  };

  return (
    <main>
      <PageHeader
        idx="08 / CORRESPONDENCE"
        title={<>Stay on <span className="accent-text">the line.</span></>}
        lede="Occasional dispatches from Lulius — new positions, platform news, and company milestones. No noise, and a one-click unsubscribe in every message."
      />

      <section className="section">
        <div className="wrap" style={{ maxWidth: 720 }}>
          {errorMsg && (
            <div style={{
              marginBottom: 32, padding: "14px 18px",
              border: "1px solid var(--accent)", color: "var(--paper)",
              fontFamily: "var(--f-mono)", fontSize: 12, letterSpacing: ".06em",
            }}>
              ERR · {errorMsg}
            </div>
          )}

          {step === "email" && (
            <form onSubmit={(e) => { e.preventDefault(); requestCode(); }} style={{ display: "flex", flexDirection: "column", gap: 32 }}>
              <div aria-hidden="true" style={{ position: "absolute", left: "-9999px", top: "auto", width: 1, height: 1, overflow: "hidden" }}>
                <input type="checkbox" name="_hp_check" tabIndex={-1} autoComplete="off"
                  checked={hpCheck} onChange={(e) => setHpCheck(e.target.checked)} />
              </div>
              <p className="lede mute" style={{ margin: 0 }}>
                We'll email you a 6-digit code to confirm the address — nobody gets added to this list without proving it's theirs.
              </p>
              <div>
                <label style={labelStyle}>Email</label>
                <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required
                  style={inputStyle} placeholder="you@example.com" autoComplete="email" />
              </div>
              <div ref={turnstileMountRef} />
              <div>
                <button type="submit" className="btn" disabled={busy || !turnstileToken}
                  style={{ opacity: busy || !turnstileToken ? 0.5 : 1 }}>
                  {busy ? "Sending…" : <>Send code <span className="arrow">→</span></>}
                </button>
              </div>
            </form>
          )}

          {step === "code" && (
            <form onSubmit={(e) => { e.preventDefault(); confirm(); }} style={{ display: "flex", flexDirection: "column", gap: 32 }}>
              <p className="lede mute" style={{ margin: 0 }}>
                We sent a 6-digit code to <span style={{ color: "var(--paper)" }}>{email}</span>. It expires in 10 minutes.
              </p>
              <div>
                <label style={labelStyle}>Verification code</label>
                <input value={code} inputMode="numeric" pattern="[0-9]*" maxLength={6}
                  onChange={(e) => setCode(e.target.value.replace(/\D/g, ""))}
                  style={{ ...inputStyle, fontFamily: "var(--f-mono)", fontSize: 28, letterSpacing: ".4em" }}
                  placeholder="——————" autoComplete="one-time-code" />
              </div>
              <div ref={turnstileMountRef} />
              <div style={{ display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap" }}>
                <button type="submit" className="btn" disabled={busy || code.length !== 6}
                  style={{ opacity: busy || code.length !== 6 ? 0.5 : 1 }}>
                  {busy ? "Checking…" : <>Confirm <span className="arrow">→</span></>}
                </button>
                <button type="button" onClick={requestCode}
                  disabled={busy || resendWait > 0 || !turnstileToken}
                  style={{
                    background: "transparent", border: "1px solid var(--line-2)", color: "var(--paper)",
                    padding: "14px 20px", fontFamily: "var(--f-mono)", fontSize: 12, letterSpacing: ".14em",
                    textTransform: "uppercase", cursor: resendWait > 0 ? "default" : "pointer",
                    opacity: busy || resendWait > 0 || !turnstileToken ? 0.5 : 1,
                  }}>
                  {resendWait > 0 ? `Resend in ${resendWait}s` : "Resend code"}
                </button>
                <button type="button" onClick={() => { setStep("email"); setErrorMsg(""); }}
                  style={{ background: "none", border: "none", color: "var(--mute)", cursor: "pointer", fontFamily: "var(--f-mono)", fontSize: 12, letterSpacing: ".14em", textTransform: "uppercase" }}>
                  Change email
                </button>
              </div>
            </form>
          )}

          {step === "done" && (
            <div style={{ padding: "24px 0" }}>
              <div className="eyebrow accent-text" style={{ marginBottom: 16 }}>
                <span className="dot"></span>{already ? "ALREADY ON THE LIST" : "ON THE LIST"}
              </div>
              <h2 className="display" style={{ fontSize: "clamp(36px, 5vw, 64px)", marginBottom: 24 }}>
                {already ? "You're already with us." : "Welcome aboard."}
              </h2>
              <p className="lede mute" style={{ maxWidth: "55ch" }}>
                {already
                  ? <><span style={{ color: "var(--paper)" }}>{email}</span> was already subscribed — nothing more to do.</>
                  : <><span style={{ color: "var(--paper)" }}>{email}</span> is confirmed. When there's something worth saying — new positions, platform news, company milestones — you'll hear it from us first.</>}
                {" "}Every message includes a one-click unsubscribe.
              </p>
              <div style={{ display: "flex", gap: 16, marginTop: 32, flexWrap: "wrap" }}>
                <a href="#/careers" onClick={(e) => { e.preventDefault(); onNavigate("/careers"); }} className="btn">
                  View open positions <span className="arrow">→</span>
                </a>
                <a href="#/" onClick={(e) => { e.preventDefault(); onNavigate("/"); }} className="btn ghost">
                  Return to index
                </a>
              </div>
            </div>
          )}
        </div>
      </section>

      <ContactCTA onNavigate={onNavigate} />
    </main>
  );
}

window.CorrespondencePage = CorrespondencePage;
