/* Registration page — captain login + roster editor
   ----------------------------------------------------------------
   Three states, swapped client-side based on whether GET /api/captain/team
   succeeds (which means the session cookie from /api/auth/verify is valid):

     1. Logged out   → email entry form, hits POST /api/auth/request-link
     2. Open roster  → 4-player editor (captain + 3 others), can save / lock
     3. Locked       → read-only summary, "request unlock" mailto

   No client-side routing. Anti-enumeration: the request-link endpoint always
   returns 200 regardless of whether the email is on our captain list.
*/

const STATE = { LOADING: "loading", LOGGED_OUT: "out", OPEN: "open", LOCKED: "locked" };

function fetchJson(url, opts) {
  return fetch(url, { credentials: "same-origin", ...opts }).then(async (r) => {
    if (!r.ok) {
      const err = new Error("http_" + r.status);
      err.status = r.status;
      throw err;
    }
    return r.json();
  });
}

function LoginCard() {
  const [email, setEmail] = React.useState("");
  const [submitting, setSubmitting] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  const [error, setError] = React.useState(null);

  const onSubmit = async (e) => {
    e.preventDefault();
    if (submitting) return;
    setSubmitting(true);
    setError(null);
    try {
      await fetchJson("/api/auth/request-link", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: email.trim() }),
      });
      setSent(true);
    } catch (err) {
      if (err.status === 429) {
        setError("Too many requests from this device. Wait an hour and try again.");
      } else {
        setError("Something went wrong. Try again in a minute.");
      }
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="auth-page">
      <div className="auth-card">
        <div className="eyebrow">Captain Sign-in</div>
        <h1>Register your foursome</h1>
        <p>
          Team captains: enter the email you gave the committee. We'll send you a one-time link to fill in your roster. Links expire in 1 hour.
        </p>

        {sent ? (
          <div className="auth-status is-success" role="status">
            <strong>Check your inbox.</strong>{" "}
            If <em>{email.trim() || "that email"}</em> is on our captain list, a sign-in link is on its way. Don't see it? Check your spam folder, or email{" "}
            <a href={`mailto:${SITE.contact}`}>{SITE.contact}</a>.
          </div>
        ) : (
          <form onSubmit={onSubmit} noValidate>
            <div className="field">
              <label className="field-label" htmlFor="email">Captain email</label>
              <input
                id="email"
                type="email"
                inputMode="email"
                autoComplete="email"
                className={`input ${error ? "is-error" : ""}`}
                placeholder="you@example.com"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                required
              />
              {error && <div className="field-error">{error}</div>}
            </div>
            <button
              type="submit"
              className={`btn btn-red ${submitting || !email.trim() ? "is-disabled" : ""}`}
              disabled={submitting || !email.trim()}
              style={{ width: "100%" }}
            >
              {submitting ? "Sending…" : "Email me a sign-in link →"}
            </button>
          </form>
        )}
      </div>
      <div className="auth-footer">
        Think you should be on the captain list?{" "}
        <a href={`mailto:${SITE.contact}?subject=${encodeURIComponent("Add me as a team captain")}`}>
          Email the committee
        </a>{" "}
        and we'll get you set up.
      </div>
    </div>
  );
}

function RosterEditor({ team, onUpdated, onLocked }) {
  const [captain, setCaptain] = React.useState({
    captain_name: team.captain_name || "",
    captain_phone: team.captain_phone || "",
  });
  const initialPlayers = [2, 3, 4].map((pos) => {
    const existing = (team.players || []).find((p) => p.position === pos);
    return {
      position: pos,
      full_name: existing ? existing.full_name || "" : "",
      email: existing ? existing.email || "" : "",
    };
  });
  const [players, setPlayers] = React.useState(initialPlayers);
  const [saving, setSaving] = React.useState(false);
  const [locking, setLocking] = React.useState(false);
  const [status, setStatus] = React.useState(null);

  const setPlayer = (idx, field, value) => {
    setPlayers((prev) => {
      const next = prev.slice();
      next[idx] = { ...next[idx], [field]: value };
      return next;
    });
  };

  const save = async (e) => {
    e && e.preventDefault();
    if (saving) return;
    setSaving(true);
    setStatus(null);
    try {
      const updated = await fetchJson("/api/captain/team", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          captain_name: captain.captain_name.trim(),
          captain_phone: captain.captain_phone.trim(),
          players: players.map((p) => ({
            position: p.position,
            full_name: p.full_name.trim(),
            email: p.email.trim(),
          })),
        }),
      });
      setStatus({ kind: "success", text: "Roster saved." });
      onUpdated && onUpdated(updated);
    } catch (err) {
      setStatus({ kind: "error", text: "Couldn't save. Check your connection and try again." });
    } finally {
      setSaving(false);
    }
  };

  const lock = async () => {
    if (locking) return;
    const ok = window.confirm(
      "Lock the roster? After this, you'll need to email the committee to make changes."
    );
    if (!ok) return;
    setLocking(true);
    setStatus(null);
    try {
      const updated = await fetchJson("/api/captain/team/lock", { method: "POST" });
      setStatus({ kind: "success", text: "Roster locked." });
      onLocked && onLocked(updated);
    } catch (err) {
      setStatus({ kind: "error", text: "Couldn't lock. Try again." });
    } finally {
      setLocking(false);
    }
  };

  return (
    <form onSubmit={save}>
      <section className="roster-section">
        <h2>01 · Captain</h2>
        <p className="section-help">
          You're the day-of contact for {team.team_name}. Make sure your phone number is one we can reach you on tournament morning.
        </p>
        <div className="player-row captain">
          <div className="player-tag">Captain (you)</div>
          <div className="field">
            <label className="field-label" htmlFor="cap-name">Full name</label>
            <input
              id="cap-name"
              className="input"
              value={captain.captain_name}
              onChange={(e) => setCaptain({ ...captain, captain_name: e.target.value })}
              autoComplete="name"
              required
            />
          </div>
          <div className="field" style={{ marginBottom: 0 }}>
            <label className="field-label" htmlFor="cap-phone">Phone (day-of texts)</label>
            <input
              id="cap-phone"
              type="tel"
              inputMode="tel"
              autoComplete="tel"
              className="input"
              placeholder="(607) 555-0100"
              value={captain.captain_phone}
              onChange={(e) => setCaptain({ ...captain, captain_phone: e.target.value })}
            />
          </div>
          <div className="field-help" style={{ marginTop: 8 }}>
            Signed in as <strong>{team.captain_email}</strong>
          </div>
        </div>
      </section>

      <section className="roster-section">
        <h2>02 · Your other 3 players</h2>
        <p className="section-help">
          Just a name and email for each. We'll send them event details directly. You can come back and update this any time before the roster is locked.
        </p>
        <div className="roster-grid">
          {players.map((p, idx) => (
            <div className="player-row" key={p.position}>
              <div className="player-tag">Player {p.position}</div>
              <div className="field">
                <label className="field-label" htmlFor={`p${p.position}-name`}>Full name</label>
                <input
                  id={`p${p.position}-name`}
                  className="input"
                  value={p.full_name}
                  onChange={(e) => setPlayer(idx, "full_name", e.target.value)}
                  autoComplete="off"
                />
              </div>
              <div className="field" style={{ marginBottom: 0 }}>
                <label className="field-label" htmlFor={`p${p.position}-email`}>Email</label>
                <input
                  id={`p${p.position}-email`}
                  type="email"
                  inputMode="email"
                  className="input"
                  value={p.email}
                  onChange={(e) => setPlayer(idx, "email", e.target.value)}
                  autoComplete="off"
                />
              </div>
            </div>
          ))}
        </div>
      </section>

      {status && (
        <div
          className={`auth-status ${status.kind === "success" ? "is-success" : "is-error"}`}
          role="status"
          style={{ marginBottom: 16 }}
        >
          {status.text}
        </div>
      )}

      <div className="roster-actions">
        <button type="submit" className={`btn btn-navy ${saving ? "is-disabled" : ""}`} disabled={saving}>
          {saving ? "Saving…" : "Save roster"}
        </button>
        <button type="button" className={`btn btn-gold ${locking ? "is-disabled" : ""}`} disabled={locking} onClick={lock}>
          {locking ? "Locking…" : "Lock roster"}
        </button>
      </div>
    </form>
  );
}

function LockedRoster({ team }) {
  const captainPlayer = {
    position: 1,
    full_name: team.captain_name,
    email: team.captain_email,
    isCaptain: true,
  };
  const others = [2, 3, 4].map(
    (pos) =>
      (team.players || []).find((p) => p.position === pos) || {
        position: pos,
        full_name: null,
        email: null,
      }
  );
  const everyone = [captainPlayer, ...others];
  const lockedAt = team.locked_at ? new Date(team.locked_at) : null;

  return (
    <>
      <div className="locked-banner">
        <strong>Roster locked.</strong> {lockedAt ? `Locked ${lockedAt.toLocaleString()}.` : ""}{" "}
        Need to swap a player? Email the committee at{" "}
        <a href={`mailto:${SITE.contact}?subject=${encodeURIComponent("Roster change for " + team.team_name)}`}>
          {SITE.contact}
        </a>.
      </div>
      <section className="roster-section">
        <h2>{team.team_name}</h2>
        <p className="section-help">
          {team.flight ? `Flight ${team.flight}.` : "Flight assignment to come."} See you on the course.
        </p>
        <div className="roster-grid">
          {everyone.map((p) => (
            <div className={`player-row ${p.isCaptain ? "captain" : ""}`} key={p.position}>
              <div className="player-tag">{p.isCaptain ? "Captain" : `Player ${p.position}`}</div>
              <div style={{ fontWeight: 600 }}>{p.full_name || <em style={{ color: "var(--ink-3)" }}>Not provided</em>}</div>
              <div style={{ fontSize: 14, color: "var(--ink-3)" }}>
                {p.email || <em>—</em>}
              </div>
            </div>
          ))}
        </div>
      </section>
    </>
  );
}

function RegistrationApp() {
  const [state, setState] = React.useState(STATE.LOADING);
  const [team, setTeam] = React.useState(null);

  const load = React.useCallback(async () => {
    try {
      const t = await fetchJson("/api/captain/team");
      setTeam(t);
      setState(t.locked_at ? STATE.LOCKED : STATE.OPEN);
    } catch (err) {
      if (err.status === 401) {
        setState(STATE.LOGGED_OUT);
      } else {
        // Other errors fall through to logged out so the user can retry.
        console.warn("registration: load failed", err);
        setState(STATE.LOGGED_OUT);
      }
    }
  }, []);

  React.useEffect(() => {
    load();
  }, [load]);

  if (state === STATE.LOADING) {
    return (
      <>
        <Topbar active="register" />
        <div className="auth-page">
          <div className="auth-card" style={{ textAlign: "center" }}>
            <div className="label">Loading…</div>
          </div>
        </div>
      </>
    );
  }

  if (state === STATE.LOGGED_OUT) {
    return (
      <>
        <Topbar active="register" />
        <LoginCard />
        <Footer />
      </>
    );
  }

  return (
    <>
      <Topbar active="register" />
      <main className="roster-page">
        <div className="roster-shell">
          <div className="roster-head">
            <div>
              <div className="label">Team Registration</div>
              <h1>{team.team_name}</h1>
            </div>
            <div className="signed-as">
              Signed in as <strong>{team.captain_email}</strong>
              {" · "}
              <a
                href="#"
                onClick={(e) => {
                  e.preventDefault();
                  fetch("/api/auth/logout", { method: "POST", credentials: "same-origin" })
                    .finally(() => window.location.reload());
                }}
              >
                Sign out
              </a>
            </div>
          </div>

          {state === STATE.LOCKED ? (
            <LockedRoster team={team} />
          ) : (
            <RosterEditor
              team={team}
              onUpdated={(t) => {
                setTeam(t);
                setState(t.locked_at ? STATE.LOCKED : STATE.OPEN);
              }}
              onLocked={(t) => {
                setTeam(t);
                setState(STATE.LOCKED);
              }}
            />
          )}
        </div>
      </main>
      <Footer />
    </>
  );
}

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