/* ============================================================
   app.jsx — nav, hero copy, two-tier waitlist/deposit modal, mount.
   Soft signal: join waitlist (email only). Hard signal: S$20
   refundable deposit via Stripe Checkout. Captures ?ref= channel
   and handles ?status=success|cancel on return from Stripe.
   ============================================================ */
const { useState, useRef, useEffect } = React;

/* ---- channel + locale captured once from the URL / browser ---- */
function readRef() {
  try {
    return new URLSearchParams(window.location.search).get("ref") || null;
  } catch {
    return null;
  }
}
const LOCALE =
  typeof navigator !== "undefined" &&
  (navigator.language || "en").toLowerCase().startsWith("zh")
    ? "zh"
    : "en";

async function postJSON(url, payload) {
  const res = await fetch(url, {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(payload),
  });
  let data = {};
  try {
    data = await res.json();
  } catch {
    /* ignore */
  }
  if (!res.ok) throw new Error(data.error || "Request failed. Please try again.");
  return data;
}

function Nav() {
  const NavMark = window.NavMark;
  return (
    <nav className="nav container">
      <a className="brand" href="#" aria-label="Slyck home">
        <NavMark size={30} />
        Slyck
      </a>
      <div className="nav-links">
        <a className="nav-link hide-sm" href="#how">How it works</a>
        <a className="nav-link dot" href="#signin">Sign in</a>
      </div>
    </nav>
  );
}

const ArrowIcon = () => (
  <svg className="arrow" width="18" height="14" viewBox="0 0 18 14" fill="none" aria-hidden="true">
    <path d="M1 7h15M11 1.5 16.5 7 11 12.5" stroke="currentColor" strokeWidth="1.8"
          strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);

/* ---------------- Waitlist + deposit modal ---------------- */
// mode: 'form' | 'loading-deposit' | 'loading-waitlist' | 'success-waitlist' | 'success-deposit'
function WaitlistModal({ open, seedMode, refTag, cameFromCancel, onClose }) {
  const [email, setEmail] = useState("");
  const [touched, setTouched] = useState(false);
  const [mode, setMode] = useState("form");      // view: 'form' | 'success-waitlist' | 'success-deposit'
  const [busy, setBusy] = useState(null);        // in-flight action: null | 'deposit' | 'waitlist'
  const [emailed, setEmailed] = useState(true);  // did the waitlist confirmation actually send?
  const [error, setError] = useState("");
  const inputRef = useRef(null);

  const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
  const showErr = touched && !valid && email.length > 0;
  const loading = busy !== null;

  // Re-seed each time the modal opens; re-trigger the melt on deposit success.
  // `busy` is kept separate from `mode` so a deposit started from the waitlist-
  // success screen doesn't unmount that screen (and a failed checkout returns to it).
  useEffect(() => {
    if (!open) return;
    const view =
      seedMode === "success-deposit" ? "success-deposit"
      : seedMode === "success-waitlist" ? "success-waitlist"
      : "form";
    setMode(view);
    setBusy(null);
    setError("");
    if (view === "success-deposit" && window.__slyckMelt) window.__slyckMelt();
    if (view === "form") {
      setEmail("");
      setTouched(false);
      const t = setTimeout(() => inputRef.current && inputRef.current.focus(), 360);
      return () => clearTimeout(t);
    }
  }, [open, seedMode]);

  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape" && open && !loading) onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [open, onClose, loading]);

  const guard = () => {
    setError("");
    if (!valid) { setTouched(true); inputRef.current && inputRef.current.focus(); return false; }
    return true;
  };

  const reserveDeposit = async () => {
    if (!guard()) return;
    setBusy("deposit");
    try {
      const { url } = await postJSON("/api/create-checkout-session", {
        email: email.trim(), ref: refTag,
      });
      window.location.href = url; // hand off to Stripe Checkout
    } catch (e) {
      setError(e.message);
      setBusy(null); // current view (form or waitlist-success) stays put
    }
  };

  const joinWaitlist = async () => {
    if (!guard()) return;
    setBusy("waitlist");
    try {
      const r = await postJSON("/api/subscribe", { email: email.trim(), ref: refTag, locale: LOCALE });
      setEmailed(r.emailed !== false);
      setBusy(null);
      setMode("success-waitlist");
    } catch (e) {
      setError(e.message);
      setBusy(null);
    }
  };

  const isSuccess = mode === "success-waitlist" || mode === "success-deposit";

  return (
    <div className={"modal-overlay" + (open ? " open" : "")}
         style={{ visibility: open ? "visible" : "hidden" }}
         onMouseDown={(e) => { if (e.target === e.currentTarget && !loading) onClose(); }}>
      <div className="modal" role="dialog" aria-modal="true" aria-label="Reserve early access">
        <button className="modal-close" onClick={onClose} aria-label="Close" disabled={loading}>
          <svg width="15" height="15" viewBox="0 0 15 15" fill="none">
            <path d="M2 2l11 11M13 2 2 13" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" />
          </svg>
        </button>

        {!isSuccess ? (
          <form onSubmit={(e) => { e.preventDefault(); reserveDeposit(); }} noValidate>
            <div className="modal-eyebrow">Founding member</div>
            <h2>Reserve your spot at the front.</h2>
            <p className="lede">
              Early members get the best cash-out rate, locked for life. A small
              refundable deposit holds your founding spot — refunded in full the
              day you cash out, or any time you ask.
            </p>

            {cameFromCancel && (
              <div className="modal-note">
                No charge was made — your spot's still open whenever you're ready.
              </div>
            )}

            <div className="field">
              <label htmlFor="wl-email">Email</label>
              <input
                id="wl-email" ref={inputRef} type="email" inputMode="email"
                placeholder="you@studio.com"
                className={showErr ? "invalid" : ""}
                value={email}
                disabled={loading}
                onChange={(e) => setEmail(e.target.value)}
                onBlur={() => setTouched(true)}
              />
              <div className={"field-error" + (showErr ? " show" : "")}>
                Enter a valid email address.
              </div>
            </div>

            <div className="deposit-card">
              <span className="dep-icon">
                <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
                  <rect x="1" y="3.5" width="16" height="11" rx="2.5" stroke="currentColor" strokeWidth="1.6" />
                  <path d="M1 7.5h16" stroke="currentColor" strokeWidth="1.6" />
                </svg>
              </span>
              <div className="dep-body">
                <strong>S$20 refundable deposit</strong> — reserves a founding spot &
                locks in founding pricing. Fully refundable, anytime — no questions asked.
              </div>
            </div>

            {error && <div className="modal-error">{error}</div>}

            <button className="btn-primary" type="submit" disabled={loading}>
              {busy === "deposit" ? "Starting secure checkout…" : "Reserve founding spot · S$20"}
              {busy !== "deposit" && <ArrowIcon />}
            </button>

            <button className="btn-text" type="button" onClick={joinWaitlist} disabled={loading}>
              {busy === "waitlist" ? "Joining…" : "or just join the waitlist →"}
            </button>

            <div className="modal-foot">
              Secure checkout by Stripe · fully refundable · launching soon
            </div>
          </form>
        ) : mode === "success-deposit" ? (
          <div className="modal-success">
            <div className="success-ring">
              <svg width="30" height="30" viewBox="0 0 30 30" fill="none">
                <path d="M7 15.5 12.5 21 23 9" stroke="currentColor" strokeWidth="2.6"
                      strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <div className="modal-eyebrow">Founding member</div>
            <h2>Spot reserved.</h2>
            <p className="lede">
              Your S$20 deposit is in — fully refundable, anytime. A confirmation
              is on its way to your inbox. You're officially one of Slyck's founding users.
            </p>
            <button className="btn-primary" onClick={onClose} type="button">
              Done
            </button>
          </div>
        ) : (
          <div className="modal-success">
            <div className="success-ring">
              <svg width="30" height="30" viewBox="0 0 30 30" fill="none">
                <path d="M7 15.5 12.5 21 23 9" stroke="currentColor" strokeWidth="2.6"
                      strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <div className="modal-eyebrow">You're on the list</div>
            <h2>You're on the list.</h2>
            <p className="lede">
              {emailed ? (
                <>
                  We sent a confirmation to{" "}
                  <strong style={{ color: "var(--ink)" }}>{email.trim()}</strong>.{" "}
                  You'll be among the first to cash out when Slyck opens.
                </>
              ) : (
                <>
                  You're on the list — we'll email{" "}
                  <strong style={{ color: "var(--ink)" }}>{email.trim()}</strong>{" "}
                  the moment early access opens.
                </>
              )}
            </p>
            {error && <div className="modal-error">{error}</div>}
            <button className="btn-text-strong" type="button" onClick={reserveDeposit} disabled={loading}>
              {busy === "deposit" ? "Starting secure checkout…" : "Lock in a founding spot · S$20 →"}
            </button>
            <button className="btn-primary" onClick={onClose} type="button">
              Done
            </button>
          </div>
        )}
      </div>
    </div>
  );
}

/* ---------------- Hero copy ---------------- */
function HeroCopy({ onOpen }) {
  const armMelt = () => { if (window.__slyckMelt) window.__slyckMelt(); };
  return (
    <div className="hero-copy">
      <div className="eyebrow">Get paid onchain</div>
      <h1 className="headline">
        Frozen value,<br /><span className="flow">set free.</span>
      </h1>
      <p className="subhead">
        Slyck turns the stablecoins you earn into spendable local money — instantly.
        Clean invoices, real records, the best cash-out rate. Built for people who
        get paid onchain.
      </p>
      <div className="cta-row">
        <button className="btn-primary" onClick={onOpen} onMouseEnter={armMelt} onFocus={armMelt}>
          Reserve early access
          <ArrowIcon />
        </button>
        <div className="trust-line">
          Free to join · refundable deposit holds your spot · launching soon
        </div>
      </div>
    </div>
  );
}

function App() {
  const [modal, setModal] = useState(false);
  const [seedMode, setSeedMode] = useState("form");
  const [cameFromCancel, setCameFromCancel] = useState(false);
  const refTag = useRef(readRef()).current;
  const HeroScene = window.HeroScene;

  // Handle return from Stripe Checkout (?status=success|cancel), then clean the URL.
  useEffect(() => {
    let status = null;
    try {
      status = new URLSearchParams(window.location.search).get("status");
    } catch {
      /* ignore */
    }
    if (status === "success") {
      setSeedMode("success-deposit");
      setModal(true);
    } else if (status === "cancel") {
      setSeedMode("form");
      setCameFromCancel(true);
      setModal(true);
    }
    if (status) {
      window.history.replaceState({}, "", window.location.pathname);
    }
  }, []);

  const openFresh = () => {
    setSeedMode("form");
    setCameFromCancel(false);
    setModal(true);
  };

  return (
    <React.Fragment>
      <Nav />
      <main className="hero container">
        <div className="hero-grid">
          <HeroCopy onOpen={openFresh} />
          <HeroScene />
        </div>
      </main>
      <WaitlistModal
        open={modal}
        seedMode={seedMode}
        refTag={refTag}
        cameFromCancel={cameFromCancel}
        onClose={() => setModal(false)}
      />
    </React.Fragment>
  );
}

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