// rsvp-form.jsx — inline RSVP form for the public invite page.
// Exposes <RsvpForm /> on the global window so invite.jsx can use it.

const { useEffect, useState, useRef, useMemo } = React;

// ─── tiny fetch helper ────────────────────────────────────────────────
async function apiPost(path, body) {
  const r = await fetch(path, {
    method: 'POST',
    headers: { 'content-type': 'application/json' },
    body: JSON.stringify(body),
  });
  const data = await r.json().catch(() => ({}));
  return { ok: r.ok, status: r.status, data };
}

// ─── presentational atoms ─────────────────────────────────────────────
function Field({ label, children, hint }) {
  return (
    <div className="field">
      <div className="field-label">{label}</div>
      {children}
      {hint && <div className="field-hint">{hint}</div>}
    </div>
  );
}

function Seg({ value, onChange, name }) {
  return (
    <div className="seg" role="radiogroup" aria-label={name}>
      <label>
        <input
          type="radio"
          name={name}
          checked={value === 1}
          onChange={() => onChange(1)}
        />
        <span>Joining</span>
      </label>
      <label>
        <input
          type="radio"
          name={name}
          checked={value === 0}
          onChange={() => onChange(0)}
        />
        <span>Can't make it</span>
      </label>
    </div>
  );
}

// ─── per-attendee block ───────────────────────────────────────────────
function AttendeeBlock({ a, onChange, locked }) {
  const editable = !locked;
  return (
    <div className="attendee">
      {a.is_plus_one && !a.display_name ? (
        <Field label="Plus-one name">
          <input
            className="input"
            type="text"
            value={a.display_name || ''}
            disabled={!editable}
            onChange={(e) => onChange({ ...a, display_name: e.target.value })}
            placeholder="Their name"
          />
        </Field>
      ) : (
        <div className="attendee-name">
          {a.display_name || (a.is_plus_one ? 'Plus-one' : 'Attendee')}
        </div>
      )}

      <Field label={a.is_plus_one ? 'Are they joining?' : 'Are you joining?'}>
        <Seg
          name={`att-${a.id || 'new'}`}
          value={a.attending === 1 ? 1 : a.attending === 0 ? 0 : null}
          onChange={editable ? (v) => onChange({ ...a, attending: v }) : () => {}}
        />
      </Field>

      <Field label="Dietary — anything we should know?" hint="Allergies, vegetarian, etc.">
        <textarea
          className="textarea"
          rows={2}
          value={a.dietary || ''}
          disabled={!editable}
          onChange={(e) => onChange({ ...a, dietary: e.target.value })}
          placeholder="none"
        />
      </Field>

      <Field label="Song request — optional">
        <input
          className="input"
          type="text"
          value={a.song_request || ''}
          disabled={!editable}
          onChange={(e) => onChange({ ...a, song_request: e.target.value })}
          placeholder="something to fill the floor"
        />
      </Field>

      <Field label="A note for us — optional">
        <textarea
          className="textarea"
          rows={2}
          value={a.message || ''}
          disabled={!editable}
          onChange={(e) => onChange({ ...a, message: e.target.value })}
          placeholder=""
        />
      </Field>

      <label className="chk">
        <input
          type="checkbox"
          checked={!!a.needs_transport}
          disabled={!editable}
          onChange={(e) => onChange({ ...a, needs_transport: e.target.checked ? 1 : 0 })}
        />
        <span className="chk-text">I'll need a lift home</span>
      </label>
    </div>
  );
}

// ─── the form itself ──────────────────────────────────────────────────
function RsvpForm({ copy }) {
  const initialToken = useMemo(() => {
    const p = new URLSearchParams(window.location.search);
    return (p.get('t') || '').trim().slice(0, 10);
  }, []);

  const [phase, setPhase] = useState(initialToken ? 'enter-token' : 'idle');
  const [token, setToken] = useState(initialToken);
  const [surname, setSurname] = useState('');
  const [error, setError] = useState('');
  const [guest, setGuest] = useState(null);
  const [attendees, setAttendees] = useState([]);
  const [plusOne, setPlusOne] = useState(null); // virtual plus-one row
  const [editReason, setEditReason] = useState('');
  const surnameInputRef = useRef(null);

  // Auto-focus surname when token arrives via URL
  useEffect(() => {
    if (phase === 'enter-token' && initialToken && surnameInputRef.current) {
      surnameInputRef.current.focus();
    }
  }, [phase, initialToken]);

  // ── transitions
  const startReply = () => { setError(''); setPhase('enter-token'); };
  const cancelReply = () => { setError(''); setPhase('idle'); };

  const verify = async (e) => {
    e?.preventDefault?.();
    if (!token || token.length !== 10) { setError('Check the token — it should be 10 characters.'); return; }
    if (!surname.trim()) { setError("We'll need the surname too."); return; }
    setError(''); setPhase('verifying');
    const { ok, status, data } = await apiPost('/api/verify-surname', { token: token.trim(), surname: surname.trim() });
    if (status === 429) { setError("Too many tries — give it a few minutes and try again."); setPhase('enter-token'); return; }
    if (!ok || !data.ok) {
      if (status === 404 || data.error === 'token_not_found') setError("That token doesn't match anything we sent out. Double-check the link.");
      else if (data.error === 'surname_mismatch') setError("That surname doesn't match our records. Try the one we'd have written down.");
      else setError("Something went sideways. Try again in a moment.");
      setPhase('enter-token');
      return;
    }
    // success
    setGuest(data.guest);
    setAttendees(data.attendees || []);
    // virtual plus-one if allowed and no real plus-one row yet
    if (data.guest.plus_one && !(data.attendees || []).some(a => a.is_plus_one)) {
      setPlusOne({ id: null, is_plus_one: 1, display_name: '', attending: null, dietary: '', song_request: '', message: '', needs_transport: 0 });
    } else {
      setPlusOne(null);
    }
    // strip ?t= from URL for screen-share safety
    if (window.location.search.includes('t=')) {
      window.history.replaceState(null, '', window.location.pathname);
    }
    setPhase(data.guest.locked ? 'review' : 'unlocked');
  };

  const updateAttendee = (idx, next) => {
    setAttendees(prev => prev.map((a, i) => i === idx ? next : a));
  };

  const updatePlusOne = (next) => setPlusOne(next);

  const submit = async () => {
    if (!attendees.length && !(plusOne && plusOne.display_name && plusOne.attending != null)) {
      setError("Tell us at least one person's answer.");
      return;
    }
    setError(''); setPhase('submitting');
    const payload = {
      token: token.trim(),
      surname: surname.trim(),
      attendees: [...attendees],
    };
    if (plusOne && (plusOne.display_name || plusOne.attending != null)) {
      payload.attendees.push(plusOne);
    }
    const { ok, status, data } = await apiPost('/api/rsvp', payload);
    if (!ok || !data.ok) {
      if (status === 409 || data.error === 'locked') setError("Your RSVP is locked. Request an edit and we'll unlock it for you.");
      else setError("Something went sideways. Try again in a moment.");
      setPhase('unlocked');
      return;
    }
    setGuest(data.guest);
    setAttendees(data.attendees || []);
    setPlusOne(null);
    setPhase('submitted');
  };

  const requestEdit = async () => {
    setError(''); setPhase('submitting');
    const { ok, data } = await apiPost('/api/rsvp/edit-request', {
      token: token.trim(),
      surname: surname.trim(),
      reason: editReason || undefined,
    });
    if (!ok || !data.ok) {
      setError("Couldn't send the request. Try again in a moment.");
      setPhase('review');
      return;
    }
    setPhase('edit-requested');
  };

  // ── render by phase ──────────────────────────────────────────────────
  if (phase === 'idle') {
    return (
      <button type="button" className="btn" onClick={startReply}>
        {copy.rsvpBtn}
        <span className="arrow"></span>
      </button>
    );
  }

  if (phase === 'enter-token' || phase === 'verifying') {
    return (
      <form className="rsvp-gate" onSubmit={verify}>
        <Field label="Your token">
          <input
            className="input mono"
            type="text"
            inputMode="text"
            autoComplete="off"
            spellCheck="false"
            value={token}
            onChange={(e) => setToken(e.target.value.trim().toLowerCase().slice(0, 10))}
            placeholder="ten characters"
            maxLength={10}
            disabled={phase === 'verifying'}
          />
        </Field>
        <Field label="Surname">
          <input
            ref={surnameInputRef}
            className="input"
            type="text"
            autoComplete="family-name"
            value={surname}
            onChange={(e) => setSurname(e.target.value)}
            placeholder="As we'd have written it down"
            disabled={phase === 'verifying'}
          />
        </Field>
        {error && <div className="form-error">{error}</div>}
        <div className="form-row">
          <button type="submit" className="btn" disabled={phase === 'verifying'}>
            {phase === 'verifying' ? 'Checking…' : 'Continue'}
            <span className="arrow"></span>
          </button>
          <button type="button" className="btn ghost" onClick={cancelReply} disabled={phase === 'verifying'}>
            Cancel
          </button>
        </div>
      </form>
    );
  }

  if (phase === 'unlocked' || phase === 'submitting') {
    const editable = phase === 'unlocked';
    return (
      <div className="rsvp-form">
        <div className="rsvp-hello">
          <span className="rsvp-hello-eyebrow">Hello, {guest.household_name}</span>
        </div>
        {attendees.map((a, i) => (
          <AttendeeBlock key={a.id || `att-${i}`} a={a} onChange={(next) => updateAttendee(i, next)} locked={!editable} />
        ))}
        {plusOne && (
          <AttendeeBlock a={plusOne} onChange={updatePlusOne} locked={!editable} />
        )}
        {error && <div className="form-error">{error}</div>}
        <div className="form-row">
          <button type="button" className="btn" onClick={submit} disabled={!editable}>
            {phase === 'submitting' ? 'Sending…' : 'Send our reply'}
            <span className="arrow"></span>
          </button>
        </div>
      </div>
    );
  }

  if (phase === 'submitted' || phase === 'review') {
    const yes = attendees.filter(a => a.attending === 1);
    const no = attendees.filter(a => a.attending === 0);
    return (
      <div className="rsvp-form">
        <h3 className="rsvp-thanks">
          {phase === 'submitted' ? 'Thank you. We have you down.' : 'You\'ve already replied.'}
        </h3>
        <div className="rsvp-recap">
          <div className="recap-row"><span className="recap-k">Joining</span><span className="recap-v">{yes.length ? yes.map(a => a.display_name).join(', ') : '—'}</span></div>
          <div className="recap-row"><span className="recap-k">Not joining</span><span className="recap-v">{no.length ? no.map(a => a.display_name).join(', ') : '—'}</span></div>
          {attendees.filter(a => a.dietary).map(a => (
            <div className="recap-row" key={`d-${a.id}`}><span className="recap-k">{a.display_name} · dietary</span><span className="recap-v">{a.dietary}</span></div>
          ))}
        </div>
        <Field label="Need to change something? Tell us what.">
          <textarea className="textarea" rows={2} value={editReason} onChange={(e) => setEditReason(e.target.value)} placeholder="optional" />
        </Field>
        {error && <div className="form-error">{error}</div>}
        <button type="button" className="btn ghost" onClick={requestEdit}>
          Request an edit
          <span className="arrow"></span>
        </button>
      </div>
    );
  }

  if (phase === 'edit-requested') {
    return (
      <div className="rsvp-form">
        <h3 className="rsvp-thanks">We'll get back to you shortly.</h3>
        <p className="rsvp-recap-note">We'll review your request and reach out to unlock it.</p>
      </div>
    );
  }

  return null;
}

Object.assign(window, { RsvpForm });
