/* global React, Icon, Button, Field, euro, buildOrder, FEEST,
   StepGegevens, StepKinderen, StepEten, EMAIL_RE */
/* ============================================================
   Bestelling aanpassen — beveiligde-link flow
   - alleen bijbestellen (verlagen kan niet)
   - annuleren met bevestiging
   - na de deadline: alleen bekijken
   ============================================================ */
const { useState: useStateMg, useMemo: useMemoMg } = React;

const ORDERS_KEY = window.FEEST_ORDERS_KEY;
const EMAIL_RE_MG = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function genToken() {
  const a = new Uint8Array(24);
  if (window.crypto && window.crypto.getRandomValues) window.crypto.getRandomValues(a);
  else for (let i = 0; i < a.length; i++) a[i] = Math.floor(Math.random() * 256);
  let s = "";
  a.forEach((b) => (s += String.fromCharCode(b)));
  return btoa(s).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
/* ============================================================
   Bestellingen lopen nu via de server-API (Neon Postgres).
   De leesbare token zit alleen in de aanpas-link; de server bewaart
   er enkel een hash van. Verlagen/annuleren wordt server-side gecheckt.
   ============================================================ */
async function apiJSON(url, opts) {
  const r = await fetch(url, Object.assign({ headers: { "Content-Type": "application/json" } }, opts || {}));
  if (r.status === 204) return null;
  let body = null;
  try { body = await r.json(); } catch (e) { /* geen json-body */ }
  if (!r.ok) throw new Error((body && body.error) || ("Er ging iets mis (" + r.status + ")."));
  return body;
}
/* Nieuwe bestelling plaatsen. Geeft { id, token } terug. */
async function createOrder(payload) {
  return apiJSON("/api/orders", { method: "POST", body: JSON.stringify(payload) });
}
/* Bestaande bestelling ophalen via de beveiligde token (aanpas-link). */
async function findOrderByToken(id, token) {
  try {
    return await apiJSON("/api/orders/" + encodeURIComponent(id) + "?token=" + encodeURIComponent(token));
  } catch (e) { return null; }
}
/* Bestelling bijwerken of annuleren; de token bewijst dat je de eigenaar bent. */
async function updateOrderRecord(id, token, patch) {
  return apiJSON("/api/orders/" + encodeURIComponent(id), {
    method: "PATCH",
    body: JSON.stringify(Object.assign({ token: token }, patch || {})),
  });
}
function manageUrl(id, token) {
  return location.pathname.split("/").pop() + "?bestelling=" + encodeURIComponent(id) + "&token=" + encodeURIComponent(token);
}
function isPastDeadline() {
  const iso = FEEST.event.deadlineISO;
  if (!iso) return false;
  const dl = new Date(iso + "T23:59:59");
  return !isNaN(dl) && new Date() > dl;
}

/* ---------- read-only samenvatting (na deadline) ---------- */
function ReadOnlySummary({ state }) {
  const { lines, total } = buildOrder(state);
  const pickup = FEEST.pickupOptions.find((o) => o.id === state.parent.pickup);
  return (
    <div className="card" style={{ padding: "var(--space-6)" }}>
      <div className="ro-grid">
        <div><span className="ro-k">Naam</span><span className="ro-v">{state.parent.naam}</span></div>
        <div><span className="ro-k">E-mail</span><span className="ro-v">{state.parent.email}</span></div>
        <div><span className="ro-k">Volwassenen</span><span className="ro-v">{state.parent.volwassenen}</span></div>
        <div><span className="ro-k">Ophalen</span><span className="ro-v">{pickup ? pickup.label : "—"}</span></div>
      </div>
      <div style={{ borderTop: "1px solid var(--line-200)", margin: "16px 0", paddingTop: 16 }}>
        <span className="ro-k">Kinderen</span>
        {state.kids.map((k, i) => <div key={i} className="drow"><span className="k">{k.naam || "Kind"}</span><span className="v">{k.opSchool ? k.groep : "niet op school"}</span></div>)}
      </div>
      <div style={{ borderTop: "1px solid var(--line-200)", paddingTop: 16 }}>
        {lines.map((l) => <div key={l.key} className="drow"><span className="k">{l.kind === "donation" ? "" : l.qty + "× "}{l.name}</span><span className="v">{euro(l.total)}</span></div>)}
        <div className="dtotal"><span className="t-lbl">Totaal betaald</span><span className="t-val tnum">{euro(total)}</span></div>
      </div>
    </div>
  );
}

/* ---------- aanpas-scherm ---------- */
function ManageOrder(props) {
  const { state, baseline, baselineTotal, orderNr, setParent, addKid, updateKid, removeKid,
    setItemQty, setTokens, setDonation, setVolunteer, onPay, onSaveNoDiff, onCancel } = props;
  const [showErr, setShowErr] = useStateMg(false);
  const [confirmCancel, setConfirmCancel] = useStateMg(false);
  const past = isPastDeadline();

  const errors = useMemoMg(() => {
    const e = {};
    if (!state.parent.naam.trim()) e.naam = "Vul je naam in.";
    if (!state.parent.email.trim()) e.email = "Vul je e-mailadres in.";
    else if (!EMAIL_RE_MG.test(state.parent.email)) e.email = "Dit lijkt geen geldig e-mailadres.";
    if (!state.parent.telefoon.trim()) e.telefoon = "Vul een telefoonnummer in.";
    const ke = {};
    state.kids.forEach((k) => { const ee = {}; if (!k.naam.trim()) ee.naam = "Vul de naam in."; if (k.opSchool && !k.groep) ee.groep = "Kies een groep."; if (Object.keys(ee).length) ke[k.id] = ee; });
    if (Object.keys(ke).length) e.kids = ke;
    return e;
  }, [state]);
  const valid = Object.keys(errors).length === 0;
  const shown = showErr ? errors : {};

  const newTotal = buildOrder(state).total;
  const diff = Math.round((newTotal - baselineTotal) * 100) / 100;

  const attempt = (fn) => { if (!valid) { setShowErr(true); window.scrollTo(0, 0); return; } fn(); };

  return (
    <div className="manage-wrap">
      <div className="manage-head">
        <p className="eyebrow">Jouw bestelling · {orderNr}</p>
        <h1 className="display">Hoi {state.parent.naam ? state.parent.naam.split(" ")[0] : "ouder"}, hier staat je bestelling</h1>
        {past
          ? <p className="lead">Aanpassen is gesloten sinds <b>{FEEST.event.deadline}</b>. Je kunt je bestelling hieronder nog wel bekijken.</p>
          : <p className="lead">Je kunt nog bijbestellen of je gegevens wijzigen tot <b>{FEEST.event.deadline}</b>. Verlagen of verwijderen kan niet — neem daarvoor contact op met de OR.</p>}
      </div>

      {past ? <ReadOnlySummary state={state} /> : (
        <React.Fragment>
          <StepGegevens state={state} setParent={setParent} errors={shown} />
          <StepKinderen state={state} addKid={addKid} updateKid={updateKid} removeKid={removeKid} errors={shown} />

          {/* ophaalwijze */}
          <div className="section-block">
            <h2 className="section-title"><Icon name="gift" size={22} style={{ color: "var(--primary)" }} /> Bonnen &amp; muntjes ophalen</h2>
            <div className="pickup-grid" role="radiogroup">
              {FEEST.pickupOptions.map((opt) => {
                const on = state.parent.pickup === opt.id;
                return (
                  <button key={opt.id} type="button" role="radio" aria-checked={on}
                    className={"pickup-opt" + (on ? " is-on" : "")} onClick={() => setParent("pickup", opt.id)}>
                    <span className="po-ic"><Icon name={opt.icon} size={22} /></span>
                    <span className="po-body"><span className="po-label">{opt.label}</span><span className="po-desc">{opt.desc}</span></span>
                    <span className="po-radio" aria-hidden="true" />
                  </button>
                );
              })}
            </div>
          </div>

          <StepEten state={state} baseline={baseline} setItemQty={setItemQty} setTokens={setTokens} setDonation={setDonation} setVolunteer={setVolunteer} />

          {/* samenvatting + acties */}
          <div className="manage-summary card">
            <div className="ms-rows">
              <div className="ms-row"><span>Eerder betaald</span><span className="tnum">{euro(baselineTotal)}</span></div>
              <div className="ms-row"><span>Nieuw totaal</span><span className="tnum">{euro(newTotal)}</span></div>
              <div className="ms-row ms-diff"><span>{diff > 0 ? "Bij te betalen" : "Te betalen"}</span><span className="tnum">{euro(diff)}</span></div>
            </div>
            {diff > 0
              ? <Button size="lg" icon="ticket" block onClick={() => attempt(() => onPay(diff))}>Bijbetalen via Mollie · {euro(diff)}</Button>
              : <Button size="lg" icon="check" block onClick={() => attempt(onSaveNoDiff)}>Wijzigingen opslaan</Button>}
            <button className="linkbtn linkbtn--danger" style={{ display: "block", margin: "14px auto 0" }} onClick={() => setConfirmCancel(true)}>Bestelling annuleren</button>
          </div>
        </React.Fragment>
      )}

      {confirmCancel && (
        <div className="modal-scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) setConfirmCancel(false); }}>
          <div className="modal" role="dialog" aria-modal="true" style={{ maxWidth: 460 }}>
            <div className="modal-head"><h3>Bestelling annuleren?</h3>
              <button className="icon-btn" onClick={() => setConfirmCancel(false)} aria-label="Sluiten"><Icon name="x" size={18} /></button></div>
            <div className="modal-body">
              <p style={{ margin: 0, fontSize: 14.5, color: "var(--fg-2)", lineHeight: 1.6 }}>
                Weet je zeker dat je bestelling <b>{orderNr}</b> wilt annuleren? Dit kan niet ongedaan worden gemaakt.
                Voor een eventuele terugbetaling neemt de OR persoonlijk contact met je op.
              </p>
            </div>
            <div className="modal-foot">
              <Button variant="secondary" onClick={() => setConfirmCancel(false)}>Nee, terug</Button>
              <button className="btn btn--lg" style={{ background: "var(--danger)", color: "#fff" }} onClick={onCancel}>Ja, annuleer</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ---------- bevestiging na opslaan ---------- */
function ManageDone({ orderNr, total, cancelled, onView }) {
  return (
    <div className="confirm-wrap">
      <div className="confirm-hero">
        <div className="confirm-badge" style={cancelled ? { background: "var(--danger-soft)", color: "var(--danger)" } : null}>
          <Icon name={cancelled ? "x" : "checkBig"} size={42} />
        </div>
        <p className="eyebrow" style={{ marginBottom: 12 }}>{cancelled ? "Bestelling geannuleerd" : "Wijzigingen opgeslagen"}</p>
        <h1>{cancelled ? "Je bestelling is geannuleerd" : "Gelukt!"}</h1>
        <p className="lead">
          {cancelled
            ? "We hebben je bestelling geannuleerd. Voor een eventuele terugbetaling neemt de OR contact met je op."
            : "Je aangepaste bestelling is opgeslagen. Je ontvangt een bijgewerkte bevestiging per e-mail."}
        </p>
        <div className="ordernr"><Icon name="ticket" size={16} style={{ color: "var(--primary)" }} /> Bestelnummer <b>{orderNr}</b>{!cancelled && total != null && <span> · totaal {euro(total)}</span>}</div>
        {!cancelled && <div style={{ marginTop: 22 }}><Button variant="secondary" icon="left" onClick={onView}>Terug naar mijn bestelling</Button></div>}
      </div>
    </div>
  );
}

/* ---------- ongeldige / verlopen link ---------- */
function ManageInvalid() {
  return (
    <div className="confirm-wrap">
      <div className="confirm-hero">
        <div className="confirm-badge" style={{ background: "var(--surface-sunk)", color: "var(--fg-3)" }}><Icon name="alert" size={42} /></div>
        <p className="eyebrow" style={{ marginBottom: 12 }}>Link werkt niet</p>
        <h1>We kunnen deze bestelling niet vinden</h1>
        <p className="lead">De link is mogelijk verlopen of onvolledig. Gebruik de knop in je bevestigingsmail, of neem contact op met de Ouderraad.</p>
        <div style={{ marginTop: 22 }}><a className="btn btn--secondary" href={location.pathname.split("/").pop()}><Icon name="left" size={18} /> Naar de bestelpagina</a></div>
      </div>
    </div>
  );
}

Object.assign(window, { genToken, createOrder, findOrderByToken, updateOrderRecord, manageUrl, isPastDeadline, ManageOrder, ManageDone, ManageInvalid });
