// EditBookingDrawer — opens for an existing booking. Partners first see a
// read-only OVERVIEW of the booking, then choose to either Cancel it or
// Amend it (change date / time / party size, add an email or phone number).
//
// Differs from the static design prototype in two ways, both required by the
// live portal:
//   1. Time slots in the amend panel come from LIVE availability
//      (usePpAvailability) for the drafted date × party size, not seed data.
//   2. When the booking's timing (date / time / guests) changes, we run a
//      fresh availability look-up the instant the partner hits "Save changes"
//      and only commit if the chosen slot is still bookable. If it has gone
//      since they opened the drawer, we surface a warning and make them pick
//      another time before the amendment is confirmed.

function EditBookingDrawer({ booking, onClose, onSave, onCancelBooking }) {
  const [mode, setMode] = React.useState('view');       // 'view' | 'amend'
  const [draft, setDraft] = React.useState(null);
  const [savedFlash, setSavedFlash] = React.useState(false);
  const [confirmCancel, setConfirmCancel] = React.useState(false);
  const [openChip, setOpenChip] = React.useState(null);  // 'date' | 'time' | 'guests' | null
  const [check, setCheck] = React.useState({ status: 'idle' }); // idle | checking | gone
  const [saving, setSaving] = React.useState(false);

  // Re-seed the draft + reset to overview whenever a new booking is opened.
  React.useEffect(() => {
    if (booking) {
      setDraft({ ...booking });
      setMode('view');
      setSavedFlash(false);
      setConfirmCancel(false);
      setOpenChip(null);
      setCheck({ status: 'idle' });
      setSaving(false);
    }
  }, [booking && booking.id]);

  React.useEffect(() => {
    if (!booking) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [booking, onClose]);

  // Resolve the venue up front — needed by the availability hook below, which
  // must run on every render (before any early return) to keep hook order
  // stable. Falls back to a name match for locally-created bookings.
  const venue = booking
    ? (venueById(booking.venueId)
        || venueById(VENUES.find(v => v.name === booking.venue)?.id)
        || { name: booking.venue, city: booking.city, operator: booking.operator })
    : {};

  // Live slots for the drafted date × party size. null = loading, [] = none.
  const slots = usePpAvailability(venue, booking && booking.product, draft && draft.date, draft && draft.guests);

  if (!booking || !draft) return null;

  const product = productById(booking.product) || { id: booking.product, name: booking.productName || booking.product };
  const G = PRODUCT_GLYPHS[booking.product] || PRODUCT_GLYPHS.dinner;
  const dirty = JSON.stringify(draft) !== JSON.stringify(booking);
  const cancelled = booking.status === 'cancelled';

  const timingChanged = draft.date !== booking.date
    || draft.time !== booking.time
    || draft.guests !== booking.guests;

  const update = (patch) => { setCheck({ status: 'idle' }); setDraft({ ...draft, ...patch }); };
  const startAmend = () => { setDraft({ ...booking }); setConfirmCancel(false); setOpenChip(null); setCheck({ status: 'idle' }); setMode('amend'); };
  const backToView = () => { setDraft({ ...booking }); setOpenChip(null); setCheck({ status: 'idle' }); setMode('view'); };

  // Fresh availability look-up for the chosen slot — bypasses the slot cache so
  // the check reflects the operator's current inventory, not what was loaded
  // when the drawer opened. Local-only bookings (no compositeId) can't be
  // verified against Bookable, so they pass through.
  const recheckAvailability = async () => {
    const compositeId = booking.compositeId || (venue.composites && venue.composites[booking.product]);
    if (!compositeId) return true;
    try {
      const key = compositeId + '|' + draft.date + '|' + draft.guests;
      if (window.__pp_slot_cache) window.__pp_slot_cache.delete(key);
      const fresh = await ppLoadAvailability(compositeId, draft.date, draft.guests);
      return Array.isArray(fresh) && fresh.some(s => s.time === draft.time);
    } catch (e) {
      // If the look-up itself fails, don't block the partner — let the save
      // attempt surface any real error from the PATCH.
      return true;
    }
  };

  const save = async () => {
    // Amending the timing requires a confirming availability look-up before we
    // commit. Contact-only edits (email / phone) skip straight to save.
    if (timingChanged) {
      setCheck({ status: 'checking' });
      const ok = await recheckAvailability();
      if (!ok) { setCheck({ status: 'gone' }); setOpenChip('time'); return; }
    }
    setCheck({ status: 'idle' });
    setSaving(true);
    try {
      const ok = await onSave(draft);
      if (ok === false) { setCheck({ status: 'error' }); return; }
      setSavedFlash(true);
      setMode('view');
      setTimeout(() => setSavedFlash(false), 2200);
    } finally {
      setSaving(false);
    }
  };

  const status = draft.status || 'pending';
  const statusLabel = status === 'confirmed' ? 'Confirmed'
    : status === 'pending' ? 'Pending'
    : status === 'cancelled' ? 'Cancelled' : status;

  return (
    <React.Fragment>
      <div className="pp-drawer-scrim" onClick={onClose}/>
      <aside className="pp-drawer" role="dialog" aria-label={mode === 'amend' ? 'Amend booking' : 'Booking details'}>
        <header className="pp-drawer-head">
          <div className="pp-drawer-head-title">
            <span className="pp-drawer-eyebrow">{mode === 'amend' ? 'Amend booking' : 'Booking'} · {String(booking.id).toUpperCase()}</span>
            <h2>{venue.name}</h2>
            <div className="pp-drawer-meta">
              <span className="pp-muted"><IconPin size={11}/> {venue.city || booking.city}</span>
              <OperatorTag id={venue.operator || booking.operator} size="sm"/>
              <span className={"pp-status-pill pp-status-pill--" + status}>
                <span className="pp-status-dot"/>{statusLabel}
              </span>
            </div>
          </div>
          <button className="pp-icon-btn" onClick={onClose} aria-label="Close">
            <IconClose size={16}/>
          </button>
        </header>

        {mode === 'view' ? (
          /* ───────── OVERVIEW ───────── */
          <React.Fragment>
            <div className="pp-drawer-body">
              {savedFlash && (
                <div className="pp-banner-success">
                  <IconCheck size={14}/>
                  <span>Booking updated. The customer has been notified.</span>
                </div>
              )}

              <section className="pp-summary">
                <div className="pp-summary-row">
                  <span className="pp-summary-icon"><G size={14}/></span>
                  <span className="pp-summary-k">Product</span>
                  <span className="pp-summary-v">{product.name}</span>
                </div>
                <div className="pp-summary-row">
                  <span className="pp-summary-icon"><IconCal size={14}/></span>
                  <span className="pp-summary-k">Date</span>
                  <span className="pp-summary-v">{fmtBookingDate(booking.date)}</span>
                </div>
                <div className="pp-summary-row">
                  <span className="pp-summary-icon"><IconClock size={14}/></span>
                  <span className="pp-summary-k">Time</span>
                  <span className="pp-summary-v">{booking.time || '—'}</span>
                </div>
                <div className="pp-summary-row">
                  <span className="pp-summary-icon"><IconUsers size={14}/></span>
                  <span className="pp-summary-k">Party size</span>
                  <span className="pp-summary-v">{booking.guests} {booking.guests === 1 ? 'guest' : 'guests'}</span>
                </div>
              </section>

              <section className="pp-form-section">
                <h3 className="pp-form-section-title">Customer</h3>
                <section className="pp-summary">
                  <div className="pp-summary-row">
                    <span className="pp-summary-icon"><IconUser size={14}/></span>
                    <span className="pp-summary-k">Name</span>
                    <span className="pp-summary-v">{booking.customer}</span>
                  </div>
                  <div className="pp-summary-row">
                    <span className="pp-summary-icon"><IconMail size={14}/></span>
                    <span className="pp-summary-k">Email</span>
                    {booking.email
                      ? <span className="pp-summary-v">{booking.email}</span>
                      : <span className="pp-summary-empty">Not provided</span>}
                  </div>
                  <div className="pp-summary-row">
                    <span className="pp-summary-icon"><IconPhone size={14}/></span>
                    <span className="pp-summary-k">Phone</span>
                    {booking.phone
                      ? <span className="pp-summary-v">{booking.phone}</span>
                      : <span className="pp-summary-empty">Not provided</span>}
                  </div>
                </section>
              </section>

              <section className="pp-form-section">
                <h3 className="pp-form-section-title">Booking record</h3>
                <section className="pp-summary">
                  <div className="pp-summary-row">
                    <span className="pp-summary-icon"><IconLink size={14}/></span>
                    <span className="pp-summary-k">Source</span>
                    <span className="pp-summary-v">{booking.source}</span>
                  </div>
                  <div className="pp-summary-row">
                    <span className="pp-summary-icon"><IconCal size={14}/></span>
                    <span className="pp-summary-k">Received</span>
                    <span className="pp-summary-v">{fmtBookingDate(booking.rcvd)}</span>
                  </div>
                  {booking.operatorBookingId && (
                    <div className="pp-summary-row">
                      <span className="pp-summary-icon"><IconTag size={14}/></span>
                      <span className="pp-summary-k">Operator ref</span>
                      <span className="pp-summary-v pp-mono">{booking.operatorBookingId}</span>
                    </div>
                  )}
                </section>
              </section>

              {booking.notes && (
                <section className="pp-form-section">
                  <h3 className="pp-form-section-title">Notes</h3>
                  <p className="pp-notes-readout">{booking.notes}</p>
                </section>
              )}

              {confirmCancel && (
                <section className="pp-form-section pp-danger-section">
                  <div className="pp-danger-title">Cancel this booking?</div>
                  <div className="pp-danger-sub">The customer and the operator will be notified. This can’t be undone from here.</div>
                  <div className="pp-danger-actions">
                    <button className="pp-btn pp-btn--ghost" onClick={() => setConfirmCancel(false)}>Keep booking</button>
                    <button className="pp-btn pp-btn--danger" onClick={() => { onCancelBooking(booking.id); onClose(); }}>
                      Yes, cancel booking
                    </button>
                  </div>
                </section>
              )}
            </div>

            <footer className="pp-drawer-foot pp-drawer-foot--edit">
              <button className="pp-btn pp-btn--ghost pp-btn--danger-ghost"
                      onClick={() => setConfirmCancel(true)}
                      disabled={cancelled || confirmCancel}>
                Cancel booking
              </button>
              <div className="pp-drawer-foot-right">
                <button className="pp-btn pp-btn--primary" onClick={startAmend} disabled={cancelled}>
                  Amend booking
                </button>
              </div>
            </footer>
          </React.Fragment>
        ) : (
          /* ───────── AMEND ───────── */
          <React.Fragment>
            <div className="pp-drawer-body">
              <button type="button" className="pp-ghost-btn" onClick={backToView}>
                <IconArrowL size={13}/> Back to overview
              </button>

              {check.status === 'error' && (
                <div className="pp-banner-warn">
                  <AlertGlyph size={14}/>
                  <span>Couldn’t save the amendment — nothing was changed and the customer wasn’t notified. Try again.</span>
                </div>
              )}

              <section className="pp-form-section">
                <h3 className="pp-form-section-title">When</h3>
                <div className="pp-amend-chips">
                  <button type="button"
                          className={"pp-dd-chip pp-dd-chip--solid is-active" + (openChip === 'date' ? " is-open" : "")}
                          onClick={() => setOpenChip(c => c === 'date' ? null : 'date')}>
                    <IconCal size={14}/>
                    <span>{new Date(draft.date + 'T00:00:00').toLocaleDateString('en-GB', { month: 'short', day: 'numeric' })}</span>
                    <IconChevronDn size={12}/>
                  </button>
                  <button type="button"
                          className={"pp-dd-chip pp-dd-chip--outline is-active" + (openChip === 'time' ? " is-open" : "")}
                          onClick={() => setOpenChip(c => c === 'time' ? null : 'time')}>
                    <IconClock size={14}/>
                    <span>{draft.time || 'Time'}</span>
                    <IconChevronDn size={12}/>
                  </button>
                  <button type="button"
                          className={"pp-dd-chip pp-dd-chip--solid is-active" + (openChip === 'guests' ? " is-open" : "")}
                          onClick={() => setOpenChip(c => c === 'guests' ? null : 'guests')}>
                    <IconUsers size={14}/>
                    <span>{draft.guests === 1 ? '1 guest' : draft.guests + ' guests'}</span>
                    <IconChevronDn size={12}/>
                  </button>
                </div>

                {openChip === 'date' && (
                  <div className="pp-amend-panel">
                    <Calendar value={draft.date} onChange={(iso) => { update({ date: iso }); setOpenChip(null); }}/>
                  </div>
                )}
                {openChip === 'time' && (
                  <div className="pp-amend-panel">
                    <TimeSelect slots={slots} value={draft.time}
                                onPick={(time) => { update({ time }); setOpenChip(null); }}/>
                  </div>
                )}
                {openChip === 'guests' && (
                  <div className="pp-amend-panel pp-amend-panel--center">
                    <GuestStepper value={draft.guests} min={1} max={100} onChange={(n) => update({ guests: n })}/>
                  </div>
                )}

                {timingChanged && (
                  <p className="pp-amend-hint">
                    <IconClock size={12}/>
                    We’ll re-check availability for this date, time and party size before confirming.
                  </p>
                )}
                {check.status === 'gone' && (
                  <div className="pp-banner-warn">
                    <AlertGlyph size={14}/>
                    <span>That time is no longer available for {draft.guests} {draft.guests === 1 ? 'guest' : 'guests'}. Pick another slot to continue.</span>
                  </div>
                )}
              </section>

              <section className="pp-form-section">
                <h3 className="pp-form-section-title">Contact details</h3>
                <div className="pp-form-grid pp-form-grid--2">
                  <Field label="Email">
                    <input className="pp-input" type="email" value={draft.email || ''}
                           placeholder="Add an email…"
                           onChange={(e) => update({ email: e.target.value })}/>
                  </Field>
                  <Field label="Phone">
                    <input className="pp-input" type="tel" value={draft.phone || ''}
                           placeholder="Add a phone number…"
                           onChange={(e) => update({ phone: e.target.value })}/>
                  </Field>
                </div>
              </section>
            </div>

            <footer className="pp-drawer-foot pp-drawer-foot--edit">
              <button className="pp-btn pp-btn--ghost" onClick={backToView} disabled={saving || check.status === 'checking'}>
                Discard
              </button>
              <div className="pp-drawer-foot-right">
                <button className="pp-btn pp-btn--primary" onClick={save}
                        disabled={!dirty || saving || check.status === 'checking'}>
                  {check.status === 'checking' ? 'Checking availability…'
                    : saving ? 'Saving…'
                    : dirty ? (timingChanged ? 'Check & save' : 'Save changes')
                    : 'No changes'}
                </button>
              </div>
            </footer>
          </React.Fragment>
        )}
      </aside>
    </React.Fragment>
  );
}

// Live time-slot picker for the amend panel. `slots` is null while the
// availability look-up is in flight, [] when nothing is bookable. The current
// booking time is shown as a disabled "current" chip when it isn't among the
// freshly returned slots so the partner can still see what they had.
function TimeSelect({ slots, value, onPick }) {
  if (slots === null) {
    return <div className="pp-time-select pp-time-select--loading"><span className="pp-muted" style={{ fontSize: 12.5 }}>Loading times…</span></div>;
  }
  const hasCurrent = value && slots.some(s => s.time === value);
  return (
    <div className="pp-time-select">
      {!hasCurrent && value && (
        <button type="button" className="pp-time-select-btn is-active is-orphan" disabled>
          <span>{value}</span>
          <span className="pp-time-select-meta">current</span>
        </button>
      )}
      {slots.map(o => (
        <button type="button" key={o.time + (o.compositeId || '')}
                className={"pp-time-select-btn pp-time-select-btn--plain" + (value === o.time ? " is-active" : "")}
                onClick={() => onPick(o.time)}>
          <span>{o.time}</span>
        </button>
      ))}
      {slots.length === 0 && (
        <span className="pp-muted" style={{ fontSize: 12.5 }}>No slots available for this date · party size.</span>
      )}
    </div>
  );
}

function AlertGlyph({ size = 14 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 9v4M12 17v.01"/><path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/>
    </svg>
  );
}

function fmtBookingDate(iso) {
  if (!iso) return '—';
  // A date-only string is parsed as UTC midnight; pin it to local midnight so a
  // negative-UTC timezone doesn't render the day before. Matches the amend
  // chip + DateRangeChip elsewhere.
  const d = new Date(iso.length === 10 ? iso + 'T00:00:00' : iso);
  if (isNaN(d.getTime())) return iso;
  return d.toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric', month: 'short', year: 'numeric' });
}

Object.assign(window, { EditBookingDrawer });
