/* global React, ReactDOM, Icon, Button, Logo, FEEST, buildOrder,
   Landing, StepGegevens, StepKinderen, StepEten, Cart, CartBar,
   StepOverzicht, Mollie, Confirmation,
   useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor */
const { useState, useEffect, useRef } = React;

const STEP_LABELS = ["Gegevens", "Kinderen", "Eten & drinken", "Overzicht"];
let KID_SEQ = 2;
const newKid = () => ({ id: "k" + KID_SEQ++, naam: "", groep: "", opSchool: true });

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "landingVariant": "editorial",
  "primary": ["#2C6860", "#235A52", "#1C4A44"],
  "buttonShape": "zacht"
}/*EDITMODE-END*/;

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [screen, setScreen] = useState("landing"); // landing | wizard | mollie | done
  const [step, setStep] = useState(0);
  const [showErr, setShowErr] = useState(false);
  const [agreed, setAgreed] = useState(false);
  const [orderNr, setOrderNr] = useState("");
  const [orderToken, setOrderToken] = useState("");
  const [baseline, setBaseline] = useState(null);       // reeds-betaalde hoeveelheden (manage)
  const [baselineTotal, setBaselineTotal] = useState(0);
  const [pendingDiff, setPendingDiff] = useState(0);
  const [manageCancelled, setManageCancelled] = useState(false);

  const [parent, setParentState] = useState({ naam: "", email: "", telefoon: "", volwassenen: 2, pickup: "", opmerking: "" });
  const [kids, setKids] = useState([{ id: "k1", naam: "", groep: "", opSchool: true }]);
  const [order, setOrder] = useState({ items: {}, tokens: 0, donation: 0 });
  const [volunteer, setVolunteerState] = useState({ wil: false, taak: "", dagdeel: "" });

  const state = { parent, kids, order, volunteer };
  const topRef = useRef(null);

  // expose home nav for the logo
  useEffect(() => { window.__goHome = () => { setScreen("landing"); }; }, []);

  // beveiligde-link: open een bestaande bestelling om aan te passen
  useEffect(() => {
    const p = new URLSearchParams(location.search);
    const id = p.get("bestelling"); const tok = p.get("token");
    if (!id || !tok) return;
    (async () => {
      const rec = await window.findOrderByToken(id, tok);
      if (!rec || rec.cancelled) { setScreen("link-invalid"); return; }
      setParentState(rec.parent); setKids(rec.kids); setOrder(rec.order);
      setVolunteerState(rec.volunteer || { wil: false, taak: "", dagdeel: "" });
      setBaseline({ items: { ...rec.order.items }, tokens: rec.order.tokens || 0, donation: rec.order.donation || 0 });
      setBaselineTotal(typeof rec.total === "number" ? rec.total : buildOrder({ parent: rec.parent, kids: rec.kids, order: rec.order, volunteer: rec.volunteer || {} }).total);
      setOrderNr(rec.id); setOrderToken(tok);
      setScreen("manage");
    })();
  }, []);

  // apply tweaks → CSS vars
  useEffect(() => {
    const r = document.documentElement;
    const pal = t.primary || TWEAK_DEFAULTS.primary;
    r.style.setProperty("--primary", pal[0]);
    r.style.setProperty("--primary-hover", pal[1] || pal[0]);
    r.style.setProperty("--primary-press", pal[2] || pal[1] || pal[0]);
    r.style.setProperty("--primary-soft", pal[0] + "22");
    r.style.setProperty("--focus-ring", pal[0] + "8c");
    r.style.setProperty("--radius-pill", t.buttonShape === "zacht" ? "14px" : "999px");
  }, [t.primary, t.buttonShape]);

  const scrollTop = () => { if (topRef.current) topRef.current.scrollTop = 0; window.scrollTo(0, 0); };

  // ---- updaters ----
  const setParent = (f, v) => setParentState((p) => ({ ...p, [f]: v }));
  const addKid = () => setKids((k) => [...k, newKid()]);
  const updateKid = (id, f, v) => setKids((ks) => ks.map((k) => (k.id === id ? { ...k, [f]: v } : k)));
  const removeKid = (id) => setKids((ks) => (ks.length > 1 ? ks.filter((k) => k.id !== id) : ks));
  const setItemQty = (id, q) => setOrder((o) => ({ ...o, items: { ...o.items, [id]: Math.max(baseline ? (baseline.items[id] || 0) : 0, q) } }));
  const setTokens = (n) => setOrder((o) => ({ ...o, tokens: Math.max(baseline ? baseline.tokens : 0, n) }));
  const setDonation = (a) => setOrder((o) => ({ ...o, donation: Math.max(baseline ? baseline.donation : 0, Math.round(a * 100) / 100) }));
  const setVolunteer = (patch) => setVolunteerState((v) => ({ ...v, ...patch }));

  // ---- validation ----
  const errors = (() => {
    const e = {};
    if (step === 0) {
      if (!parent.naam.trim()) e.naam = "Vul je naam in.";
      if (!parent.email.trim()) e.email = "Vul je e-mailadres in.";
      else if (!EMAIL_RE.test(parent.email)) e.email = "Dit lijkt geen geldig e-mailadres.";
      if (!parent.telefoon.trim()) e.telefoon = "Vul een telefoonnummer in.";
    }
    if (step === 1) {
      const ke = {};
      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;
  })();
  const stepValid = Object.keys(errors).length === 0;
  const { total, count } = buildOrder(state);
  const cartEmpty = count === 0 && order.donation === 0;

  const goTo = (s) => { setShowErr(false); setStep(s); scrollTop(); };
  const next = () => {
    if (!stepValid) { setShowErr(true); return; }
    if (step < 3) { setStep(step + 1); setShowErr(false); scrollTop(); }
  };
  const back = () => {
    if (step === 0) { setScreen("landing"); return; }
    setStep(step - 1); setShowErr(false); scrollTop();
  };
  const startWizard = () => { setScreen("wizard"); setStep(0); scrollTop(); };
  const goPay = () => {
    if (!parent.pickup) { setShowErr(true); scrollTop(); return; }
    setScreen("mollie");
  };
  const paid = async (method) => {
    try {
      const { total } = buildOrder(state);
      // De server kent het bestelnummer toe en geeft de aanpas-token terug.
      const res = await window.createOrder({ parent, kids, order, volunteer, payment: method || "ideal", total });
      setOrderNr(res.id); setOrderToken(res.token);
    } catch (e) {
      alert("De bestelling kon niet worden opgeslagen. Controleer je verbinding en probeer het opnieuw.");
      setScreen("wizard"); scrollTop(); return;
    }
    setScreen("done"); scrollTop();
  };

  // ---- aanpassen (manage) acties ----
  const finalizeManage = async (method) => {
    const { total } = buildOrder(state);
    try {
      await window.updateOrderRecord(orderNr, orderToken, {
        parent, kids, order, volunteer, total, lastPayment: method || undefined,
      });
    } catch (e) {
      alert("De wijziging kon niet worden opgeslagen. Probeer het opnieuw.");
      setScreen("manage"); scrollTop(); return;
    }
    setBaselineTotal(total);
    setBaseline({ items: { ...order.items }, tokens: order.tokens || 0, donation: order.donation || 0 });
    setManageCancelled(false);
    setScreen("manage-done"); scrollTop();
  };
  const managePayDiff = (diff) => { setPendingDiff(diff); setScreen("manage-pay"); scrollTop(); };
  const manageCancel = async () => {
    try { await window.updateOrderRecord(orderNr, orderToken, { cancelled: true }); }
    catch (e) { alert("Annuleren is mislukt. Probeer het opnieuw."); return; }
    setManageCancelled(true); setScreen("manage-done"); scrollTop();
  };
  const reopenManage = () => { setScreen("manage"); scrollTop(); };
  const restart = () => {
    setScreen("landing"); setStep(0); setAgreed(false);
    setParentState({ naam: "", email: "", telefoon: "", volwassenen: 2, pickup: "", opmerking: "" });
    setKids([{ id: "k1", naam: "", groep: "", opSchool: true }]);
    setOrder({ items: {}, tokens: 0, donation: 0 });
    setVolunteerState({ wil: false, taak: "", dagdeel: "" });
    scrollTop();
  };

  const shownErrors = showErr ? errors : {};

  // ---------- TWEAKS PANEL ----------
  const panel = (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Landingspagina" />
      <TweakRadio label="Stijl" value={t.landingVariant}
        options={[{ value: "editorial", label: "Strak" }, { value: "photo", label: "Foto" }, { value: "festival", label: "Speels" }]}
        onChange={(v) => { setTweak("landingVariant", v); setScreen("landing"); }} />
      <TweakSection label="Merk & vorm" />
      <TweakColor label="Actiekleur" value={t.primary}
        options={[["#2C6860", "#235A52", "#1C4A44"], ["#925248", "#8A4C40", "#743F35"], ["#A9802F", "#6E4E16", "#553C11"]]}
        onChange={(v) => setTweak("primary", v)} />
      <TweakRadio label="Knopvorm" value={t.buttonShape}
        options={[{ value: "rond", label: "Rond" }, { value: "zacht", label: "Zacht" }]}
        onChange={(v) => setTweak("buttonShape", v)} />
    </TweaksPanel>
  );

  // ---------- SCREENS ----------
  if (screen === "landing") {
    return (
      <div className="app" ref={topRef}>
        <header className="topbar">
          <Logo />
          <div className="right">
            <span className="deadline"><Icon name="clock" size={16} /> Bestellen kan t/m <b>{FEEST.event.deadline}</b></span>
            <Button size="sm" iconRight="right" onClick={startWizard}>Bestellen</Button>
          </div>
        </header>
        <Landing variant={t.landingVariant} onStart={startWizard} />
        <footer className="site-foot">
          <span>De Schovenhorst · Eindfeest 2026 · Ouderraad (OR)</span>
          <a href="admin.html">Beheer</a>
        </footer>
        {panel}
      </div>
    );
  }

  if (screen === "mollie") {
    return (<div>
      <Mollie amount={total} onSuccess={paid} onCancel={() => setScreen("wizard")} />
      {panel}
    </div>);
  }

  if (screen === "done") {
    return (
      <div className="app" ref={topRef}>
        <header className="topbar"><Logo /><div className="right"><span className="deadline"><Icon name="check" size={16} style={{ color: "var(--success)" }} /> Bestelling bevestigd</span></div></header>
        <Confirmation state={state} orderNr={orderNr} onRestart={restart} manageHref={orderToken ? window.manageUrl(orderNr, orderToken) : null} />
        {panel}
      </div>
    );
  }

  // ---------- AANPASSEN (manage) ----------
  if (screen === "link-invalid") {
    return (<div className="app" ref={topRef}>
      <header className="topbar"><Logo /></header>
      <ManageInvalid />
    </div>);
  }
  if (screen === "manage-pay") {
    return (<div>
      <Mollie amount={pendingDiff} onSuccess={(m) => finalizeManage(m)} onCancel={() => { setScreen("manage"); scrollTop(); }} />
    </div>);
  }
  if (screen === "manage-done") {
    return (<div className="app" ref={topRef}>
      <header className="topbar"><Logo /><div className="right"><span className="deadline"><Icon name="check" size={16} style={{ color: manageCancelled ? "var(--danger)" : "var(--success)" }} /> {manageCancelled ? "Geannuleerd" : "Bijgewerkt"}</span></div></header>
      <ManageDone orderNr={orderNr} total={buildOrder(state).total} cancelled={manageCancelled} onView={reopenManage} />
    </div>);
  }
  if (screen === "manage") {
    return (<div className="app" ref={topRef}>
      <header className="topbar">
        <Logo />
        <div className="right"><span className="deadline"><Icon name="clock" size={16} /> {isPastDeadline() ? "Aanpassen gesloten" : "Aanpassen kan t/m"} <b>{FEEST.event.deadline}</b></span></div>
      </header>
      <div className="wizard">
        <ManageOrder state={state} baseline={baseline} baselineTotal={baselineTotal} orderNr={orderNr}
          setParent={setParent} addKid={addKid} updateKid={updateKid} removeKid={removeKid}
          setItemQty={setItemQty} setTokens={setTokens} setDonation={setDonation} setVolunteer={setVolunteer}
          onPay={managePayDiff} onSaveNoDiff={() => finalizeManage(null)} onCancel={manageCancel} />
      </div>
    </div>);
  }

  // ---------- WIZARD ----------
  const isMenu = step === 2;
  const isReview = step === 3;

  let stepEl = null;
  if (step === 0) stepEl = <StepGegevens state={state} setParent={setParent} errors={shownErrors} />;
  else if (step === 1) stepEl = <StepKinderen state={state} addKid={addKid} updateKid={updateKid} removeKid={removeKid} errors={shownErrors} />;
  else if (step === 2) stepEl = <StepEten state={state} setItemQty={setItemQty} setTokens={setTokens} setDonation={setDonation} setVolunteer={setVolunteer} />;
  else if (step === 3) stepEl = <StepOverzicht state={state} goTo={goTo} setParent={setParent} agreed={agreed} setAgreed={setAgreed} showErr={showErr} />;

  return (
    <div className="app" ref={topRef}>
      <header className="topbar">
        <Logo />
        <div className="right">
          <span className="deadline"><Icon name="clock" size={16} /> Bestellen kan t/m <b>{FEEST.event.deadline}</b></span>
        </div>
      </header>

      <div className="wizard">
        {/* desktop stepper */}
        <nav className="stepper" aria-label="Voortgang" style={{ marginBottom: "var(--space-7)" }}>
          {STEP_LABELS.map((lbl, i) => (
            <React.Fragment key={i}>
              <div className={"step " + (i === step ? "is-active" : i < step ? "is-done is-clickable" : "")}
                onClick={() => { if (i < step) goTo(i); }}>
                <span className="dot">{i < step ? <Icon name="check" size={16} /> : i + 1}</span>
                <span className="lbl">{lbl}</span>
              </div>
              {i < STEP_LABELS.length - 1 && <span className={"bar" + (i < step ? " is-filled" : "")} />}
            </React.Fragment>
          ))}
        </nav>

        {/* mobile progress */}
        <div className="mprogress">
          <div className="mp-top"><span>Stap {step + 1} van 4 · <b>{STEP_LABELS[step]}</b></span><span className="muted">{Math.round(((step + 1) / 4) * 100)}%</span></div>
          <div className="mp-track"><div className="mp-fill" style={{ width: `${((step + 1) / 4) * 100}%` }} /></div>
        </div>

        {isMenu ? (
          <div className="wizard-grid">
            {stepEl}
            <Cart state={state} desktop onPrimary={() => next()} primaryLabel="Naar overzicht"
              primaryDisabled={cartEmpty} footnote={cartEmpty ? "Voeg iets toe om verder te gaan." : "Aanpassen kan tot " + FEEST.event.deadline + "."} />
          </div>
        ) : stepEl}

        {/* footer nav */}
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 16, marginTop: "var(--space-7)", maxWidth: isReview ? 760 : "none", marginLeft: isReview ? "auto" : 0, marginRight: isReview ? "auto" : 0 }}>
          <Button variant="secondary" icon="left" onClick={back}>{step === 0 ? "Terug naar start" : "Vorige"}</Button>
          {isReview ? (
            <Button size="lg" icon="ticket" onClick={goPay} disabled={!agreed || cartEmpty}>Afrekenen via Mollie · {window.euro(total)}</Button>
          ) : isMenu ? (
            <span className="muted" style={{ fontSize: 13.5, display: "none" }} />
          ) : (
            <Button iconRight="right" onClick={next}>Volgende</Button>
          )}
        </div>
      </div>

      {/* mobile cart bar on menu step */}
      {isMenu && <CartBar state={state} onPrimary={() => next()} primaryLabel="Overzicht" disabled={cartEmpty} />}

      {panel}
    </div>
  );
}

// Wacht tot de serverconfig (menu, prijzen, datum) geladen is, render daarna.
(window.FEEST_READY || Promise.resolve()).then(() => {
  ReactDOM.createRoot(document.getElementById("root")).render(<App />);
});
