// Search landing screen — omni search bar with live suggestions + scale-friendly browse.

function SearchBar({ value, onChange, onSubmit, onPickSuggestion, glow = true, autoFocus = false, compact = false, searching = false }) {
  const v = value;
  const set = (patch) => onChange({ ...v, ...patch });
  const [openLoc, setOpenLoc] = React.useState(false);
  const [openProd, setOpenProd] = React.useState(false);
  const [openOp, setOpenOp] = React.useState(false);
  const [openGuests, setOpenGuests] = React.useState(false);
  const [omniOpen, setOmniOpen] = React.useState(false);
  // Track first interaction — we don't want the omni dropdown opening on the
  // page's initial autoFocus, only when the agent actively clicks/types.
  const hasInteracted = React.useRef(false);
  const closeAllDD = () => { setOpenLoc(false); setOpenProd(false); setOpenOp(false); setOpenGuests(false); };
  const wrapRef = React.useRef(null);

  const handlePick = (pick) => {
    setOmniOpen(false);
    // Product / operator picks are FILTERS, not destinations: stage them into
    // the search bar (clearing the free-text that opened the dropdown) and
    // wait for the partner to press search. Bubbling these to onPickSuggestion
    // would navigate straight to results and run the search immediately, which
    // is exactly what we don't want. Everything else (venue, booking,
    // run-search, screen jumps) is an explicit destination — bubble as before.
    if (pick && pick.kind === 'product' && pick.product) { set({ productType: pick.product.id, text: '' }); return; }
    if (pick && pick.kind === 'operator' && pick.operator) { set({ operatorId: pick.operator.id, text: '' }); return; }
    if (onPickSuggestion) onPickSuggestion(pick);
  };

  return (
    <div className={"pp-searchbar-wrap" + (glow ? " has-glow" : "") + (compact ? " is-compact" : "")} ref={wrapRef}>
      {glow && <div className="pp-searchbar-glow" aria-hidden="true"/>}
      <form className="pp-searchbar" onSubmit={(e) => { e.preventDefault(); setOmniOpen(false); onSubmit(); }}>
        <span className="pp-searchbar-icon"><IconSearch size={18}/></span>
        <input
          className="pp-searchbar-input"
          placeholder={compact ? "Search venues, customers, bookings…" : ""}
          value={v.text}
          autoFocus={autoFocus}
          onMouseDown={() => { hasInteracted.current = true; }}
          onFocus={() => { if (hasInteracted.current) setOmniOpen(true); }}
          onChange={(e) => { hasInteracted.current = true; set({ text: e.target.value }); setOmniOpen(true); }}
          onKeyDown={(e) => {
            if (e.key === 'Escape') { setOmniOpen(false); e.target.blur(); }
            if (e.key === 'ArrowDown' && omniOpen) {
              const first = wrapRef.current && wrapRef.current.querySelector('.pp-omni-row');
              if (first) { first.focus(); e.preventDefault(); }
            }
          }}
        />
        <DropdownChip
          icon={IconPin}
          label={v.location === 'All locations' ? 'Location' : v.location}
          active={v.location !== 'All locations'}
          open={openLoc}
          onToggle={() => { setOpenLoc(o => !o); setOpenProd(false); setOpenOp(false); setOpenGuests(false); setOmniOpen(false); }}
          onClose={() => setOpenLoc(false)}>
          {CITIES.map(c => (
            <button type="button" key={c} className={"pp-dd-item" + (c === v.location ? " is-active" : "")}
                    onClick={() => { set({ location: c }); setOpenLoc(false); }}>
              {c}
            </button>
          ))}
        </DropdownChip>
        <DropdownChip
          icon={IconBox}
          label={v.productType ? productById(v.productType).name : 'Product'}
          active={!!v.productType}
          open={openProd}
          onToggle={() => { closeAllDD(); setOpenProd(o => !o); setOmniOpen(false); }}
          onClose={() => setOpenProd(false)}>
          <button type="button" className={"pp-dd-item" + (!v.productType ? " is-active" : "")}
                  onClick={() => { set({ productType: null }); setOpenProd(false); }}>
            Any product
          </button>
          {PRODUCT_TYPES.map(p => (
            <button type="button" key={p.id} className={"pp-dd-item" + (p.id === v.productType ? " is-active" : "")}
                    onClick={() => { set({ productType: p.id }); setOpenProd(false); }}>
              {p.name}
            </button>
          ))}
        </DropdownChip>
        <OperatorChip
          value={v.operatorId}
          open={openOp}
          onToggle={() => { setOpenOp(o => !o); setOpenLoc(false); setOpenProd(false); setOpenGuests(false); setOmniOpen(false); }}
          onClose={() => setOpenOp(false)}
          onChange={(id) => { set({ operatorId: id }); setOpenOp(false); }}/>
        <DateChip value={v.date} onChange={(d) => set({ date: d })} />
        <DropdownChip
          icon={IconUsers}
          label={String(v.guests)}
          active
          open={openGuests}
          onToggle={() => { setOpenGuests(o => !o); setOpenLoc(false); setOpenProd(false); setOpenOp(false); setOmniOpen(false); }}
          onClose={() => setOpenGuests(false)}
          variant="solid"
          menuRight>
          <GuestStepper value={v.guests} onChange={(n) => set({ guests: n })}/>
        </DropdownChip>
        <button type="submit" className={"pp-searchbar-go" + (searching ? ' is-busy' : '')} aria-label="Search" disabled={searching}>
          <span className="pp-go-icon" aria-hidden="true"><IconSend size={16}/></span>
          <span className="pp-go-spinner" aria-hidden="true">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round">
              <path d="M12 3a9 9 0 1 1-9 9" style={{ transformOrigin: '12px 12px', animation: 'pp-spin 1s linear infinite' }}/>
            </svg>
          </span>
        </button>
      </form>

      {omniOpen && onPickSuggestion && (
        <OmniSuggest text={v.text} anchorRef={wrapRef} onClose={() => setOmniOpen(false)} onPick={handlePick}/>
      )}
    </div>
  );
}

function GuestStepper({ value, onChange, min = 1, max = 999 }) {
  // Local text state so partial typing (e.g. while typing "33", you don't see 3
  // then 33 trip back to default) feels natural. Commit on blur or Enter.
  const [text, setText] = React.useState(String(value));
  React.useEffect(() => { setText(String(value)); }, [value]);

  const commit = (raw) => {
    const n = parseInt(String(raw).replace(/[^0-9]/g, ''), 10);
    if (isNaN(n)) { setText(String(value)); return; }
    const clamped = Math.max(min, Math.min(max, n));
    onChange(clamped);
    setText(String(clamped));
  };

  const bump = (delta) => {
    const n = parseInt(text, 10);
    const base = isNaN(n) ? value : n;
    onChange(Math.max(min, Math.min(max, base + delta)));
  };

  return (
    <div className="pp-guest-stepper">
      <div className="pp-guest-stepper-label">Number of guests</div>
      <div className="pp-guest-stepper-row">
        <button type="button" className="pp-guest-stepper-btn"
                aria-label="Decrease"
                disabled={value <= min}
                onClick={() => bump(-1)}>
          <span>−</span>
        </button>
        <input className="pp-guest-stepper-input"
               inputMode="numeric"
               pattern="[0-9]*"
               value={text}
               aria-label="Number of guests"
               onChange={(e) => setText(e.target.value.replace(/[^0-9]/g, ''))}
               onBlur={(e) => commit(e.target.value)}
               onKeyDown={(e) => {
                 if (e.key === 'Enter') { e.preventDefault(); commit(e.currentTarget.value); e.currentTarget.blur(); }
                 if (e.key === 'ArrowUp')   { e.preventDefault(); bump(1); }
                 if (e.key === 'ArrowDown') { e.preventDefault(); bump(-1); }
               }}/>
        <button type="button" className="pp-guest-stepper-btn"
                aria-label="Increase"
                disabled={value >= max}
                onClick={() => bump(1)}>
          <span>+</span>
        </button>
      </div>
      <div className="pp-guest-stepper-hint">{value === 1 ? '1 guest' : value + ' guests'}</div>
    </div>
  );
}

function OperatorChip({ value, open, onToggle, onClose, onChange }) {
  const [filter, setFilter] = React.useState('');
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open, onClose]);
  React.useEffect(() => { if (!open) setFilter(''); }, [open]);

  const label = value ? operatorById(value).name : 'Operator';
  const list = OPERATORS.filter(o => !filter || o.name.toLowerCase().includes(filter.toLowerCase()));
  const pinned = list.filter(o => o.pinned);
  const others = list.filter(o => !o.pinned);

  return (
    <div className="pp-dd-wrap" ref={ref}>
      <button type="button"
              className={"pp-dd-chip pp-dd-chip--outline" + (value ? " is-active" : "") + (open ? " is-open" : "")}
              onClick={onToggle}>
        <IconTag size={14}/>
        <span>{label}</span>
        <IconChevronDn size={12}/>
      </button>
      {open && (
        <div className="pp-dd-menu pp-dd-menu--op">
          <div className="pp-dd-search">
            <IconSearch size={13}/>
            <input autoFocus value={filter} onChange={(e) => setFilter(e.target.value)} placeholder={'Filter ' + OPERATORS.length + ' operators…'}/>
          </div>
          <button type="button" className={"pp-dd-item" + (!value ? " is-active" : "")}
                  onClick={() => onChange(null)}>
            All operators
          </button>
          {pinned.length > 0 && (
            <React.Fragment>
              <div className="pp-dd-sect">Pinned</div>
              {pinned.map(o => (
                <button type="button" key={o.id} className={"pp-dd-item pp-dd-item--op" + (value === o.id ? " is-active" : "")}
                        onClick={() => onChange(o.id)}>
                  <span className="pp-op-tag pp-op-tag--sm"><IconTag size={10}/><span>{o.name}</span></span>
                  <span className="pp-dd-item-meta">{o.venueCount}</span>
                </button>
              ))}
            </React.Fragment>
          )}
          {others.length > 0 && (
            <React.Fragment>
              {pinned.length > 0 && <div className="pp-dd-sect">All operators</div>}
              {others.map(o => (
                <button type="button" key={o.id} className={"pp-dd-item pp-dd-item--op" + (value === o.id ? " is-active" : "")}
                        onClick={() => onChange(o.id)}>
                  <span>{o.name}</span>
                  <span className="pp-dd-item-meta">{o.venueCount}</span>
                </button>
              ))}
            </React.Fragment>
          )}
          {list.length === 0 && <div className="pp-dd-empty">No operators match “{filter}”</div>}
        </div>
      )}
    </div>
  );
}

function DropdownChip({ icon: Ico, label, active, open, onToggle, onClose, variant = 'outline', menuRight = false, children }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = (e) => { if (ref.current && !ref.current.contains(e.target)) onClose(); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open, onClose]);
  return (
    <div className="pp-dd-wrap" ref={ref}>
      <button type="button"
              className={"pp-dd-chip pp-dd-chip--" + variant + (active ? " is-active" : "") + (open ? " is-open" : "")}
              onClick={onToggle}>
        {Ico && <Ico size={14}/>}
        <span>{label}</span>
        <IconChevronDn size={12}/>
      </button>
      {open && (
        <div className={"pp-dd-menu" + (menuRight ? " pp-dd-menu--right" : "")}>{children}</div>
      )}
    </div>
  );
}

function DateChip({ 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]);

  const d = new Date(value);
  const label = d.toLocaleDateString('en-GB', { month: 'short', day: 'numeric' });

  return (
    <div className="pp-dd-wrap" ref={ref}>
      <button type="button"
              className={"pp-dd-chip pp-dd-chip--solid is-active" + (open ? " is-open" : "")}
              onClick={() => setOpen(o => !o)}>
        <IconCal size={14}/>
        <span>{label}</span>
      </button>
      {open && (
        <div className="pp-dd-menu pp-dd-menu--cal pp-dd-menu--right">
          <Calendar value={value} onChange={(iso) => { onChange(iso); setOpen(false); }}/>
        </div>
      )}
    </div>
  );
}

// Month-grid calendar with prev/next nav. ISO date string in/out.
function Calendar({ value, onChange, minISO }) {
  const valDate = value ? new Date(value + 'T00:00:00') : new Date();
  const [cursor, setCursor] = React.useState(() => {
    const d = new Date(valDate); d.setDate(1); return d;
  });

  React.useEffect(() => {
    // Re-anchor the cursor if the selection jumps to a different month.
    if (valDate.getMonth() !== cursor.getMonth() || valDate.getFullYear() !== cursor.getFullYear()) {
      // Don't fight the user's nav; only follow if cursor is far away.
    }
  }, [value]);

  const year = cursor.getFullYear();
  const month = cursor.getMonth();
  const monthLabel = cursor.toLocaleDateString('en-GB', { month: 'long', year: 'numeric' });

  // Build the day grid — Mon-first.
  const firstOfMonth = new Date(year, month, 1);
  const firstWeekday = (firstOfMonth.getDay() + 6) % 7; // Mon=0..Sun=6
  const daysInMonth = new Date(year, month + 1, 0).getDate();
  const daysInPrevMonth = new Date(year, month, 0).getDate();

  const cells = [];
  // Leading days from prev month
  for (let i = firstWeekday - 1; i >= 0; i--) {
    const day = daysInPrevMonth - i;
    const d = new Date(year, month - 1, day);
    cells.push({ d, inMonth: false });
  }
  // This month
  for (let day = 1; day <= daysInMonth; day++) {
    cells.push({ d: new Date(year, month, day), inMonth: true });
  }
  // Trailing days to fill 6 weeks
  while (cells.length < 42) {
    const last = cells[cells.length - 1].d;
    const d = new Date(last); d.setDate(last.getDate() + 1);
    cells.push({ d, inMonth: d.getMonth() === month });
  }

  const today = new Date(); today.setHours(0,0,0,0);
  const isoOf = (d) => {
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2,'0');
    const day = String(d.getDate()).padStart(2,'0');
    return y + '-' + m + '-' + day;
  };
  const minDate = minISO ? new Date(minISO + 'T00:00:00') : null;

  const stepMonth = (delta) => {
    const c = new Date(cursor); c.setMonth(cursor.getMonth() + delta); setCursor(c);
  };
  const goToToday = () => {
    const c = new Date(); c.setDate(1); setCursor(c);
    onChange(isoOf(today));
  };

  return (
    <div className="pp-cal">
      <div className="pp-cal-head">
        <button type="button" className="pp-cal-nav" onClick={() => stepMonth(-1)} aria-label="Previous month">
          <IconArrowL size={14}/>
        </button>
        <div className="pp-cal-month">{monthLabel}</div>
        <button type="button" className="pp-cal-nav" onClick={() => stepMonth(1)} aria-label="Next month">
          <IconArrowR size={14}/>
        </button>
        <button type="button" className="pp-cal-today" onClick={goToToday}>Today</button>
      </div>
      <div className="pp-cal-grid pp-cal-grid--dow">
        {['Mo','Tu','We','Th','Fr','Sa','Su'].map((d, i) => (
          <div key={i} className="pp-cal-doh">{d}</div>
        ))}
      </div>
      <div className="pp-cal-grid">
        {cells.map((c, i) => {
          const iso = isoOf(c.d);
          const isSelected = iso === value;
          const isToday = c.d.getTime() === today.getTime();
          const isDisabled = minDate && c.d < minDate;
          return (
            <button key={i}
                    type="button"
                    disabled={isDisabled}
                    className={"pp-cal-cell"
                      + (c.inMonth ? '' : ' is-muted')
                      + (isSelected ? ' is-active' : '')
                      + (isToday ? ' is-today' : '')
                      + (isDisabled ? ' is-disabled' : '')}
                    onClick={() => onChange(iso)}>
              {c.d.getDate()}
            </button>
          );
        })}
      </div>
    </div>
  );
}

// ─────────────── Browse sections — scale-friendly ────────────────────────────
// 6 products fit in a row; if there are more they wrap to a 2nd row.
// Operators: show pinned + a compact chip grid. Filter input + "Show all" toggle.

function ProductBrowseGrid({ query, onPick }) {
  // Always show all (currently 6) — if we grow past ~10, switch to a
  // horizontally scrollable rail (set overflow-x:auto on .pp-prod-grid).
  return (
    <div className="pp-prod-grid">
      {PRODUCT_TYPES.map(p => {
        const G = PRODUCT_GLYPHS[p.id];
        const count = VENUES.filter(v => v.products.includes(p.id)).length;
        return (
          <button type="button" key={p.id}
                  className="pp-prod-tile"
                  style={{ '--tile-accent': p.accent }}
                  onClick={() => onPick(p.id)}>
            <div className="pp-prod-tile-glyph"><G size={28}/></div>
            <div className="pp-prod-tile-name">{p.name}</div>
            <div className="pp-prod-tile-meta">{count} venues</div>
          </button>
        );
      })}
    </div>
  );
}

function OperatorBrowse({ onPick }) {
  const [filter, setFilter] = React.useState('');
  const [showAll, setShowAll] = React.useState(false);

  const filtered = OPERATORS.filter(o => !filter || o.name.toLowerCase().includes(filter.toLowerCase()));
  const pinned = filtered.filter(o => o.pinned);
  const others = filtered.filter(o => !o.pinned);

  const showAllMode = !!filter || showAll;
  const visible = showAllMode ? filtered : pinned;

  return (
    <div className="pp-op-browse">
      <div className="pp-op-browse-bar">
        <div className="pp-input-wrap pp-input-wrap--icon pp-op-browse-filter">
          <span className="pp-input-icon"><IconSearch size={13}/></span>
          <input className="pp-input pp-input--ghost"
                 placeholder={'Filter ' + OPERATORS.length + ' operators…'}
                 value={filter}
                 onChange={(e) => setFilter(e.target.value)}/>
        </div>
        {OPERATORS.length > pinned.length && !filter && (
          <button type="button" className="pp-op-browse-toggle" onClick={() => setShowAll(s => !s)}>
            {showAll ? 'Show pinned only' : 'Show all ' + OPERATORS.length}
            <IconChevronDn size={12} style={{ transform: showAll ? 'rotate(180deg)' : '' }}/>
          </button>
        )}
      </div>

      {pinned.length > 0 && !filter && !showAll && (
        <div className="pp-op-browse-eyebrow">Your pinned operators</div>
      )}
      {(filter || showAll) && pinned.length > 0 && (
        <React.Fragment>
          <div className="pp-op-browse-eyebrow">Pinned ({pinned.length})</div>
          <div className="pp-op-chip-grid">
            {pinned.map(o => <OperatorChipCard key={o.id} op={o} onClick={() => onPick(o.id)}/>)}
          </div>
          <div className="pp-op-browse-eyebrow">All operators ({others.length})</div>
          <div className="pp-op-chip-grid">
            {others.map(o => <OperatorChipCard key={o.id} op={o} onClick={() => onPick(o.id)}/>)}
          </div>
        </React.Fragment>
      )}
      {(!filter && !showAll) && (
        <div className="pp-op-chip-grid">
          {visible.map(o => <OperatorChipCard key={o.id} op={o} onClick={() => onPick(o.id)} large/>)}
        </div>
      )}
      {filtered.length === 0 && (
        <div className="pp-empty pp-empty--inline">
          <div className="pp-empty-title">No operators match</div>
          <div className="pp-empty-sub">Try a different spelling, or clear the filter.</div>
        </div>
      )}
    </div>
  );
}

function OperatorChipCard({ op, onClick, large }) {
  const cities = Array.from(new Set(VENUES.filter(v => v.operator === op.id).map(v => v.city))).slice(0, 3);
  return (
    <button type="button" className={"pp-op-chipcard" + (large ? " is-large" : "")} onClick={onClick}>
      <span className="pp-op-chipcard-head">
        <span className="pp-op-tag pp-op-tag--md">
          <IconTag size={12}/>
          <span>{op.name}</span>
        </span>
      </span>
      <span className="pp-op-chipcard-meta">
        {op.venueCount} venues
        {large && cities.length > 0 && <span> · {cities.join(', ')}</span>}
      </span>
    </button>
  );
}

function SearchScreen({ query, setQuery, onSearch, onPickSuggestion, searching = false }) {
  return (
    <div className="pp-screen-search">
      <div className="pp-screen-search-inner">
        <h1 className="pp-page-display">Search inventory</h1>
        <p className="pp-page-sub">Find the right slot across every operator you work with — or pull up an existing customer booking.</p>

        <SearchBar value={query} onChange={setQuery} onSubmit={onSearch} onPickSuggestion={onPickSuggestion} autoFocus glow searching={searching} />

        {searching && <SkeletonStack rows={3}/>}

        <section className="pp-section">
          <div className="pp-section-head">
            <h2 className="pp-section-title">Browse by product</h2>
            <span className="pp-section-meta">{PRODUCT_TYPES.length} types</span>
          </div>
          <ProductBrowseGrid query={query} onPick={(pid) => onPickSuggestion({ kind: 'product', product: { id: pid } })} />
        </section>

        <section className="pp-section">
          <div className="pp-section-head">
            <h2 className="pp-section-title">Browse by operator</h2>
            <span className="pp-section-meta">{OPERATORS.length} groups</span>
          </div>
          <OperatorBrowse onPick={(oid) => onPickSuggestion({ kind: 'operator', operator: { id: oid } })} />
        </section>
      </div>
    </div>
  );
}

function SkeletonStack({ rows = 3 }) {
  return (
    <div className="pp-skel-stack" aria-hidden="true">
      {Array.from({ length: rows }).map((_, i) => (
        <div key={i} className="pp-skel-row">
          <div className="pp-skel-thumb pp-shimmer"/>
          <div className="pp-skel-lines">
            <div className="pp-skel-line pp-skel-line--w65 pp-shimmer"/>
            <div className="pp-skel-line pp-skel-line--w40 pp-shimmer"/>
          </div>
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { SearchBar, SearchScreen, DropdownChip, DateChip, Calendar, ProductBrowseGrid, OperatorBrowse, OperatorChip, SkeletonStack });
