/* Volaire — /booking: 6-step wizard, summary rail, protection slot #1, confirmation */
const { loadDraft, saveDraft, clearDraft } = window.VolaireDraft;

/* ---------- reducer ---------- */
function bookingReducer(state, action) {
  switch (action.type) {
    case 'SET_STEP': return Object.assign({}, state, { step: action.step });
    case 'SET_FLIGHTS': return Object.assign({}, state, { outbound: action.outbound, inbound: action.inbound, tripType: action.tripType });
    case 'SET_FARE': return Object.assign({}, state, { fareFamily: action.fareFamily });
    case 'SET_PASSENGER': return Object.assign({}, state, { passenger: Object.assign({}, state.passenger, action.passenger) });
    case 'SET_TRAVELER': {
      const list = (state.travelers || []).slice();
      list[action.index] = Object.assign({}, list[action.index], action.patch);
      return Object.assign({}, state, { travelers: list });
    }
    case 'SET_TRAVELER_BOOKER': {
      // At most one traveller is the booker.
      const list = (state.travelers || []).map(function (tr, i) {
        return Object.assign({}, tr, { isBooker: action.on && i === action.index });
      });
      return Object.assign({}, state, { travelers: list });
    }
    case 'SET_SEAT': {
      const tid = action.seat.travelerId || 'holder';
      const seats = state.seats.filter(function (s) { return !(s.flightId === action.seat.flightId && (s.travelerId || 'holder') === tid); });
      if (action.seat.seat) seats.push(Object.assign({ travelerId: tid }, action.seat));
      return Object.assign({}, state, { seats: seats });
    }
    case 'SET_EXTRAS': return Object.assign({}, state, { extras: Object.assign({}, state.extras, action.extras) });
    case 'ATTACH_PROTECTION': return Object.assign({}, state, { protection: action.protection });
    case 'REMOVE_PROTECTION': return Object.assign({}, state, { protection: null });
    case 'SET_PAYMENT': return Object.assign({}, state, action.payload);
    case 'CONFIRM_BOOKING': return Object.assign({}, state, { step: 'success', pnr: action.pnr });
    case 'RESET': return JSON.parse(JSON.stringify(window.VolaireDraft.EMPTY_DRAFT));
    default: return state;
  }
}

function useBookingDraft() {
  const [draft, dispatch] = React.useReducer(bookingReducer, null, loadDraft);
  useEffect(function () { saveDraft(draft); }, [draft]);
  return [draft, dispatch];
}

/* ---------- totals ---------- */
function flightCount(d) { return d.inbound ? 2 : 1; }
function paxTotal(d) { return window.VolaireDraft.paxCount(d.pax); }
function fareTotal(d) {
  if (!d.outbound || !d.fareFamily) return 0;
  let perPax = d.outbound.fares[d.fareFamily].price;
  if (d.inbound) perPax += d.inbound.fares[d.fareFamily].price;
  return perPax * paxTotal(d);
}
function seatsTotal(d) { return d.seats.reduce(function (s, x) { return s + (x.fee || 0); }, 0); }
function extrasTotal(d) {
  const n = flightCount(d), e = d.extras, P = L.OPTION_PRICES, inc = L.FARE_RULES[d.fareFamily || 'light'];
  let s = 0;
  if (!inc.checkedBag) s += (e.checkedBags || 0) * P.checkedBag * n;
  s += (e.extraBags || 0) * P.extraBag * n;
  if (e.priority && !inc.priority) s += P.priority * n;
  if (e.meal) s += P.meal * n;
  if (e.sportsEquipment) s += P.sports;
  return s;
}
function bookingTotal(d) { return fareTotal(d) + seatsTotal(d) + extrasTotal(d); }

/* ---------- progress bar ---------- */
const STEP_KEYS = ['booking.step1', 'booking.step2', 'booking.step3', 'booking.step4', 'booking.step5', 'booking.step6'];
function ProgressBar({ step, onJump }) {
  const { t } = useLang();
  const cur = step === 'success' ? 7 : step;
  return (
    <ol className="flex flex-wrap items-center gap-x-1 gap-y-2" aria-label={t('booking.title')}>
      {STEP_KEYS.map(function (k, i) {
        const n = i + 1, done = cur > n, active = cur === n;
        return (
          <li key={k} className="flex items-center gap-1">
            <button disabled={!done} onClick={function () { if (done) onJump(n); }}
              aria-current={active ? 'step' : undefined}
              className={'flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-semibold sm:text-[13px] ' +
                (active ? 'bg-cobalt text-white' : done ? 'text-cobalt hover:bg-cobalt/10' : 'text-muted/60')}>
              <span className={'flex h-4.5 w-4.5 items-center justify-center ' + (done ? 'text-success' : '')}>
                {done ? <Icon name="check" size={14}></Icon> : <span className="tabular-nums">{n}</span>}
              </span>
              <span className="hidden sm:inline">{t(k)}</span>
            </button>
            {n < 6 ? <span className="h-px w-3 bg-line sm:w-5"></span> : null}
          </li>
        );
      })}
    </ol>
  );
}

/* ---------- summary rail ---------- */
function SummaryFlightLine({ f, fare }) {
  return (
    <div className="flex items-center justify-between gap-2 text-sm">
      <span className="flex items-center gap-1.5 tabular-nums text-ink">
        <span className="font-semibold">{f.origin}</span>
        <Icon name="arrowRight" size={12} className="text-muted"></Icon>
        <span className="font-semibold">{f.destination}</span>
        <span className="text-xs text-muted">{L.fmtTime(f.departTime)}</span>
      </span>
      <span className="font-semibold tabular-nums">{L.fmtEUR(f.fares[fare].price)}</span>
    </div>
  );
}
function SummaryRail({ draft, mobileCta, onCta, ctaLabel, ctaDisabled }) {
  const { t } = useLang();
  const [openMobile, setOpenMobile] = useState(false);
  const total = bookingTotal(draft);
  const body = (
    <div className="flex flex-col gap-3">
      <h2 className="text-sm font-bold uppercase tracking-wider text-muted">{t('booking.summary.title')}</h2>
      {draft.outbound ? (
        <div className="flex flex-col gap-1.5 border-b border-line pb-3">
          <SummaryFlightLine f={draft.outbound} fare={draft.fareFamily}></SummaryFlightLine>
          {draft.inbound ? <SummaryFlightLine f={draft.inbound} fare={draft.fareFamily}></SummaryFlightLine> : null}
          <div className="mt-1 flex items-center justify-between">
            <FareFamilyPill fare={draft.fareFamily}></FareFamilyPill>
            <span className="text-xs text-muted">× {paxTotal(draft)} {paxTotal(draft) === 1 ? t('pax.count.one').replace(/^1\s*/, '') : t('pax.title').toLowerCase()}</span>
          </div>
        </div>
      ) : null}
      {seatsTotal(draft) > 0 || draft.seats.length ? (
        <div className="flex items-center justify-between border-b border-line pb-3 text-sm">
          <span className="text-muted">{t('booking.summary.seats')} <span className="tabular-nums">{draft.seats.map(function (s) { return s.seat; }).join(' · ')}</span></span>
          <span className="font-semibold tabular-nums">{seatsTotal(draft) ? L.fmtEUR(seatsTotal(draft)) : t('booking.seats.included')}</span>
        </div>
      ) : null}
      {extrasTotal(draft) > 0 ? (
        <div className="flex items-center justify-between border-b border-line pb-3 text-sm">
          <span className="text-muted">{t('booking.summary.options')}</span>
          <span className="font-semibold tabular-nums">{L.fmtEUR(extrasTotal(draft))}</span>
        </div>
      ) : null}
      {draft.protection ? (
        <div className="flex items-start justify-between gap-2 border-b border-line pb-3 text-sm">
          <span className="flex items-center gap-1.5 text-muted"><Icon name="shield" size={14} className="text-success"></Icon>{t('booking.summary.protection')}</span>
          <span className="text-right">
            <span className="block font-semibold tabular-nums">{L.fmtEUR(draft.protection.premium)}</span>
            <span className="block text-xs text-muted">{t('booking.summary.protection.separate')}</span>
          </span>
        </div>
      ) : null}
      <div className="flex items-baseline justify-between" aria-live="polite">
        <span className="text-sm font-bold text-ink">{t('booking.summary.total')}</span>
        <span className="text-2xl font-bold tabular-nums tracking-tight text-ink">{L.fmtEUR(total)}</span>
      </div>
    </div>
  );
  return (
    <React.Fragment>
      <aside className="hidden lg:block">
        <div className="sticky top-36 rounded-xl border border-line bg-white p-5">{body}</div>
      </aside>
      {/* mobile collapsible bottom bar */}
      <div className="fixed bottom-0 left-0 right-0 z-40 border-t border-line bg-white lg:hidden">
        {openMobile ? <div className="border-b border-line p-4">{body}</div> : null}
        <div className="flex items-center justify-between gap-3 px-4 py-3">
          <button className="flex items-center gap-1 text-left" onClick={function () { setOpenMobile(!openMobile); }} aria-expanded={openMobile}>
            <div>
              <p className="text-[11px] font-semibold uppercase tracking-wide text-muted">{t('booking.summary.total')}</p>
              <p className="text-lg font-bold tabular-nums text-ink">{L.fmtEUR(total)}</p>
            </div>
            <Icon name="chevronDown" size={16} className={'text-muted ' + (openMobile ? '' : 'rotate-180')}></Icon>
          </button>
          {mobileCta ? (
            <button onClick={onCta} disabled={ctaDisabled}
              className="rounded-lg bg-cobalt px-6 py-2.5 text-sm font-bold text-white disabled:opacity-40">{ctaLabel || t('common.continue')}</button>
          ) : null}
        </div>
      </div>
    </React.Fragment>
  );
}

/* ---------- step footer ---------- */
function StepFooter({ onBack, onNext, nextLabel, nextDisabled }) {
  const { t } = useLang();
  return (
    <div className="mt-6 flex items-center justify-between gap-3">
      {onBack ? (
        <button onClick={onBack} className="rounded-lg px-4 py-3 text-sm font-semibold text-muted hover:bg-white hover:text-ink">
          ← {t('common.back')}
        </button>
      ) : <span></span>}
      <button onClick={onNext} disabled={nextDisabled}
        className="w-full rounded-lg bg-cobalt px-8 py-3 text-sm font-bold text-white transition-colors hover:bg-cobaltDark disabled:cursor-not-allowed disabled:opacity-40 sm:w-auto">
        {nextLabel || t('common.continue')}
      </button>
    </div>
  );
}

/* ---------- step 1: flights review ---------- */
function FlightRecap({ f, fare, label }) {
  const { t, lang } = useLang();
  return (
    <div className="rounded-xl border border-line bg-white p-4">
      <div className="flex items-center justify-between gap-2">
        <span className="text-xs font-bold uppercase tracking-wider text-muted">{label}</span>
        <Link to="/search" className="text-sm font-semibold text-cobalt hover:underline">{t('common.edit')}</Link>
      </div>
      <div className="mt-2 flex flex-wrap items-center gap-x-5 gap-y-2">
        <p className="text-xl font-bold tabular-nums tracking-tight text-ink">
          {L.fmtTime(f.departTime)} {f.origin} <span className="font-normal text-muted">→</span> {L.fmtTime(f.arriveTime)} {f.destination}
        </p>
        <FareFamilyPill fare={fare}></FareFamilyPill>
      </div>
      <p className="mt-1 text-sm capitalize text-muted">{L.fmtDateLong(f.departTime, lang)} · {f.flightNumber} · {f.aircraft} · {L.fmtDuration(f.durationMin)}</p>
    </div>
  );
}
function Step1Flights({ draft, dispatch }) {
  const { t } = useLang();
  return (
    <div>
      <h1 className="text-2xl font-bold tracking-tight text-ink">{t('booking.step1.title')}</h1>
      <div className="mt-4 flex flex-col gap-3">
        <FlightRecap f={draft.outbound} fare={draft.fareFamily} label={t('booking.seats.outbound')}></FlightRecap>
        {draft.inbound ? <FlightRecap f={draft.inbound} fare={draft.fareFamily} label={t('booking.seats.return')}></FlightRecap> : null}
      </div>
      <StepFooter onNext={function () { dispatch({ type: 'SET_STEP', step: 2 }); }}></StepFooter>
    </div>
  );
}

/* ---------- step 2: booker + travellers ---------- */
function bandLabelKey(band) { return band === 'under_18' ? 'child' : band === 'from_65' ? 'senior' : 'adult'; }
// One traveller (insured person) identity card, numbered globally 1..N. An
// adult traveller can be flagged as the booking holder (checkbox); when it is,
// its identity comes from the booker and the fields are hidden.
function TravelerCard({ n, traveler, onPatch, onToggleBooker }) {
  const { t } = useLang();
  const v = traveler || {};
  const band = v.band;
  const isAdult = band === 'adults';
  const dob = band === 'under_18'
    ? { max: L.todayISO(0), min: L.addDays(L.todayISO(0), -18 * 365) }
    : band === 'from_65'
      ? { max: L.addDays(L.todayISO(0), -65 * 365), min: null }
      : { max: L.todayISO(0), min: null };
  return (
    <div className="rounded-xl border border-line bg-white p-4">
      <div className="flex items-center gap-2">
        <span className="flex h-7 w-7 items-center justify-center rounded-full bg-cobalt/10 text-cobalt text-xs font-bold">{n}</span>
        <p className="text-sm font-bold text-ink">{t('booking.passenger.travelerN').replace('{n}', n)}</p>
        <Badge variant="neutral" className="ml-auto">{t('booking.passenger.' + bandLabelKey(band))}</Badge>
      </div>
      {isAdult ? (
        <label className="mt-3 flex cursor-pointer items-center gap-2.5 text-sm text-ink">
          <input type="checkbox" checked={!!v.isBooker} className="h-4 w-4 rounded border-line text-cobalt focus:ring-cobalt"
            onChange={function (e) { onToggleBooker(e.target.checked); }} />
          {t('booking.passenger.sameAsBooker')}
        </label>
      ) : null}
      {v.isBooker ? (
        <p className="mt-3 flex items-center gap-2 rounded-lg bg-cobalt/5 px-3 py-2 text-sm text-muted"><Icon name="user" size={14} className="text-cobalt"></Icon>{t('booking.passenger.usesBookerDetails')}</p>
      ) : (
        <div className="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-3">
          <Field label={t('booking.passenger.firstName')}>
            <input className={inputCls} value={v.firstName || ''} required onChange={function (e) { onPatch({ firstName: e.target.value }); }} />
          </Field>
          <Field label={t('booking.passenger.lastName')}>
            <input className={inputCls} value={v.lastName || ''} required onChange={function (e) { onPatch({ lastName: e.target.value }); }} />
          </Field>
          <Field label={t('booking.passenger.dateOfBirth')}>
            <input type="date" className={inputCls + ' tabular-nums'} value={v.dateOfBirth || ''} required max={dob.max} min={dob.min || undefined} onChange={function (e) { onPatch({ dateOfBirth: e.target.value }); }} />
          </Field>
        </div>
      )}
    </div>
  );
}
function Step2Passenger({ draft, dispatch }) {
  const { t } = useLang();
  const session = useSession();
  const p = draft.passenger;
  const travelers = draft.travelers || [];
  function set(k, v) { dispatch({ type: 'SET_PASSENGER', passenger: (function () { const o = {}; o[k] = v; return o; })() }); }
  const bookerValid = p.firstName && p.lastName && p.dateOfBirth && p.email && p.phone;
  const travelersValid = travelers.every(function (tr) { return tr.isBooker || (tr.firstName && tr.lastName && tr.dateOfBirth); });
  const valid = bookerValid && travelersValid;
  return (
    <div>
      <h1 className="text-2xl font-bold tracking-tight text-ink">{t('booking.passenger.title')}</h1>
      <p className="mt-1 text-sm text-muted">{t('booking.passenger.note')}</p>

      <form className="mt-4 flex flex-col gap-3" onSubmit={function (e) { e.preventDefault(); if (valid) dispatch({ type: 'SET_STEP', step: 3 }); }}>
        {/* booker (booking + policy holder, an adult) */}
        <div className="rounded-xl border border-line bg-white p-5">
          <div className="flex items-center gap-2">
            <span className="flex h-7 w-7 items-center justify-center rounded-full bg-cobalt text-white"><Icon name="user" size={15}></Icon></span>
            <p className="text-sm font-bold text-ink">{t('booking.passenger.bookerTitle')}</p>
            <Badge variant="cobaltSoft" className="ml-auto">{t('booking.passenger.adult')}</Badge>
          </div>
          <p className="mt-1 text-xs text-muted">{t('booking.passenger.bookerNote')}</p>
          <div className="mt-3 grid grid-cols-1 gap-4 sm:grid-cols-6">
            <Field label={t('booking.passenger.salutation')} className="sm:col-span-1">
              <select className={inputCls} value={p.salutation} onChange={function (e) { set('salutation', e.target.value); }}>
                <option value="Mme">{t('booking.passenger.mrs')}</option>
                <option value="M.">{t('booking.passenger.mr')}</option>
              </select>
            </Field>
            <Field label={t('booking.passenger.firstName')} className="sm:col-span-2">
              <input className={inputCls} value={p.firstName} required autoComplete="given-name" onChange={function (e) { set('firstName', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.lastName')} className="sm:col-span-3">
              <input className={inputCls} value={p.lastName} required autoComplete="family-name" onChange={function (e) { set('lastName', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.dateOfBirth')} className="sm:col-span-3">
              <input type="date" className={inputCls + ' tabular-nums'} value={p.dateOfBirth} required max={L.todayISO(0)} onChange={function (e) { set('dateOfBirth', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.nationality')} className="sm:col-span-3">
              <input className={inputCls} value={p.nationality} placeholder="Française" onChange={function (e) { set('nationality', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.email')} className="sm:col-span-3">
              <input type="email" className={inputCls} value={p.email} required autoComplete="email" onChange={function (e) { set('email', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.phone')} className="sm:col-span-3">
              <input type="tel" className={inputCls + ' tabular-nums'} value={p.phone} required autoComplete="tel" onChange={function (e) { set('phone', e.target.value); }} />
            </Field>
            <Field label={t('booking.passenger.loyalty')} className="sm:col-span-3">
              <input className={inputCls + ' tabular-nums'} value={p.loyaltyNumber} placeholder="VC 000 000" onChange={function (e) { set('loyaltyNumber', e.target.value); }} />
            </Field>
          </div>
          {!session ? (
            <label className="mt-4 flex cursor-pointer items-start gap-2.5 text-sm text-ink">
              <input type="checkbox" checked={!!p.createAccount} className="mt-0.5 h-4 w-4 rounded border-line text-cobalt focus:ring-cobalt"
                onChange={function (e) { set('createAccount', e.target.checked); }} />
              {t('booking.passenger.createAccount')}
            </label>
          ) : null}
        </div>

        {/* travellers (insured), numbered 1..N */}
        {travelers.length ? (
          <h2 className="mt-2 text-xs font-bold uppercase tracking-wider text-muted">{t('booking.passenger.travelersTitle')}</h2>
        ) : null}
        {travelers.map(function (tr, i) {
          return (
            <TravelerCard key={i} n={i + 1} traveler={tr}
              onPatch={function (patch) { dispatch({ type: 'SET_TRAVELER', index: i, patch: patch }); }}
              onToggleBooker={function (on) { dispatch({ type: 'SET_TRAVELER_BOOKER', index: i, on: on }); }}></TravelerCard>
          );
        })}

        <StepFooter onBack={function () { dispatch({ type: 'SET_STEP', step: 1 }); }}
          onNext={function () { if (valid) dispatch({ type: 'SET_STEP', step: 3 }); }} nextDisabled={!valid}></StepFooter>
      </form>
    </div>
  );
}

/* ---------- step 3: seats (one seat per traveller per leg) ---------- */
function trInitials(tr) {
  return ((tr.firstName || 'V')[0] + (tr.lastName || (tr.id[0] || 'L'))[0]).toUpperCase();
}
function trName(tr, i, t) {
  if (tr.firstName || tr.lastName) return (tr.firstName + ' ' + tr.lastName).trim();
  return t('booking.seats.traveler') + ' ' + (i + 1);
}
function Step3Seats({ draft, dispatch }) {
  const { t } = useLang();
  const travelers = window.VolaireDraft.travelerList(draft);
  const [tab, setTab] = useState('out');
  const [travelerIdx, setTravelerIdx] = useState(0);
  const legs = [{ id: 'out', f: draft.outbound, label: t('booking.seats.outbound') }];
  if (draft.inbound) legs.push({ id: 'in', f: draft.inbound, label: t('booking.seats.return') });
  const leg = legs.find(function (x) { return x.id === tab; }) || legs[0];
  const tr = travelers[travelerIdx] || travelers[0];
  const sel = draft.seats.find(function (s) { return s.flightId === leg.id && (s.travelerId || 'holder') === tr.id; });
  // Seats taken by OTHER travellers on this leg (block double-booking).
  const taken = draft.seats.filter(function (s) { return s.flightId === leg.id && (s.travelerId || 'holder') !== tr.id; }).map(function (s) { return s.seat; });
  function pick(seatId, fee) { dispatch({ type: 'SET_SEAT', seat: { flightId: leg.id, travelerId: tr.id, seat: seatId, fee: fee } }); }
  return (
    <div>
      <h1 className="text-2xl font-bold tracking-tight text-ink">{t('booking.seats.title')}</h1>
      {/* traveller selector */}
      {travelers.length > 1 ? (
        <div role="tablist" aria-label={t('booking.passenger.travelersTitle')} className="mt-3 flex flex-wrap gap-1.5">
          {travelers.map(function (x, i) {
            const anySeat = draft.seats.some(function (s) { return (s.travelerId || 'holder') === x.id; });
            return (
              <button key={x.id} role="tab" aria-selected={travelerIdx === i}
                className={'flex items-center gap-1.5 rounded-lg border px-3 py-1.5 text-sm font-medium ' + (travelerIdx === i ? 'border-cobalt bg-cobalt/10 text-cobalt' : 'border-line text-ink hover:border-cobalt/50')}
                onClick={function () { setTravelerIdx(i); }}>
                <span className="flex h-5 w-5 items-center justify-center rounded-full bg-cobalt/15 text-[10px] font-bold text-cobalt">{trInitials(x)}</span>
                {trName(x, i, t)}
                {anySeat ? <Icon name="check" size={13} className="text-success"></Icon> : null}
              </button>
            );
          })}
        </div>
      ) : null}
      {legs.length > 1 ? (
        <div role="tablist" className="mt-3 flex w-fit rounded-lg border border-line bg-white p-0.5">
          {legs.map(function (lg) {
            const s = draft.seats.find(function (x) { return x.flightId === lg.id && (x.travelerId || 'holder') === tr.id; });
            return (
              <button key={lg.id} role="tab" aria-selected={tab === lg.id}
                className={'rounded-md px-4 py-1.5 text-sm font-medium ' + (tab === lg.id ? 'bg-cobalt text-white' : 'text-muted hover:text-ink')}
                onClick={function () { setTab(lg.id); }}>
                {lg.label}{s ? <span className="ml-1.5 tabular-nums opacity-80">{s.seat}</span> : null}
              </button>
            );
          })}
        </div>
      ) : null}
      <div className="mt-4 rounded-xl border border-line bg-white p-4 sm:p-5">
        <div className="flex flex-wrap items-center justify-between gap-2">
          <p className="text-sm text-muted">{leg.f.flightNumber} · {leg.f.origin} → {leg.f.destination} · {trName(tr, travelerIdx, t)}</p>
          <p className="text-sm font-semibold text-ink" aria-live="polite">
            {sel ? t('booking.seats.selected') + ' : ' : ''}<span className="tabular-nums text-cobalt">{sel ? sel.seat : ''}</span>
            {sel ? <span className="text-muted"> · {sel.fee ? L.fmtEUR(sel.fee) : t('booking.seats.included')}</span> : null}
          </p>
        </div>
        <div className="mt-4">
          <SeatMap flight={leg.f} fareFamily={draft.fareFamily} selected={sel ? sel.seat : null} taken={taken} onSelect={pick} initials={trInitials(tr)}></SeatMap>
        </div>
        <div className="mt-4 flex flex-wrap items-center gap-3 border-t border-line pt-4">
          <button className="rounded-lg border border-line px-4 py-2 text-sm font-semibold text-ink hover:border-cobalt"
            onClick={function () {
              legs.forEach(function (lg) { travelers.forEach(function (x) { dispatch({ type: 'SET_SEAT', seat: { flightId: lg.id, travelerId: x.id, seat: null } }); }); });
              showToast(t('booking.seats.chooseForMe.note'));
            }}>
            {t('booking.seats.chooseForMe')}
          </button>
          <span className="text-xs text-muted">{t('booking.seats.chooseForMe.note')}</span>
        </div>
      </div>
      <StepFooter onBack={function () { dispatch({ type: 'SET_STEP', step: 2 }); }}
        onNext={function () {
          // Advance across travellers/legs before leaving the step.
          if (sel && legs.length > 1 && tab === 'out' && !draft.seats.find(function (s) { return s.flightId === 'in' && (s.travelerId || 'holder') === tr.id; })) { setTab('in'); return; }
          if (sel && travelerIdx < travelers.length - 1) { setTravelerIdx(travelerIdx + 1); setTab('out'); return; }
          dispatch({ type: 'SET_STEP', step: 4 });
        }}></StepFooter>
    </div>
  );
}

/* ---------- step 4: options ---------- */
function OptionRow({ icon, title, desc, right, children }) {
  return (
    <div className="flex flex-col gap-3 rounded-xl border border-line bg-white p-4 sm:flex-row sm:items-center">
      <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-cobalt/10 text-cobalt"><Icon name={icon} size={20}></Icon></span>
      <div className="min-w-0 flex-1">
        <p className="font-semibold text-ink">{title}</p>
        <p className="text-sm text-muted">{desc}</p>
      </div>
      <div className="flex shrink-0 items-center gap-3">{right}{children}</div>
    </div>
  );
}
function Stepper({ value, onChange, max }) {
  return (
    <div className="flex items-center gap-1 rounded-lg border border-line">
      <button className="px-3 py-1.5 text-lg font-bold text-muted hover:text-cobalt disabled:opacity-30" disabled={value <= 0}
        onClick={function () { onChange(value - 1); }} aria-label="−">−</button>
      <span className="w-6 text-center text-sm font-bold tabular-nums">{value}</span>
      <button className="px-3 py-1.5 text-lg font-bold text-muted hover:text-cobalt disabled:opacity-30" disabled={value >= (max || 3)}
        onClick={function () { onChange(value + 1); }} aria-label="+">+</button>
    </div>
  );
}
function Toggle({ on, onChange, label }) {
  return (
    <button role="switch" aria-checked={on} aria-label={label}
      className={'relative h-7 w-12 rounded-full transition-colors ' + (on ? 'bg-cobalt' : 'bg-line')}
      onClick={function () { onChange(!on); }}>
      <span className={'absolute top-0.5 h-6 w-6 rounded-full bg-white shadow transition-all ' + (on ? 'left-[22px]' : 'left-0.5')}></span>
    </button>
  );
}
function Step4Options({ draft, dispatch }) {
  const { t } = useLang();
  const e = draft.extras, P = L.OPTION_PRICES, inc = L.FARE_RULES[draft.fareFamily], n = flightCount(draft);
  function set(k, v) { dispatch({ type: 'SET_EXTRAS', extras: (function () { const o = {}; o[k] = v; return o; })() }); }
  const per = ' / ' + t('booking.options.perFlight');
  return (
    <div>
      <h1 className="text-2xl font-bold tracking-tight text-ink">{t('booking.options.title')}</h1>
      <div className="mt-4 flex flex-col gap-3">
        <OptionRow icon="bag" title={t('booking.options.checkedBag')} desc={t('booking.options.checkedBag.desc')}
          right={inc.checkedBag
            ? <Badge variant="success">{t('booking.options.included')}</Badge>
            : <span className="text-sm font-semibold tabular-nums text-ink">{L.fmtEUR(P.checkedBag)}<span className="font-normal text-muted">{per}</span></span>}>
          {!inc.checkedBag ? <Stepper value={e.checkedBags || 0} max={2} onChange={function (v) { set('checkedBags', v); }}></Stepper> : null}
        </OptionRow>
        <OptionRow icon="bag" title={t('booking.options.extraBag')} desc={t('booking.options.extraBag.desc')}
          right={<span className="text-sm font-semibold tabular-nums text-ink">{L.fmtEUR(P.extraBag)}<span className="font-normal text-muted">{per}</span></span>}>
          <Stepper value={e.extraBags || 0} max={2} onChange={function (v) { set('extraBags', v); }}></Stepper>
        </OptionRow>
        <OptionRow icon="planeUp" title={t('booking.options.priority')} desc={t('booking.options.priority.desc')}
          right={inc.priority
            ? <Badge variant="gold">{t('booking.options.included')}</Badge>
            : <span className="text-sm font-semibold tabular-nums text-ink">{L.fmtEUR(P.priority)}<span className="font-normal text-muted">{per}</span></span>}>
          {!inc.priority ? <Toggle on={!!e.priority} onChange={function (v) { set('priority', v); }} label={t('booking.options.priority')}></Toggle> : null}
        </OptionRow>
        <div className="rounded-xl border border-line bg-white p-4">
          <div className="flex items-center gap-3">
            <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-cobalt/10 text-cobalt"><Icon name="meal" size={20}></Icon></span>
            <div className="flex-1">
              <p className="font-semibold text-ink">{t('booking.options.meal')}</p>
              <p className="text-sm text-muted">{t('booking.options.meal.desc')} · <span className="font-semibold tabular-nums text-ink">{L.fmtEUR(P.meal)}</span>{per}</p>
            </div>
          </div>
          <div role="radiogroup" aria-label={t('booking.options.meal')} className="mt-3 flex flex-wrap gap-2">
            {[{ v: null, l: t('booking.options.meal.none') }, { v: 'classic', l: t('booking.options.meal.classic') }, { v: 'vegetarian', l: t('booking.options.meal.vegetarian') }, { v: 'gluten-free', l: t('booking.options.meal.glutenFree') }].map(function (o) {
              const on = (e.meal || null) === o.v;
              return (
                <button key={String(o.v)} role="radio" aria-checked={on}
                  className={'rounded-lg border px-4 py-2 text-sm font-medium ' + (on ? 'border-cobalt bg-cobalt/10 text-cobalt' : 'border-line text-ink hover:border-cobalt/50')}
                  onClick={function () { set('meal', o.v); }}>{o.l}</button>
              );
            })}
          </div>
        </div>
        <OptionRow icon="bike" title={t('booking.options.sports')} desc={t('booking.options.sports.desc')}
          right={<span className="text-sm font-semibold tabular-nums text-ink">{L.fmtEUR(P.sports)}</span>}>
          <Toggle on={!!e.sportsEquipment} onChange={function (v) { set('sportsEquipment', v); }} label={t('booking.options.sports')}></Toggle>
        </OptionRow>
      </div>
      <StepFooter onBack={function () { dispatch({ type: 'SET_STEP', step: 3 }); }}
        onNext={function () { dispatch({ type: 'SET_STEP', step: 5 }); }}></StepFooter>
    </div>
  );
}

Object.assign(window, {
  bookingReducer, useBookingDraft, flightCount, paxTotal, fareTotal, seatsTotal, extrasTotal, bookingTotal,
  ProgressBar, SummaryRail, StepFooter, FlightRecap,
  Step1Flights, Step2Passenger, TravelerCard, Step3Seats, Step4Options, OptionRow, Stepper, Toggle,
});
