/* global React, TopBar, Header, Footer */
const { useState, useMemo, useEffect } = React;

/* ============================================================
   FIRMENFEIER-BUCHUNG
   Wiederverwendbare Booking-Engine, hier konfiguriert für
   Firmenfeier. Strings via window.t / window.tt (i18n.jsx).
   ============================================================ */

const BOOKING_ENDPOINT = "/api/booking";

const PRICING = {
  perPersonBase: 29.90,
  perPersonExtraHour: 14.95,
  minPersons: 10,
  baseHours: 2,
  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,
};

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

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

function calcTotal(state) {
  const persons = Math.max(PRICING.minPersons, state.persons || 0);
  const hours = Math.max(PRICING.baseHours, state.hours || PRICING.baseHours);
  const extraHours = hours - PRICING.baseHours;

  const lines = [];

  const personSubtotal =
    persons * PRICING.perPersonBase +
    persons * extraHours * PRICING.perPersonExtraHour;
  lines.push({
    label: window.tt("ffb.line.base", { persons, price: fmtEUR(PRICING.perPersonBase), hours: PRICING.baseHours }),
    amount: persons * PRICING.perPersonBase,
  });
  if (extraHours > 0) {
    lines.push({
      label: window.tt("ffb.line.extra_hours", { n: extraHours, persons, price: fmtEUR(PRICING.perPersonExtraHour) }),
      amount: persons * extraHours * PRICING.perPersonExtraHour,
    });
  }

  if (state.drinks) {
    const amt = Math.max(0, state.drinksBudget || 0);
    lines.push({ label: window.t("ffb.line.drinks"), amount: amt });
  }

  if (state.music === "dj") {
    lines.push({ label: window.t("ffb.line.dj"), amount: PRICING.dj });
  } else if (state.music === "own") {
    lines.push({ label: window.t("ffb.line.own_music"), amount: PRICING.ownMusic });
  }

  if (state.customBalls && state.customBallsAmount >= PRICING.customBallsPackSize) {
    const packs = Math.ceil(state.customBallsAmount / PRICING.customBallsPackSize);
    const amt = packs * PRICING.customBallsPack;
    lines.push({
      label: window.tt("ffb.line.custom_balls", { n: packs * PRICING.customBallsPackSize }),
      amount: amt,
    });
  }

  if (state.giftBalls) {
    const amt = persons * PRICING.customBallsGiftPerPerson;
    lines.push({ label: window.tt("ffb.line.gift_balls", { persons }), amount: amt });
  }

  if (state.coach) {
    const amt = hours * PRICING.coachPerHour;
    lines.push({ label: window.tt("ffb.line.coach", { hours }), amount: amt });
  }

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

function SubHero() {
  return (
    <section className="sub-hero">
      <div className="inner">
        <div>
          <div className="crumbs">
            <a href="index.html">{window.t("ff.crumb_book")}</a>
            <span className="sep">/</span>
            <a href="firmenfeier.html">{window.t("ff.crumb")}</a>
            <span className="sep">/</span>
            <span>{window.t("ffb.crumb_buchen")}</span>
          </div>
          <h1>
            {window.t("ffb.title_pre")}<br/>
            <span className="alt">{window.t("ffb.title_alt")}</span>
          </h1>
          <p className="lede">
            {window.t("ff_buchung.lede")}
          </p>
        </div>
        <div className="photo" style={{ backgroundImage: "url('assets/sub-firmenfeier.webp')", backgroundSize: "cover", backgroundPosition: "center" }}>
        </div>
      </div>
    </section>
  );
}

function FormRow({ 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 AddonToggle({ 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 BookingForm() {
  const [persons, setPersons] = useState(PRICING.minPersons);
  const [hours, setHours] = useState(PRICING.baseHours);
  const [date, setDate] = useState("");
  const [time, setTime] = useState("18:00");

  const [drinks, setDrinks] = useState(false);
  const [drinksBudget, setDrinksBudget] = useState(PRICING.drinksBudgetDefault);
  const [music, setMusic] = useState("none");
  const [customBalls, setCustomBalls] = useState(false);
  const [customBallsAmount, setCustomBallsAmount] = useState(PRICING.customBallsPackSize);
  const [customBallsLogo, setCustomBallsLogo] = useState(null);
  const [customBallsLogoName, setCustomBallsLogoName] = useState("");
  const [customBallsNote, setCustomBallsNote] = useState("");
  const [giftBalls, setGiftBalls] = useState(false);
  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 needsCustomBallsLead = customBalls || giftBalls;
  const minDate = useMemo(
    () =>
      todayPlusDays(
        needsCustomBallsLead
          ? Math.max(PRICING.minLeadDaysDefault, PRICING.minLeadDaysCustomBalls)
          : PRICING.minLeadDaysDefault,
      ),
    [needsCustomBallsLead],
  );

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

  const showLogoUpload = customBalls || giftBalls;

  const calc = useMemo(
    () =>
      calcTotal({
        persons,
        hours,
        drinks,
        drinksBudget,
        music,
        customBalls,
        customBallsAmount,
        giftBalls,
        coach,
      }),
    [persons, hours, drinks, drinksBudget, music, customBalls, customBallsAmount, giftBalls, 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 < PRICING.minPersons) e.persons = window.tt("ffb.err.persons_min", { n: PRICING.minPersons });
    if (hours < PRICING.baseHours) e.hours = window.tt("ffb.err.hours_min", { n: PRICING.baseHours });
    if (customBalls && customBallsAmount < PRICING.customBallsPackSize) {
      e.customBallsAmount = window.tt("ffb.err.balls_min", { n: PRICING.customBallsPackSize });
    }
    if (showLogoUpload && !customBallsLogo) {
      e.customBallsLogo = window.t("ffb.err.logo_required");
    }
    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 (!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;
  }

  function handleLogoUpload(file) {
    if (!file) {
      setCustomBallsLogo(null);
      setCustomBallsLogoName("");
      return;
    }
    if (file.size > 5 * 1024 * 1024) {
      setErrors((p) => ({ ...p, customBallsLogo: window.t("ffb.err.logo_size") }));
      return;
    }
    const reader = new FileReader();
    reader.onload = () => {
      setCustomBallsLogo({
        filename: file.name,
        mimeType: file.type || "application/octet-stream",
        base64: String(reader.result).split(",")[1] || "",
      });
      setCustomBallsLogoName(file.name);
      setErrors((p) => {
        const n = { ...p };
        delete n.customBallsLogo;
        return n;
      });
    };
    reader.readAsDataURL(file);
  }

  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: "firmenfeier",
        submittedAt: new Date().toISOString(),
        event: { date, time, persons, hours },
        options: {
          drinks: drinks ? { budget: Math.max(0, drinksBudget || 0) } : false,
          music,
          customBalls: customBalls ? { amount: customBallsAmount, note: customBallsNote } : null,
          giftBalls,
          robot,
          coach,
        },
        logo: customBallsLogo,
        contact: {
          firstName: contactFirst,
          lastName: contactLast,
          email: contactEmail,
          phone: contactPhone,
        },
        billing: {
          company,
          street: billingStreet,
          zip: billingZip,
          city: billingCity,
          vatId,
        },
        notes,
        pricing: {
          lines: calc.lines,
          totalNet: calc.total,
        },
        lang: window.currentLang || "de",
      };
      const res = await fetch(BOOKING_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="firmenfeier.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: PRICING.baseHours, days: PRICING.minLeadDaysDefault })}
        </p>

        <div className="form-grid form-grid-2">
          <FormRow label={window.t("ffb.lbl.date")} error={errors.date}>
            <input
              type="date"
              value={date}
              min={minDate}
              onChange={(e) => setDate(e.target.value)}
            />
          </FormRow>
          <FormRow label={window.t("ffb.lbl.time")} error={errors.time}>
            <input
              type="time"
              value={time}
              step="900"
              onChange={(e) => setTime(e.target.value)}
            />
          </FormRow>
          <FormRow
            label={window.t("ffb.lbl.persons")}
            hint={window.tt("ffb.hint.persons", { n: PRICING.minPersons })}
            error={errors.persons}
          >
            <input
              type="number"
              inputMode="numeric"
              min={PRICING.minPersons}
              step="1"
              value={persons}
              onChange={(e) => setPersons(parseInt(e.target.value || "0", 10))}
            />
          </FormRow>
          <FormRow
            label={window.t("ffb.lbl.hours")}
            hint={window.tt("ffb.hint.hours", { n: PRICING.baseHours, price: fmtEUR(PRICING.perPersonExtraHour) })}
            error={errors.hours}
          >
            <input
              type="number"
              inputMode="numeric"
              min={PRICING.baseHours}
              step="1"
              value={hours}
              onChange={(e) => setHours(parseInt(e.target.value || "0", 10))}
            />
          </FormRow>
        </div>
      </div>

      {/* ============ OPTIONEN ============ */}
      <div className="form-step">
        <h2>{window.t("ffb.s2.h2")}</h2>

        <div className="addons">
          <AddonToggle
            id="drinks"
            title={window.t("ffb.addon.drinks.title")}
            price={drinks ? fmtEUR(Math.max(0, drinksBudget || 0)) : window.t("ffb.price.budget")}
            checked={drinks}
            onChange={setDrinks}
          >
            {drinks && (
              <FormRow
                label={window.t("ffb.addon.drinks.amount_label")}
                hint={window.t("ffb.addon.drinks.hint")}
              >
                <input
                  type="number"
                  inputMode="numeric"
                  min={PRICING.drinksBudgetMin}
                  step={PRICING.drinksBudgetStep}
                  value={drinksBudget}
                  onChange={(e) => setDrinksBudget(parseInt(e.target.value || "0", 10))}
                />
              </FormRow>
            )}
          </AddonToggle>

          <AddonToggle
            id="dj"
            title={window.t("ffb.addon.dj.title")}
            price={window.tt("ffb.price.flat", { eur: fmtEUR(PRICING.dj) })}
            checked={music === "dj"}
            onChange={(v) => setMusic(v ? "dj" : "none")}
            disabled={music === "own"}
          />

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

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

          <AddonToggle
            id="gift-balls"
            title={window.t("ffb.addon.gift_balls.title")}
            price={window.tt("ffb.price.per_person", { eur: fmtEUR(PRICING.customBallsGiftPerPerson) })}
            checked={giftBalls}
            onChange={setGiftBalls}
          />

          <AddonToggle
            id="robot"
            title={window.t("ffb.addon.robot.title")}
            price={window.t("ffb.addon.free")}
            checked={robot}
            onChange={setRobot}
          />

          <AddonToggle
            id="coach"
            title={window.tt("ffb.addon.coach.title", { hours })}
            price={window.tt("ffb.price.per_hour", { eur: fmtEUR(PRICING.coachPerHour) })}
            checked={coach}
            onChange={setCoach}
          />

          <div className="addon checked replays-info">
            <div className="addon-body">
              <div className="addon-head">
                <span className="addon-title">{window.t("ffb.addon.replays.title")}</span>
                <span className="addon-price">{window.t("ffb.addon.free")}</span>
              </div>
              <div className="addon-extra">
                {window.t("ffb.addon.replays.body")}
              </div>
            </div>
          </div>
        </div>

        {showLogoUpload && (
          <div className="logo-upload">
            <h3>{window.t("ffb.logo.h3")}</h3>
            <FormRow
              label={window.t("ffb.logo.lbl")}
              error={errors.customBallsLogo}
              hint={customBallsLogoName ? window.tt("ffb.logo.uploaded", { name: customBallsLogoName }) : null}
            >
              <input
                type="file"
                accept="image/png,image/jpeg,image/svg+xml"
                onChange={(e) => handleLogoUpload(e.target.files?.[0] || null)}
              />
            </FormRow>
            <FormRow
              label={window.t("ffb.logo.note_lbl")}
              hint={window.t("ffb.logo.note_hint")}
            >
              <textarea
                rows={3}
                value={customBallsNote}
                onChange={(e) => setCustomBallsNote(e.target.value)}
              />
            </FormRow>
          </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">
          <FormRow label={window.t("ffb.lbl.first_name")} error={errors.contactFirst}>
            <input value={contactFirst} onChange={(e) => setContactFirst(e.target.value)} autoComplete="given-name" />
          </FormRow>
          <FormRow label={window.t("ffb.lbl.last_name")} error={errors.contactLast}>
            <input value={contactLast} onChange={(e) => setContactLast(e.target.value)} autoComplete="family-name" />
          </FormRow>
          <FormRow label={window.t("ffb.lbl.email")} error={errors.contactEmail}>
            <input
              type="email"
              inputMode="email"
              autoComplete="email"
              value={contactEmail}
              onChange={(e) => setContactEmail(e.target.value)}
            />
          </FormRow>
          <FormRow label={window.t("ffb.lbl.phone")}>
            <input
              type="tel"
              inputMode="tel"
              autoComplete="tel"
              value={contactPhone}
              onChange={(e) => setContactPhone(e.target.value)}
            />
          </FormRow>
        </div>

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

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

      {/* ============ SUMMARY + CHECKOUT ============ */}
      <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>{fmtEUR(l.amount)}</span>
            </li>
          ))}
        </ul>
        <div className="price-total">
          <span>{window.t("ffb.summary.total")}</span>
          <span>{fmtEUR(calc.total)}</span>
        </div>
        <p className="form-note">
          {window.t("ffb.summary.tax_note")}
        </p>

        <FormRow 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>
        </FormRow>

        <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>
  );
}

function App() {
  useEffect(() => {
    document.title = window.t("page.title.firmenfeier");
  }, []);
  return (
    <>
      <TopBar />
      <Header active="firmenfeiern" />
      <SubHero />
      <BookingForm />
      <Footer />
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
