/* Registration.jsx — Participant registration form (PPR Phila form digital intake).
   Loads signature_pad from CDN on demand for the 4 waiver signatures. */

const SIG_LIB_URL = "https://cdn.jsdelivr.net/npm/signature_pad@4/dist/signature_pad.umd.min.js";

function loadSigPad() {
  if (window.SignaturePad) return Promise.resolve(window.SignaturePad);
  return new Promise((resolve, reject) => {
    const s = document.createElement("script");
    s.src = SIG_LIB_URL;
    s.async = true;
    s.onload = () => resolve(window.SignaturePad);
    s.onerror = () => reject(new Error("signature_pad_failed_to_load"));
    document.head.appendChild(s);
  });
}

const FACILITIES = [
  "", "Athletic Recreation Center", "Hawthorne Cultural Center",
  "Holmesburg Recreation Center", "Kingsessing Recreation Center",
  "Kendrick Recreation Center", "Venice Island Performing Arts Center",
  "Other"
];
const GRADES = ["", "K", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th"];
const SHIRT_OPTS = [
  ["", "—"], ["cs", "Child's small"], ["cm", "Child's medium"], ["cl", "Child's large"],
  ["as", "Adult small"], ["am", "Adult medium"], ["al", "Adult large"], ["axl", "Adult XL"], ["other", "Other (specify)"]
];
const RACES = [
  ["ai_an", "American Indian or Alaska Native"], ["asian", "Asian"],
  ["black", "Black or African American"], ["hispanic", "Hispanic or Latino"],
  ["mena", "Middle Eastern or North African"], ["nh_pi", "Native Hawaiian or Pacific Islander"],
  ["white", "White"]
];
// CR #144: Dismissal + Release stay required (the city's liability waivers).
// Emergency Clause + Media Release are optional now per JJ -- some families
// want to skip the media release without losing the rest of the form.
const WAIVERS = [
  { key: "dismissal", title: "Dismissal",                     required: true,  body: "By signing below, I acknowledge that it is my and my child's responsibility to arrange transport home." },
  { key: "release",   title: "Release & Assumption of Risk",  required: true,  body: "I grant permission for my child/ward to attend the program and participate in any and all of its activities, including fieldtrips. I release the City of Philadelphia from all liabilities in case of an injury or illness suffered by the above child resulting from participating in the Program. I voluntarily assume all risks of loss, damage and all injuries that may be sustained by myself and/or my minor child/ward." },
  { key: "emergency", title: "Emergency Clause",              required: false, body: "In the event that my minor child suffers an injury or illness that requires immediate medical attention, I/my minor child will be taken to the nearest hospital. No employee, official, agent or representative of the City will be held responsible for injuries or damages arising from such emergency medical treatment." },
  { key: "media",     title: "Media Release",                 required: false, body: "I authorize, without compensation, the use by the City of my or my minor child/ward's image and/or voice recordings during the Program. This includes permission to reproduce, publicize, broadcast or display visual images or voice recordings, with or without my name, throughout the world, in perpetuity." }
];

function ParticipantRegistrationPage() {
  const blank = {
    facility: "", facility_other: "", program: "", season_year: "Summer 2026",
    participant_name: "", date_of_birth: "", age: "",
    address: "", city: "Philadelphia", state: "PA", zip: "",
    primary_language: "English", gender: "",
    race: {}, home_phone: "", cell_phone: "", email: "",
    school: "", grade: "", shirt_size: "", shirt_size_other: "",
    contacts: [{ name: "", relationship: "", email: "", phone: "", caregiver: true, emergency_contact: false, authorized_pickup: false }],
    staff_alerts: ""
  };
  const [data, setData] = React.useState(blank);
  const [submitted, setSubmitted] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState("");

  // Signature pads — one per waiver. Refs to the canvases + sigpad instances.
  const canvasRefs = React.useRef({});
  const padsRef = React.useRef({});
  const [sigMeta, setSigMeta] = React.useState(() =>
    Object.fromEntries(WAIVERS.map(w => [w.key, { relationship: "", date: new Date().toISOString().slice(0, 10) }]))
  );

  React.useEffect(() => {
    let cancelled = false;
    loadSigPad().then(SignaturePad => {
      if (cancelled) return;
      WAIVERS.forEach(w => {
        const canvas = canvasRefs.current[w.key];
        if (!canvas || padsRef.current[w.key]) return;
        // High-DPI prep
        const ratio = Math.max(window.devicePixelRatio || 1, 1);
        canvas.width = canvas.offsetWidth * ratio;
        canvas.height = canvas.offsetHeight * ratio;
        canvas.getContext("2d").scale(ratio, ratio);
        padsRef.current[w.key] = new SignaturePad(canvas, {
          backgroundColor: "rgba(255,255,255,0)",
          penColor: "#2A1820"
        });
      });
    }).catch(() => setError("Couldn't load signature pad — please refresh and try again."));
    return () => { cancelled = true; };
  }, []);

  const update = (k, v) => setData(d => ({ ...d, [k]: v }));
  const updateRace = (k, v) => setData(d => ({ ...d, race: { ...d.race, [k]: v } }));
  const updateContact = (i, k, v) => setData(d => {
    const next = d.contacts.slice();
    next[i] = { ...next[i], [k]: v };
    return { ...d, contacts: next };
  });
  const addContact = () => setData(d => ({
    ...d,
    contacts: d.contacts.length >= 4 ? d.contacts : [...d.contacts, {
      name: "", relationship: "", email: "", phone: "",
      caregiver: false, emergency_contact: false, authorized_pickup: false
    }]
  }));
  const clearSig = (key) => padsRef.current[key]?.clear();

  const onSubmit = async (e) => {
    e.preventDefault();
    setError("");
    // CR #276: belt-and-braces last-name check. The HTML5 pattern on the field
    // catches the same case at the browser level, but if a user pastes a value
    // that loses its second token after trim, we surface a clear error here
    // rather than letting the server reject.
    const nameTokens = String(data.participant_name || "").trim().split(/\s+/).filter(Boolean);
    if (nameTokens.length < 2) {
      setError("Please enter both a first and last name for the participant.");
      return;
    }
    // Auto-derive age if missing
    let age = data.age;
    if (!age && data.date_of_birth) {
      const dob = new Date(data.date_of_birth);
      if (!isNaN(dob)) {
        const today = new Date();
        let a = today.getFullYear() - dob.getFullYear();
        if (today.getMonth() < dob.getMonth() || (today.getMonth() === dob.getMonth() && today.getDate() < dob.getDate())) a -= 1;
        if (a >= 0) age = a;
      }
    }

    // Capture each signature as PNG data URL. Required waivers must be signed;
    // optional ones (Media Release, Emergency Clause per CR #144) are sent
    // through as empty strings when blank.
    const signatures = {};
    for (const w of WAIVERS) {
      const pad = padsRef.current[w.key];
      const empty = !pad || pad.isEmpty();
      if (empty && w.required) {
        setError(`Please sign the ${w.title} waiver before submitting.`);
        return;
      }
      signatures[w.key] = empty ? "" : pad.toDataURL("image/png");
    }

    setSubmitting(true);
    try {
      const res = await fetch("/api/registration", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ...data, age, signatures, signature_meta: sigMeta })
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok || !json.ok) throw new Error((json.details && json.details.join(", ")) || json.error || `error_${res.status}`);
      setSubmitted({ ref: json.ref, emailStatus: json.email_status, pdfBase64: json.pdf_base64, pdfFilename: json.pdf_filename });
    } catch (err) {
      setError(`Couldn't submit: ${err.message}. Try again, or email Joseph.J.Pospiech@phila.gov.`);
    } finally {
      setSubmitting(false);
    }
  };

  if (submitted) {
    // CR #261: offer the parent a download of the filled PDF for their
    // records. Server returns it base64-encoded so we decode + blob + click.
    const downloadPdf = () => {
      if (!submitted.pdfBase64) return;
      try {
        const bytes = Uint8Array.from(atob(submitted.pdfBase64), c => c.charCodeAt(0));
        const blob = new Blob([bytes], { type: "application/pdf" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = submitted.pdfFilename || `participant-registration-${submitted.ref}.pdf`;
        document.body.appendChild(a);
        a.click();
        a.remove();
        setTimeout(() => URL.revokeObjectURL(url), 10000);
      } catch (_) { /* swallow; the email copy is the canonical record */ }
    };
    return <ConfirmationView
      title="Registration submitted."
      body={`Reference: ${submitted.ref}. A signed copy of the form has been emailed to the program coordinator. Save this reference for your records.`}
      ctaLabel="Submit another registration"
      onCta={() => { setSubmitted(null); setData(blank); padsRef.current = {}; }}
      secondary={submitted.pdfBase64 ? { label: "Download for your records ↓", onClick: downloadPdf } : null}
    />;
  }

  // CR #249: clamp DOB to (today - 100y) ≤ dob ≤ (today - 1y) so the browser
  // blocks submit if a parent tries to leave it as today's date or enters
  // something nonsensical.
  const todayIso = new Date().toISOString().slice(0, 10);
  const dobMin = (() => { const d = new Date(); d.setFullYear(d.getFullYear() - 100); return d.toISOString().slice(0, 10); })();
  const dobMax = (() => { const d = new Date(); d.setFullYear(d.getFullYear() - 1); return d.toISOString().slice(0, 10); })();

  return (
    <div>
      <FormHero
        eyebrow="Participant Registration"
        title={<>Register for<br/>a program.</>}
        body="Fill out and sign the City of Philadelphia Parks & Recreation participant registration form below. A signed copy is emailed to the program coordinator on submission."
        bg="var(--c-cream-deep)"
      />
      <section className="section">
        <div className="container" style={{ maxWidth: 920 }}>
          <form onSubmit={onSubmit}>

            <FormSection number="01" title="Program & enrollment">
              {data.facility === "Other" ? (
                /* CR #225: when Other is picked, the "Please specify"
                   box should appear ABOVE the Program name box. Break
                   the row apart so the order reads facility ->
                   please-specify -> program. */
                <>
                  <Field label="Facility" type="select" options={FACILITIES} value={data.facility} onChange={v => update("facility", v)} required />
                  <Field
                    label="Please specify the recreation center or playground"
                    value={data.facility_other}
                    onChange={v => update("facility_other", v)}
                    required
                  />
                  <Field label="Program name" value={data.program} onChange={v => update("program", v)} />
                </>
              ) : (
                <Row>
                  <Field label="Facility" type="select" options={FACILITIES} value={data.facility} onChange={v => update("facility", v)} required />
                  <Field label="Program name" value={data.program} onChange={v => update("program", v)} />
                </Row>
              )}
              <Field label="Season / Year" value={data.season_year} onChange={v => update("season_year", v)} />
            </FormSection>

            <FormSection number="02" title="Participant">
              <Row>
                <Field
                  label="First and last name"
                  value={data.participant_name}
                  onChange={v => update("participant_name", v)}
                  required
                  pattern="^\s*\S+\s+\S.*$"
                  title="Please enter both a first and last name."
                />
                <Field label="Date of birth" type="date" value={data.date_of_birth} onChange={v => update("date_of_birth", v)} required min={dobMin} max={dobMax} title={`Must be between ${dobMin} and ${dobMax}`} />
              </Row>
              <Row>
                <Field label="Residential address" value={data.address} onChange={v => update("address", v)} required />
                <Field label="City" value={data.city} onChange={v => update("city", v)} />
              </Row>
              <Row>
                <Field label="State" value={data.state} onChange={v => update("state", v)} />
                <Field label="ZIP code" value={data.zip} onChange={v => update("zip", v)} required inputMode="numeric" maxLength={5} pattern="\d{5}" title="5-digit ZIP code" placeholder="19102" />
              </Row>
              <Row>
                <Field label="Primary language at home" value={data.primary_language} onChange={v => update("primary_language", v)} />
                <Field label="Gender" value={data.gender} onChange={v => update("gender", v)} />
              </Row>

              <CheckboxGrid label="Race (check all that apply)" items={RACES} state={data.race} onToggle={(k, v) => updateRace(k, v)} />

              <Row>
                <Field
                  label="Home phone"
                  type="tel"
                  value={data.home_phone}
                  onChange={v => update("home_phone", v)}
                  placeholder="215-555-0100"
                  inputMode="tel"
                  maxLength={12}
                  pattern="\d{3}-\d{3}-\d{4}"
                  title="Use XXX-XXX-XXXX format"
                  formatter={window.formatPhone}
                />
                <Field
                  label="Cell phone"
                  type="tel"
                  value={data.cell_phone}
                  onChange={v => update("cell_phone", v)}
                  placeholder="215-555-0100"
                  inputMode="tel"
                  maxLength={12}
                  pattern="\d{3}-\d{3}-\d{4}"
                  title="Use XXX-XXX-XXXX format"
                  formatter={window.formatPhone}
                />
              </Row>
              <Field label="Email" type="email" value={data.email} onChange={v => update("email", v)} />
              <Row>
                <Field label="School name" value={data.school} onChange={v => update("school", v)} />
                <Field label="Grade" type="select" options={GRADES} value={data.grade} onChange={v => update("grade", v)} />
              </Row>
              <Row>
                <Field label="Shirt size" type="select"
                  options={SHIRT_OPTS.map(o => o[0])}
                  optionLabels={SHIRT_OPTS.map(o => o[1])}
                  value={data.shirt_size}
                  onChange={v => update("shirt_size", v)} />
                {data.shirt_size === "other" && (
                  <Field label="Other shirt size" value={data.shirt_size_other} onChange={v => update("shirt_size_other", v)} />
                )}
              </Row>
            </FormSection>

            <FormSection number="03" title="Parent / guardian / emergency contacts">
              {data.contacts.map((c, i) => (
                <div key={i} style={{ border: "2px solid var(--c-ink-soft)", borderRadius: 12, padding: 18, background: "var(--c-paper)" }}>
                  <div style={{ fontFamily: "var(--f-mono)", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--c-ink-soft)", marginBottom: 10 }}>
                    Contact {i + 1}{i === 0 ? " · primary" : ""}
                  </div>
                  <Row>
                    <Field label="First and last name" value={c.name} onChange={v => updateContact(i, "name", v)} required={i === 0} />
                    <Field label="Relationship" value={c.relationship} onChange={v => updateContact(i, "relationship", v)} required={i === 0} />
                  </Row>
                  <Row>
                    <Field label="Email" type="email" value={c.email} onChange={v => updateContact(i, "email", v)} required={i === 0} />
                    <Field
                      label="Phone"
                      type="tel"
                      value={c.phone}
                      onChange={v => updateContact(i, "phone", v)}
                      required={i === 0}
                      placeholder="215-555-0100"
                      inputMode="tel"
                      maxLength={12}
                      pattern="\d{3}-\d{3}-\d{4}"
                      title="Use XXX-XXX-XXXX format"
                      formatter={window.formatPhone}
                    />
                  </Row>
                  <div style={{ display: "flex", gap: 18, flexWrap: "wrap", marginTop: 8 }}>
                    <Checkbox label="Caregiver" checked={c.caregiver} onChange={v => updateContact(i, "caregiver", v)} />
                    <Checkbox label="Emergency contact" checked={c.emergency_contact} onChange={v => updateContact(i, "emergency_contact", v)} />
                    <Checkbox label="Authorized for pick up" checked={c.authorized_pickup} onChange={v => updateContact(i, "authorized_pickup", v)} />
                  </div>
                </div>
              ))}
              {data.contacts.length < 4 && (
                <button type="button" onClick={addContact} className="btn small ghost" style={{ alignSelf: "flex-start" }}>
                  + Add another contact
                </button>
              )}
            </FormSection>

            <FormSection number="04" title="Waivers & signatures">
              <p style={{ fontSize: 14, color: "var(--c-ink-soft)", marginTop: -4, lineHeight: 1.55 }}>
                A parent or legal guardian signs the Dismissal and Release waivers below.
                Emergency Clause and Media Release are optional &mdash; sign them only if
                you agree. Use a finger or stylus on touch devices, or click and drag
                with a mouse.
              </p>
              {WAIVERS.map(w => (
                <div key={w.key} style={{ border: "2px solid var(--c-ink)", borderRadius: 14, padding: 20, background: "var(--c-cream-deep)" }}>
                  <div className="display" style={{ fontSize: 22, marginBottom: 8 }}>
                    {w.title}
                    {!w.required && (
                      <span style={{ fontFamily: "var(--f-mono)", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--c-ink-soft)", marginLeft: 12, fontWeight: 400 }}>
                        Optional
                      </span>
                    )}
                  </div>
                  <p style={{ fontSize: 13, color: "var(--c-ink)", lineHeight: 1.55, marginBottom: 14 }}>{w.body}</p>
                  <Row>
                    <Field label="Relationship to participant" value={sigMeta[w.key].relationship}
                      onChange={v => setSigMeta(s => ({ ...s, [w.key]: { ...s[w.key], relationship: v } }))} />
                    <Field label="Date" type="date" value={sigMeta[w.key].date}
                      onChange={v => setSigMeta(s => ({ ...s, [w.key]: { ...s[w.key], date: v } }))} />
                  </Row>
                  <div style={{ marginTop: 12 }}>
                    <div style={{ fontFamily: "var(--f-mono)", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--c-ink-soft)", marginBottom: 6 }}>
                      Signature of parent or legal guardian
                    </div>
                    <canvas
                      ref={el => { canvasRefs.current[w.key] = el; }}
                      style={{ width: "100%", height: 140, display: "block", border: "2px solid var(--c-ink)", borderRadius: 10, background: "var(--c-paper)", touchAction: "none" }}
                    />
                    <button type="button" onClick={() => clearSig(w.key)} className="btn small ghost" style={{ marginTop: 8 }}>
                      Clear signature
                    </button>
                  </div>
                </div>
              ))}
            </FormSection>

            <FormSection number="05" title="Anything staff should know?">
              <Field label="Behavioral, dietary, medical, or transit-assistance notes (optional)"
                type="textarea" value={data.staff_alerts} onChange={v => update("staff_alerts", v)} />
            </FormSection>

            {error && (
              <div style={{ marginTop: 24, padding: 14, background: "#FBE4DC", border: "2px solid var(--c-primary)", borderRadius: 12, fontSize: 14, color: "var(--c-ink)" }}>
                {error}
              </div>
            )}

            <div className="card" style={{ background: "var(--c-cream-deep)", marginTop: 32, display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 14 }}>
              <div>
                <div className="display" style={{ fontSize: 20 }}>Submit registration</div>
                <div style={{ fontSize: 13, color: "var(--c-ink-soft)" }}>A signed copy is emailed to the program coordinator on submit.</div>
              </div>
              <button type="submit" className="btn" disabled={submitting}>
                {submitting ? "Submitting…" : "Submit registration →"}
              </button>
            </div>
          </form>
        </div>
      </section>
    </div>
  );
}

function CheckboxGrid({ label, items, state, onToggle }) {
  return (
    <div>
      <div style={{ fontFamily: "var(--f-mono)", fontSize: 11, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--c-ink-soft)", marginBottom: 8 }}>{label}</div>
      <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: 8 }}>
        {items.map(([k, lbl]) => (
          <Checkbox key={k} label={lbl} checked={!!state[k]} onChange={v => onToggle(k, v)} />
        ))}
      </div>
    </div>
  );
}

function Checkbox({ label, checked, onChange }) {
  return (
    <label style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 14, cursor: "pointer", userSelect: "none" }}>
      <input type="checkbox" checked={!!checked} onChange={e => onChange(e.target.checked)} style={{ width: 18, height: 18, accentColor: "var(--c-primary)" }} />
      {label}
    </label>
  );
}

Object.assign(window, { ParticipantRegistrationPage });
