// Bookings list — table of all bookings with grouping, filtering, search.

const BOOKINGS_PAGE_SIZE = 25;

function BookingsScreen({ bookings, groupBy, setGroupBy, onOpen, initialText, onNewWalkin }) {
  const [text, setText]     = React.useState(initialText || '');
  const [venueF, setVenueF] = React.useState('');
  const [statusF, setStatusF] = React.useState('');
  const [dateFrom, setDateFrom] = React.useState('');
  const [dateTo,   setDateTo]   = React.useState('');
  const [todayOnly, setTodayOnly] = React.useState(false);
  const [sort, setSort] = React.useState('rcvd-desc'); // rcvd-desc | rcvd-asc | date-asc | date-desc
  const [page, setPage] = React.useState(0);

  React.useEffect(() => {
    if (initialText !== undefined && initialText !== null) setText(initialText);
  }, [initialText]);

  // Reset to page 0 whenever the filtered set changes shape — searching across
  // ALL bookings should land you on the first page of matches.
  React.useEffect(() => { setPage(0); }, [text, venueF, statusF, dateFrom, dateTo, todayOnly, sort, groupBy]);

  // The system's "today" for the demo. (Matches the seed bookings dated 2026-05-12.)
  const todayISO = '2026-05-12';
  const todays = bookings.filter(b => b.date === todayISO && b.status !== 'cancelled');

  const filtered = bookings.filter(b => {
    if (text && !(b.customer.toLowerCase().includes(text.toLowerCase())
                 || b.venue.toLowerCase().includes(text.toLowerCase())
                 || b.id.toLowerCase().includes(text.toLowerCase()))) return false;
    if (venueF && b.venue !== venueF) return false;
    if (statusF && b.status !== statusF) return false;
    if (dateFrom && (!b.date || b.date < dateFrom)) return false;
    if (dateTo   && (!b.date || b.date > dateTo))   return false;
    if (todayOnly && b.date !== todayISO) return false;
    return true;
  });

  // Sort by the active Date column option. Sort BEFORE grouping so that
  // groupBy=flat (the most common view) reflects the chosen order; grouped
  // views keep insertion order within each group.
  const [sortField, sortDir] = sort.split('-');
  const sortKey = sortField === 'date' ? 'date' : 'rcvd';
  filtered.sort((a, b) => {
    const av = a[sortKey] || '';
    const bv = b[sortKey] || '';
    if (av === bv) return 0;
    return sortDir === 'asc' ? (av < bv ? -1 : 1) : (av < bv ? 1 : -1);
  });

  // Pagination — search/filter/sort run across every booking, but only one
  // page worth of rows is rendered. Grouping is applied to the page slice.
  const totalCount  = filtered.length;
  const totalPages  = Math.max(1, Math.ceil(totalCount / BOOKINGS_PAGE_SIZE));
  const safePage    = Math.min(page, totalPages - 1);
  const pageStart   = safePage * BOOKINGS_PAGE_SIZE;
  const pageEnd     = Math.min(totalCount, pageStart + BOOKINGS_PAGE_SIZE);
  const pageRows    = filtered.slice(pageStart, pageEnd);

  // Group the current page's rows.
  let groups = [{ key:'all', label:null, rows: pageRows }];
  if (groupBy === 'operator') {
    groups = OPERATORS.map(o => ({
      key: o.id,
      label: <OperatorTag id={o.id} size="md"/>,
      rows: pageRows.filter(b => b.operator === o.id),
    })).filter(g => g.rows.length > 0);
  } else if (groupBy === 'product') {
    groups = PRODUCT_TYPES.map(p => ({
      key: p.id,
      label: <ProductPill id={p.id}/>,
      rows: pageRows.filter(b => b.product === p.id),
    })).filter(g => g.rows.length > 0);
  } else if (groupBy === 'date') {
    const byDate = {};
    pageRows.forEach(b => { (byDate[b.date] = byDate[b.date] || []).push(b); });
    groups = Object.keys(byDate).sort().map(d => ({
      key: d,
      label: <span className="pp-group-date">{fmtDate(d)}</span>,
      rows: byDate[d],
    }));
  }

  const uniqueVenues = Array.from(new Set(bookings.map(b => b.venue)));

  return (
    <div className="pp-screen-bookings">
      <div className="pp-page-head">
        <div>
          <h1 className="pp-page-display">Bookings</h1>
          <p className="pp-page-sub">Add, edit and amend bookings across your operators.</p>
        </div>
        <div className="pp-page-head-actions">
          <button type="button" className="pp-btn pp-btn--ghost">
            <IconDownload size={14}/>
            <span>Export CSV</span>
          </button>
        </div>
      </div>

      <div className="pp-bookings-toolbar">
        <Select value={venueF} onChange={setVenueF} icon={IconPin}>
          <option value="">Venue Name</option>
          {uniqueVenues.map(v => <option key={v} value={v}>{v}</option>)}
        </Select>
        <Select value={statusF} onChange={setStatusF} icon={IconFilter}>
          <option value="">Filter by status</option>
          <option value="confirmed">Confirmed</option>
          <option value="pending">Pending</option>
          <option value="cancelled">Cancelled</option>
        </Select>
        <DateRangeChip from={dateFrom} to={dateTo}
                       onChange={(f, t) => { setDateFrom(f || ''); setDateTo(t || ''); }}
                       onClear={() => { setDateFrom(''); setDateTo(''); }}/>
        {todayOnly && (
          <button type="button" className="pp-filter-chip pp-filter-chip--toggle" onClick={() => setTodayOnly(false)}>
            <IconCal size={11}/>
            <span>Today only</span>
            <IconClose size={11}/>
          </button>
        )}
        <div className="pp-toolbar-spacer"/>
        <GroupBySwitch value={groupBy} onChange={setGroupBy}/>
        <div className="pp-input-wrap pp-input-wrap--search">
          <span className="pp-input-icon"><IconSearch size={14}/></span>
          <input className="pp-input pp-input--ghost"
                 placeholder="Search bookings…"
                 value={text}
                 onChange={(e) => setText(e.target.value)}/>
        </div>
      </div>

      <div className="pp-bookings-table">
        <div className="pp-bookings-header">
          <div className="pp-col-source">Source</div>
          <div className="pp-col-operator">Operator</div>
          <div className="pp-col-venue">Venue</div>
          <div className="pp-col-product">Product</div>
          <div className="pp-col-customer">Customer</div>
          <div className="pp-col-guests">Guests</div>
          <div className="pp-col-date"><DateSortHeader value={sort} onChange={setSort}/></div>
          <div className="pp-col-time">Time</div>
          <div className="pp-col-status">Status</div>
        </div>
        {groups.map(g => (
          <BookingsGroup key={g.key} label={g.label} rows={g.rows} onOpen={onOpen}/>
        ))}
        {totalCount === 0 && (
          <div className="pp-empty pp-empty--inline">
            <div className="pp-empty-title">No bookings match</div>
            <div className="pp-empty-sub">Clear a filter or widen the date range to see more.</div>
          </div>
        )}
      </div>

      {totalCount > 0 && (
        <BookingsPagination
          total={totalCount}
          pageStart={pageStart}
          pageEnd={pageEnd}
          page={safePage}
          totalPages={totalPages}
          onPage={(p) => setPage(Math.max(0, Math.min(totalPages - 1, p)))}/>
      )}
    </div>
  );
}

function BookingsPagination({ total, pageStart, pageEnd, page, totalPages, onPage }) {
  return (
    <div className="pp-pagination">
      <div className="pp-pagination-meta">
        Showing <strong>{pageStart + 1}</strong>–<strong>{pageEnd}</strong> of <strong>{total}</strong>
      </div>
      <div className="pp-pagination-controls">
        <button type="button" className="pp-btn pp-btn--ghost pp-btn--xs"
                disabled={page === 0}
                onClick={() => onPage(page - 1)}>
          <IconArrowL size={12}/>
          <span>Previous</span>
        </button>
        <span className="pp-pagination-page">Page {page + 1} of {totalPages}</span>
        <button type="button" className="pp-btn pp-btn--ghost pp-btn--xs"
                disabled={page >= totalPages - 1}
                onClick={() => onPage(page + 1)}>
          <span>Next</span>
          <IconArrowR size={12}/>
        </button>
      </div>
    </div>
  );
}

// ─────────── Today strip — compact horizontal scroll of today's bookings ─────
function TodayStrip({ bookings, onOpen, onShowToday }) {
  if (!bookings || bookings.length === 0) {
    return (
      <div className="pp-today-strip pp-today-strip--empty">
        <div className="pp-today-strip-title">
          <span className="pp-today-eyebrow">Today</span>
          <span className="pp-today-date">{fmtDate('2026-05-12')}</span>
        </div>
        <div className="pp-today-strip-empty">No bookings for today.</div>
      </div>
    );
  }
  const sorted = [...bookings].sort((a, b) => a.time.localeCompare(b.time));
  return (
    <section className="pp-today-strip">
      <header className="pp-today-strip-head">
        <div className="pp-today-strip-title">
          <span className="pp-today-eyebrow">Today</span>
          <span className="pp-today-date">{fmtDate('2026-05-12')}</span>
          <span className="pp-today-count">{bookings.length} {bookings.length === 1 ? 'booking' : 'bookings'}</span>
        </div>
        <button type="button" className="pp-today-show-all" onClick={onShowToday}>
          Show today only <IconArrowR size={12}/>
        </button>
      </header>
      <div className="pp-today-strip-list">
        {sorted.map(b => (
          <button key={b.id} type="button" className="pp-today-card" onClick={() => onOpen && onOpen(b)}>
            <div className="pp-today-card-time">{b.time}</div>
            <div className="pp-today-card-main">
              <div className="pp-today-card-customer">{b.customer}</div>
              <div className="pp-today-card-venue">{b.venue}</div>
              <div className="pp-today-card-meta">
                <ProductPill id={b.product}/>
                <span className="pp-guest-pip"><IconUsers size={10}/> {b.guests}</span>
                {b.walkIn && <span className="pp-walkin-pip">Walk-in</span>}
              </div>
            </div>
          </button>
        ))}
      </div>
    </section>
  );
}

function GroupBySwitch({ value, onChange }) {
  const opts = [
    { id: 'flat',     label: 'List',        icon: IconLayoutRows },
    { id: 'operator', label: 'By operator', icon: IconTag },
    { id: 'product',  label: 'By product',  icon: IconBox },
    { id: 'date',     label: 'By date',     icon: IconCal },
  ];
  return (
    <div className="pp-segmented pp-segmented--sm" role="radiogroup" aria-label="Group bookings by">
      {opts.map(o => {
        const Ico = o.icon;
        return (
          <button key={o.id} type="button" role="radio" aria-checked={value === o.id}
                  className={"pp-segmented-btn" + (value === o.id ? " is-active" : "")}
                  onClick={() => onChange(o.id)}
                  title={o.label}>
            <Ico size={13}/>
            <span>{o.label}</span>
          </button>
        );
      })}
    </div>
  );
}

function Select({ value, onChange, icon: Ico, children }) {
  return (
    <div className="pp-select-wrap">
      {Ico && <span className="pp-input-icon"><Ico size={14}/></span>}
      <select className={"pp-select" + (Ico ? " pp-select--with-icon" : "")}
              value={value} onChange={(e) => onChange(e.target.value)}>
        {children}
      </select>
      <span className="pp-select-caret"><IconChevronDn size={12}/></span>
    </div>
  );
}

function BookingsGroup({ label, rows, onOpen }) {
  const [open, setOpen] = React.useState(true);
  return (
    <React.Fragment>
      {label && (
        <div className="pp-bookings-grouphead" onClick={() => setOpen(o => !o)}>
          <button type="button" className={"pp-disclose" + (open ? " is-open" : "")} aria-label={open ? 'Collapse' : 'Expand'}>
            <IconChevron size={11}/>
          </button>
          {label}
          <span className="pp-bookings-grouphead-count">{rows.length}</span>
        </div>
      )}
      {open && rows.map(b => (
        <BookingRow key={b.id} booking={b} onOpen={onOpen}/>
      ))}
    </React.Fragment>
  );
}

function BookingRow({ booking, onOpen }) {
  const product = productById(booking.product);
  const G = PRODUCT_GLYPHS[booking.product];
  return (
    <div className="pp-bookings-row" onClick={() => onOpen && onOpen(booking)}>
      <div className="pp-col-source">
        <span className={"pp-source" + (booking.source === 'Walk-in' ? " pp-source--walkin" : "")}>
          {booking.source === 'Walk-in' ? <IconPlus size={12}/> : <IconLink size={12}/>}
          <span>{booking.source}</span>
        </span>
      </div>
      <div className="pp-col-operator">
        <OperatorTag id={booking.operator} size="sm"/>
      </div>
      <div className="pp-col-venue">
        <div className="pp-bookings-venue">{booking.venue}</div>
        <div className="pp-bookings-city">{booking.city}</div>
      </div>
      <div className="pp-col-product">
        <div className="pp-bookings-product"><G size={12}/> {product.name}</div>
      </div>
      <div className="pp-col-customer">{booking.customer}</div>
      <div className="pp-col-guests">
        <span className="pp-guest-pip"><IconUsers size={11}/> {booking.guests}</span>
      </div>
      <div className="pp-col-date">
        <div className="pp-bookings-date">{fmtDateShort(booking.date)}</div>
        <div className="pp-bookings-rcvd">Rcvd: {fmtDateShort(booking.rcvd)}</div>
      </div>
      <div className="pp-col-time">{booking.time}</div>
      <div className="pp-col-status">
        <StatusDot status={booking.status}/>
      </div>
    </div>
  );
}

function fmtDateShort(iso) {
  const d = new Date(iso);
  const dd = String(d.getDate()).padStart(2,'0');
  const mm = String(d.getMonth()+1).padStart(2,'0');
  return dd + '/' + mm + '/' + d.getFullYear();
}

// Sort menu for the Date column header — same four options as the
// reference design (Reservation Date / Received Date × earliest / latest).
const SORT_OPTIONS = [
  { id: 'date-asc',  label: 'Reservation Date (earliest first)' },
  { id: 'date-desc', label: 'Reservation Date (latest first)' },
  { id: 'rcvd-asc',  label: 'Received Date (earliest first)' },
  { id: 'rcvd-desc', label: 'Received Date (latest first)' },
];

function DateSortHeader({ value, onChange }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);
  return (
    <span className="pp-dd-wrap" ref={ref} style={{ display: 'inline-block' }}>
      <button type="button"
              className={"pp-col-sort" + (open ? ' is-open' : '')}
              aria-haspopup="listbox"
              aria-expanded={open}
              onClick={() => setOpen(o => !o)}>
        <span>Date</span>
        <IconChevronDn size={11}/>
      </button>
      {open && (
        <div className="pp-dd-menu" role="listbox" style={{ minWidth: 260 }}>
          {SORT_OPTIONS.map(o => (
            <button key={o.id} type="button" role="option" aria-selected={o.id === value}
                    className={"pp-dd-item" + (o.id === value ? ' is-active' : '')}
                    onClick={() => { onChange(o.id); setOpen(false); }}>
              {o.label}
            </button>
          ))}
        </div>
      )}
    </span>
  );
}

// Date-range chip used on the bookings toolbar. Shows a single chip that
// reads "Any date" / "From X" / "Until Y" / "X → Y" and opens a popover
// containing two side-by-side Calendars plus a Clear button.
function DateRangeChip({ from, to, onChange, onClear }) {
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const fmt = (iso) => new Date(iso + 'T00:00:00').toLocaleDateString('en-GB', { month: 'short', day: 'numeric', year: 'numeric' });
  const hasRange = !!(from || to);
  const label = !hasRange ? 'Any date'
             : from && to ? fmt(from) + ' → ' + fmt(to)
             : from       ? 'From ' + fmt(from)
             :              'Until ' + fmt(to);

  return (
    <div className="pp-dd-wrap" ref={ref}>
      <button type="button"
              className={"pp-dd-chip" + (hasRange ? " is-active" : "") + (open ? " is-open" : "")}
              onClick={() => setOpen(o => !o)}>
        <IconCal size={14}/>
        <span>{label}</span>
        {hasRange && (
          <span className="pp-dd-chip-clear"
                role="button" tabIndex={0} aria-label="Clear date range"
                onClick={(e) => { e.stopPropagation(); onClear(); }}
                onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.stopPropagation(); e.preventDefault(); onClear(); } }}>
            <IconClose size={11}/>
          </span>
        )}
        <IconChevronDn size={11}/>
      </button>
      {open && (
        <div className="pp-dd-menu pp-dd-menu--daterange">
          <div className="pp-daterange-grid">
            <div className="pp-daterange-col">
              <div className="pp-daterange-label">From</div>
              <Calendar value={from || ''} onChange={(iso) => onChange(iso, to && iso > to ? iso : to)}/>
            </div>
            <div className="pp-daterange-col">
              <div className="pp-daterange-label">To</div>
              <Calendar value={to || ''} minISO={from || undefined} onChange={(iso) => onChange(from, iso)}/>
            </div>
          </div>
          <div className="pp-daterange-foot">
            <button type="button" className="pp-btn pp-btn--ghost pp-btn--xs" onClick={() => { onClear(); }}>Clear</button>
            <button type="button" className="pp-btn pp-btn--primary pp-btn--xs" onClick={() => setOpen(false)}>Done</button>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { BookingsScreen, fmtDateShort, DateSortHeader, DateRangeChip });
