/* global React */
/* ============================================================
   DDPP GENERISCHE BUCHUNGS-ENGINE
   Wiederverwendbare Booking-Form für alle Event-Typen.
   Exportiert window.EventBookingForm({ cfg }).
   cfg steuert Preis, Mindestpersonen, Personen-Bezeichnung (noun),
   Rechnungsmodus ('company' | 'private') und welche Add-ons gelten.
   Strings via window.t / window.tt (i18n.jsx) — neutrale ev.*-Keys
   für personenbezogene Zeilen, sonst Wiederverwendung der ffb.*-Keys.
   ============================================================ */

const EBOOKING_ENDPOINT = "/api/booking";

/* Gemeinsame Add-on-/Stundenpreise (Basispreis & Mindestpersonen aus cfg) */
const EB_PRICING = {
  perPersonExtraHour: 14.95,
  drinksBudgetDefault: 300,
  drinksBudgetMin: 100,
  drinksBudgetStep: 50,
  dj: 300,
  ownMusic: 49.90,
  customBallsPack: 150,
  customBallsPackSize: 200,
  customBallsGiftPerPerson: 14.90,
  coachPerHour: 79.90,
  minLeadDaysDefault: 2,
  minLeadDaysCustomBalls: 1,
};

/* ----------------------------------------------------------------
   PRO EVENT-TYP — hier kannst du Preise jederzeit anpassen.
   base       = Grundpreis pro Person (Basis-Stunden)
   minPersons = Mindestpersonen
   baseHours  = inkludierte Stunden
   billing    = 'company' (Firma + USt-IdNr.) | 'private' (nur Person)
   noun       = Personen-Bezeichnung in den Preiszeilen
   extras     = true → Custom-Bälle / Geschenkbälle / Replay-Hinweis
   ---------------------------------------------------------------- */
const EB_TYPES = {
  firmenfeiern: { kind: "firmenfeier", base: 29.90, minPersons: 10, baseHours: 2, billing: "company", noun: window.t("ev.noun.firmenfeiern"), extras: true },
  geburtstage:  { kind: "geburtstag",  base: 24.90, minPersons: 6,  baseHours: 2, billing: "private", noun: window.t("ev.noun.geburtstage"),  extras: false },
  events:       { kind: "event",       base: 24.90, minPersons: 8,  baseHours: 2, billing: "private", noun: window.t("ev.noun.events"),       extras: true },
};

const ebFmtEUR = (n) =>
  new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(n);

function ebTodayPlusDays(days) {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  d.setDate(d.getDate() + days);
  return d.toISOString().slice(0, 10);
}

function ebCalcTotal(cfg, state) {
  const persons = Math.max(cfg.minPersons, state.persons || 0);
  const hours = Math.max(cfg.baseHours, state.hours || cfg.baseHours);
  const extraHours = hours - cfg.baseHours;
  const noun = cfg.noun;
  const lines = [];

  lines.push({
    label: window.tt("ev.line.base", { persons, noun, price: ebFmtEUR(cfg.base), hours: cfg.baseHours }),
    amount: persons * cfg.base,
  });
  if (extraHours > 0) {
    lines.push({
      label: window.tt("ev.line.extra", { n: extraHours, persons, noun, price: ebFmtEUR(EB_PRICING.perPersonExtraHour) }),
      amount: persons * extraHours * EB_PRICING.perPersonExtraHour,
    });
  }
  if (state.drinks) {
    lines.push({ label: window.t("ffb.line.drinks"), amount: Math.max(0, state.drinksBudget || 0) });
  }
  if (state.music === "dj") {
    lines.push({ label: window.t("ffb.line.dj"), amount: EB_PRICING.dj });
  } else if (state.music === "own") {
    lines.push({ label: window.t("ffb.line.own_music"), amount: EB_PRICING.ownMusic });
  }
  if (cfg.extras && state.customBalls && state.customBallsAmount >= EB_PRICING.customBallsPackSize) {
    const packs = Math.ceil(state.customBallsAmount / EB_PRICING.customBallsPackSize);
    lines.push({ label: window.tt("ffb.line.custom_balls", { n: packs * EB_PRICING.customBallsPackSize }), amount: packs * EB_PRICING.customBallsPack });
  }
  if (state.coach) {
    lines.push({ label: window.tt("ffb.line.coach", { hours }), amount: hours * EB_PRICING.coachPerHour });
  }

  const total = lines.reduce((s, l) => s + l.amount, 0);
  return { lines, total, persons, hours };
}

function EbFormRow({ label, hint, error, children }) {
  return (
    <div className="form-row">
      {label && <label className="form-label">{label}</label>}
      {children}
      {hint && !error && <div className="form-hint">{hint}</div>}
      {error && <div className="form-error">{error}</div>}
    </div>
  );
}

function EbAddonToggle({ id, title, price, checked, onChange, disabled, children }) {
  return (
    <label className={`addon ${checked ? "checked" : ""} ${disabled ? "disabled" : ""}`}>
      <input type="checkbox" id={id} checked={checked} disabled={disabled} onChange={(e) => onChange(e.target.checked)} />
      <div className="addon-body">
        <div className="addon-head">
          <span className="addon-title">{title}</span>
          <span className="addon-price">{price}</span>
        </div>
        {children && <div className="addon-extra">{children}</div>}
      </div>
    </label>
  );
}

function EventBookingForm({ cfg }) {
  const { useState, useMemo, useEffect } = React;
  const noun = cfg.noun;

  const [persons, setPersons] = useState(cfg.minPersons);
  const [hours, setHours] = useState(cfg.baseHours);
  const [date, setDate] = useState("");
  const [time, setTime] = useState("18:00");

  const [drinks, setDrinks] = useState(false);
  const [drinksBudget, setDrinksBudget] = useState(EB_PRICING.drinksBudgetDefault);
  const [music, setMusic] = useState("none");
  const [customBalls, setCustomBalls] = useState(false);
  const [customBallsAmount, setCustomBallsAmount] = useState(EB_PRICING.customBallsPackSize);
  const [robot, setRobot] = useState(true);
  const [coach, setCoach] = useState(false);

  const [contactFirst, setContactFirst] = useState("");
  const [contactLast, setContactLast] = useState("");
  const [contactEmail, setContactEmail] = useState("");
  const [contactPhone, setContactPhone] = useState("");
  const [company, setCompany] = useState("");
  const [billingStreet, setBillingStreet] = useState("");
  const [billingZip, setBillingZip] = useState("");
  const [billingCity, setBillingCity] = useState("");
  const [vatId, setVatId] = useState("");
  const [notes, setNotes] = useState("");
  const [consent, setConsent] = useState(false);

  const [submitting, setSubmitting] = useState(false);
  const [submitResult, setSubmitResult] = useState(null);
  const [errors, setErrors] = useState({});

  const isCompany = cfg.billing === "company";
  const minDate = useMemo(
    () => ebTodayPlusDays(customBalls ? Math.max(EB_PRICING.minLeadDaysDefault, EB_PRICING.minLeadDaysCustomBalls) : EB_PRICING.minLeadDaysDefault),
    [customBalls],
  );

  useEffect(() => { if (date && date < minDate) setDate(minDate); }, [minDate, date]);

  const calc = useMemo(
    () => ebCalcTotal(cfg, { persons, hours, drinks, drinksBudget, music, customBalls, customBallsAmount, coach }),
    [cfg, persons, hours, drinks, drinksBudget, music, customBalls, customBallsAmount, coach],
  );

  function validate() {
    const e = {};
    if (!date) e.date = window.t("ffb.err.date_required");
    if (date && date < minDate) e.date = window.tt("ffb.err.date_min", { date: minDate });
    if (!time) e.time = window.t("ffb.err.time_required");
    if (persons < cfg.minPersons) e.persons = window.tt("ev.hint.persons", { n: cfg.minPersons, noun });
    if (hours < cfg.baseHours) e.hours = window.tt("ffb.err.hours_min", { n: cfg.baseHours });
    if (cfg.extras && customBalls && customBallsAmount < EB_PRICING.customBallsPackSize) {
      e.customBallsAmount = window.tt("ffb.err.balls_min", { n: EB_PRICING.customBallsPackSize });
    }
    if (!contactFirst.trim()) e.contactFirst = window.t("ffb.err.required");
    if (!contactLast.trim()) e.contactLast = window.t("ffb.err.required");
    if (!contactEmail.trim() || !/.+@.+\..+/.test(contactEmail)) e.contactEmail = window.t("ffb.err.email_invalid");
    if (isCompany && !company.trim()) e.company = window.t("ffb.err.required");
    if (!billingStreet.trim()) e.billingStreet = window.t("ffb.err.required");
    if (!billingZip.trim()) e.billingZip = window.t("ffb.err.required");
    if (!billingCity.trim()) e.billingCity = window.t("ffb.err.required");
    if (!consent) e.consent = window.t("ffb.err.consent");
    setErrors(e);
    return Object.keys(e).length === 0;
  }

  async function handleSubmit(e) {
    e.preventDefault();
    setSubmitResult(null);
    if (!validate()) {
      const firstErr = document.querySelector(".form-error");
      if (firstErr) firstErr.scrollIntoView({ behavior: "smooth", block: "center" });
      return;
    }
    setSubmitting(true);
    try {
      const payload = {
        kind: cfg.kind,
        submittedAt: new Date().toISOString(),
        event: { date, time, persons, hours },
        options: {
          drinks: drinks ? { budget: Math.max(0, drinksBudget || 0) } : false,
          music,
          customBalls: cfg.extras && customBalls ? { amount: customBallsAmount } : null,
          robot,
          coach,
        },
        contact: { firstName: contactFirst, lastName: contactLast, email: contactEmail, phone: contactPhone },
        billing: { company: isCompany ? company : null, street: billingStreet, zip: billingZip, city: billingCity, vatId: isCompany ? vatId : null },
        notes,
        pricing: { lines: calc.lines, totalNet: calc.total },
        lang: window.currentLang || "de",
      };
      const res = await fetch(EBOOKING_ENDPOINT, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      setSubmitResult("ok");
      window.scrollTo({ top: 0, behavior: "smooth" });
    } catch (err) {
      console.error(err);
      setSubmitResult("error");
    } finally {
      setSubmitting(false);
    }
  }

  if (submitResult === "ok") {
    return (
      <section className="section booking-success">
        <div className="section-eyebrow">{window.t("ffb.success.eyebrow")}</div>
        <h2>{window.t("ffb.success.h2")}</h2>
        <p className="intro">{window.t("ffb.success.body")}</p>
        <a href="index.html" className="btn btn-orange btn-xl">{window.t("ffb.success.back")}</a>
      </section>
    );
  }

  return (
    <form className="section booking-form" onSubmit={handleSubmit} noValidate>
      {submitResult === "error" && (
        <div className="form-banner form-banner-error">{window.t("ffb.error_banner")}</div>
      )}

      {/* TERMIN */}
      <div className="form-step">
        <h2>{window.t("ffb.s1.h2")}</h2>
        <p className="intro">{window.tt("ffb.s1.intro", { hours: cfg.baseHours, days: EB_PRICING.minLeadDaysDefault })}</p>
        <div className="form-grid form-grid-2">
          <EbFormRow label={window.t("ffb.lbl.date")} error={errors.date}>
            <input type="date" value={date} min={minDate} onChange={(e) => setDate(e.target.value)} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.time")} error={errors.time}>
            <input type="time" value={time} step="900" onChange={(e) => setTime(e.target.value)} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.persons")} hint={window.tt("ev.hint.persons", { n: cfg.minPersons, noun })} error={errors.persons}>
            <input type="number" inputMode="numeric" min={cfg.minPersons} step="1" value={persons} onChange={(e) => setPersons(parseInt(e.target.value || "0", 10))} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.hours")} hint={window.tt("ev.hint.hours", { n: cfg.baseHours, noun, price: ebFmtEUR(EB_PRICING.perPersonExtraHour) })} error={errors.hours}>
            <input type="number" inputMode="numeric" min={cfg.baseHours} step="1" value={hours} onChange={(e) => setHours(parseInt(e.target.value || "0", 10))} />
          </EbFormRow>
        </div>
      </div>

      {/* OPTIONEN */}
      <div className="form-step">
        <h2>{window.t("ffb.s2.h2")}</h2>
        <div className="addons">
          <EbAddonToggle
            id="eb-drinks"
            title={window.t("ffb.addon.drinks.title")}
            price={drinks ? ebFmtEUR(Math.max(0, drinksBudget || 0)) : window.t("ffb.price.budget")}
            checked={drinks}
            onChange={setDrinks}
          >
            {drinks && (
              <EbFormRow label={window.t("ffb.addon.drinks.amount_label")} hint={window.t("ffb.addon.drinks.hint")}>
                <input type="number" inputMode="numeric" min={EB_PRICING.drinksBudgetMin} step={EB_PRICING.drinksBudgetStep} value={drinksBudget} onChange={(e) => setDrinksBudget(parseInt(e.target.value || "0", 10))} />
              </EbFormRow>
            )}
          </EbAddonToggle>

          <EbAddonToggle id="eb-dj" title={window.t("ffb.addon.dj.title")} price={window.tt("ffb.price.flat", { eur: ebFmtEUR(EB_PRICING.dj) })} checked={music === "dj"} onChange={(v) => setMusic(v ? "dj" : "none")} disabled={music === "own"} />
          <EbAddonToggle id="eb-own-music" title={window.t("ffb.addon.own_music.title")} price={window.tt("ffb.price.flat", { eur: ebFmtEUR(EB_PRICING.ownMusic) })} checked={music === "own"} onChange={(v) => setMusic(v ? "own" : "none")} disabled={music === "dj"} />

          {cfg.extras && (
            <EbAddonToggle
              id="eb-custom-balls"
              title={window.t("ffb.addon.custom_balls.title")}
              price={window.tt("ffb.price.per_pack", { eur: ebFmtEUR(EB_PRICING.customBallsPack), size: EB_PRICING.customBallsPackSize })}
              checked={customBalls}
              onChange={setCustomBalls}
            >
              {customBalls && (
                <EbFormRow label={window.t("ffb.addon.custom_balls.amount_label")} error={errors.customBallsAmount}>
                  <input type="number" inputMode="numeric" min={EB_PRICING.customBallsPackSize} step={EB_PRICING.customBallsPackSize} value={customBallsAmount} onChange={(e) => setCustomBallsAmount(parseInt(e.target.value || "0", 10))} />
                </EbFormRow>
              )}
            </EbAddonToggle>
          )}

          <EbAddonToggle id="eb-robot" title={window.t("ffb.addon.robot.title")} price={window.t("ffb.addon.free")} checked={robot} onChange={setRobot} />
          <EbAddonToggle id="eb-coach" title={window.tt("ffb.addon.coach.title", { hours })} price={window.tt("ffb.price.per_hour", { eur: ebFmtEUR(EB_PRICING.coachPerHour) })} checked={coach} onChange={setCoach} />
        </div>
      </div>

      {/* KONTAKT + RECHNUNG */}
      <div className="form-step">
        <h2>{window.t("ffb.s3.h2")}</h2>
        <h3 className="form-subhead">{window.t("ffb.s3.contact_subhead")}</h3>
        <div className="form-grid form-grid-2">
          <EbFormRow label={window.t("ffb.lbl.first_name")} error={errors.contactFirst}>
            <input value={contactFirst} onChange={(e) => setContactFirst(e.target.value)} autoComplete="given-name" />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.last_name")} error={errors.contactLast}>
            <input value={contactLast} onChange={(e) => setContactLast(e.target.value)} autoComplete="family-name" />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.email")} error={errors.contactEmail}>
            <input type="email" inputMode="email" autoComplete="email" value={contactEmail} onChange={(e) => setContactEmail(e.target.value)} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.phone")}>
            <input type="tel" inputMode="tel" autoComplete="tel" value={contactPhone} onChange={(e) => setContactPhone(e.target.value)} />
          </EbFormRow>
        </div>

        <h3 className="form-subhead">{window.t(isCompany ? "ffb.s3.billing_subhead" : "ev.s3.billing_private")}</h3>
        <div className="form-grid form-grid-2">
          {isCompany && (
            <EbFormRow label={window.t("ffb.lbl.company")} error={errors.company}>
              <input value={company} onChange={(e) => setCompany(e.target.value)} autoComplete="organization" />
            </EbFormRow>
          )}
          {isCompany && (
            <EbFormRow label={window.t("ffb.lbl.vat")}>
              <input value={vatId} onChange={(e) => setVatId(e.target.value)} />
            </EbFormRow>
          )}
          <EbFormRow label={window.t("ffb.lbl.street")} error={errors.billingStreet}>
            <input value={billingStreet} autoComplete="street-address" onChange={(e) => setBillingStreet(e.target.value)} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.zip")} error={errors.billingZip}>
            <input value={billingZip} inputMode="numeric" autoComplete="postal-code" onChange={(e) => setBillingZip(e.target.value)} />
          </EbFormRow>
          <EbFormRow label={window.t("ffb.lbl.city")} error={errors.billingCity}>
            <input value={billingCity} autoComplete="address-level2" onChange={(e) => setBillingCity(e.target.value)} />
          </EbFormRow>
        </div>

        <EbFormRow label={window.t("ffb.lbl.notes")}>
          <textarea rows={3} value={notes} onChange={(e) => setNotes(e.target.value)} />
        </EbFormRow>
      </div>

      {/* SUMMARY */}
      <div className="form-step booking-summary">
        <div className="section-eyebrow">{window.t("ffb.summary.eyebrow")}</div>
        <h2>{window.t("ffb.summary.h2")}</h2>
        <ul className="price-lines">
          {calc.lines.map((l, i) => (
            <li key={i}><span>{l.label}</span><span>{ebFmtEUR(l.amount)}</span></li>
          ))}
        </ul>
        <div className="price-total"><span>{window.t("ffb.summary.total")}</span><span>{ebFmtEUR(calc.total)}</span></div>
        <p className="form-note">{window.t("ffb.summary.tax_note")}</p>

        <EbFormRow error={errors.consent}>
          <label className="consent">
            <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} />
            <span>{window.t("ffb.consent.text_pre")}<a href="datenschutz.html" target="_blank" rel="noopener">{window.t("ffb.consent.link")}</a>{window.t("ffb.consent.text_post")}</span>
          </label>
        </EbFormRow>

        <button type="submit" className="btn btn-orange btn-xl booking-submit" disabled={submitting}>
          {submitting ? window.t("ffb.submit.sending") : window.t("ffb.submit")}
        </button>
      </div>
    </form>
  );
}

window.EventBookingForm = EventBookingForm;
window.EB_TYPES = EB_TYPES;
