// Brook Consultancy — Public booking page (v2 pass 3)
//
// Loaded when ?role=book. No PIN. No sync polling. Posts the booking JSON to
// the configured Apps Script Web App endpoint, which writes it to the same
// Shared Drive folder the operator queue pulls from.
//
// Slot generation is deterministic from configurable settings (start/end
// time, slot length, table count). Strict slot validation: re-fetches the
// latest bookings on Submit and rejects if the slot just got taken.

// ---- helpers --------------------------------------------------------------
function _todayIsoDate() { return new Date().toISOString().slice(0, 10); }
function _isoSlotKey(iso) {
  // Hash an ISO datetime to a stable per-slot key, ignoring sub-minute precision.
  return new Date(iso).toISOString().slice(0, 16);
}
function _fmtSlot(date) {
  const h = String(date.getHours()).padStart(2, '0');
  const m = String(date.getMinutes()).padStart(2, '0');
  return `${h}:${m}`;
}
function _fmtSlotRange(start, lenMin) {
  const end = new Date(start.getTime() + lenMin * 60_000);
  return `${_fmtSlot(start)} – ${_fmtSlot(end)}`;
}

function generateSlots(cfg) {
  // cfg = { date: 'YYYY-MM-DD', startTime: 'HH:MM', endTime: 'HH:MM', slotLengthMin, tables }
  const slots = [];
  const [sh, sm] = (cfg.startTime || '09:30').split(':').map(Number);
  const [eh, em] = (cfg.endTime || '17:00').split(':').map(Number);
  const lenMin = cfg.slotLengthMin || 30;
  const tables = cfg.tables || 3;
  const date = cfg.date || _todayIsoDate();

  const start = new Date(`${date}T${String(sh).padStart(2,'0')}:${String(sm).padStart(2,'0')}:00`);
  const end   = new Date(`${date}T${String(eh).padStart(2,'0')}:${String(em).padStart(2,'0')}:00`);
  for (let t = start.getTime(); t + lenMin * 60_000 <= end.getTime(); t += lenMin * 60_000) {
    const slotStart = new Date(t);
    slots.push({
      iso: slotStart.toISOString(),
      label: _fmtSlotRange(slotStart, lenMin),
      capacity: tables
    });
  }
  return slots;
}

// Count taken seats per slot key from a list of booking records / log entries
function countTaken(slotsIsoList, takenList) {
  const counts = {};
  takenList.forEach(b => {
    const iso = b.slot_iso || (b.booking && b.booking.slot_iso);
    if (!iso) return;
    const status = b.status || (b.booking && b.booking.status) || 'booked';
    if (status === 'cancelled' || status === 'no_show') return;
    const key = _isoSlotKey(iso);
    counts[key] = (counts[key] || 0) + 1;
  });
  return counts;
}

// ---------------------------------------------------------------------------
// Booking page
// ---------------------------------------------------------------------------
const ZONES = [
  { id: 'education_social_care', label: 'Education & Social Care', sub: 'Ofsted, CQC, children\u2019s homes, supported living, transitional living, nurseries, schools and SEND APs' },
  { id: 'small_business', label: 'Small Business Support', sub: 'Owner-operators, micro-businesses, sole traders looking for support with specific projects or the systems, processes and digital transformation that help your business grow and thrive' },
  { id: 'outsourced_services', label: 'Outsourced Services', sub: 'Outsourced back-office FD, CFO and finance, admin, marketing and compliance' }
];

const BUSINESS_TYPES = ['Care', 'Small business', 'Nonprofit', 'Faith-based', 'Community', 'Other'];

function BookingPage() {
  // Slot config from settings — fall back to sensible defaults.
  const cfg = window.loadDriveSettings ? window.loadDriveSettings() : {};
  // Default booking date is the J-Trade event day; admin can override in Settings.
  const DEFAULT_BOOKING_DATE = cfg.bookingDate || '2026-05-13';
  const slotCfgBase = {
    startTime: cfg.bookingStart || '09:30',
    endTime:   cfg.bookingEnd   || '17:00',
    slotLengthMin: 30,
    tables: cfg.bookingTables || 3
  };
  const appsScriptUrl = cfg.appsScriptUrl || '';

  const [bookingDate, setBookingDate] = React.useState(DEFAULT_BOOKING_DATE);
  const [taken, setTaken] = React.useState({});             // {slotKey: count}
  const [loading, setLoading] = React.useState(false);
  const [submitted, setSubmitted] = React.useState(null);   // null | submitted booking
  const [error, setError] = React.useState(null);

  // Form fields
  const [contactName, setContactName] = React.useState('');
  const [businessName, setBusinessName] = React.useState('');
  const [businessType, setBusinessType] = React.useState('');
  const [region, setRegion] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [zone, setZone] = React.useState('');
  const [slotIso, setSlotIso] = React.useState('');
  const [headlineChallenge, setHeadlineChallenge] = React.useState('');
  const [hopes, setHopes] = React.useState('');

  const slotCfg = { ...slotCfgBase, date: bookingDate };
  const slots = React.useMemo(() => generateSlots(slotCfg), [bookingDate, slotCfgBase.startTime, slotCfgBase.endTime, slotCfgBase.tables]);

  // Clear any selected slot when the date changes — the previously-picked
  // slot no longer exists in the new day's slot list.
  React.useEffect(() => { setSlotIso(''); }, [bookingDate]);

  // Pull current bookings from Apps Script on mount and again on submit (strict).
  const refreshTaken = React.useCallback(async () => {
    if (!appsScriptUrl) return {};
    setLoading(true);
    try {
      const url = appsScriptUrl + (appsScriptUrl.includes('?') ? '&' : '?') + 'action=list_bookings&date=' + encodeURIComponent(bookingDate);
      const res = await fetch(url, { method: 'GET', mode: 'cors' });
      if (!res.ok) throw new Error('HTTP ' + res.status);
      const data = await res.json();
      const bookings = Array.isArray(data) ? data : (data.bookings || []);
      const counts = countTaken(slots.map(s => s.iso), bookings);
      setTaken(counts);
      return counts;
    } catch (e) {
      // Don't surface — the page is still usable in loose mode if Apps Script is down,
      // and on submit we'll either succeed or surface the failure there.
      console.warn('Could not load taken slots:', e);
      return {};
    } finally {
      setLoading(false);
    }
  }, [appsScriptUrl, bookingDate, slots]);

  React.useEffect(() => {
    refreshTaken();
    // Refresh every 60s while the page is open
    const id = setInterval(refreshTaken, 60_000);
    return () => clearInterval(id);
  }, [refreshTaken]);

  const isSlotFull = (iso, capacity) => (taken[_isoSlotKey(iso)] || 0) >= capacity;

  const valid =
    contactName.trim() &&
    businessName.trim() &&
    businessType &&
    email.trim() &&
    zone &&
    slotIso;

  const submit = async (e) => {
    e.preventDefault();
    setError(null);
    if (!valid) {
      setError('Please complete the required fields highlighted below.');
      return;
    }
    if (!appsScriptUrl) {
      setError('Booking endpoint is not configured for this event. Please mention this to a Brook team member at the stand.');
      return;
    }
    setLoading(true);
    try {
      // Strict re-check: pull latest bookings just before writing
      const fresh = await refreshTaken();
      const slot = slots.find(s => s.iso === slotIso);
      if (slot && (fresh[_isoSlotKey(slotIso)] || 0) >= slot.capacity) {
        setSlotIso('');
        setError('That slot was just taken — please pick another. Available slots have refreshed below.');
        setLoading(false);
        return;
      }

      const record = window.buildInitialBooking();
      record.booking = {
        ...record.booking,
        contact_name: contactName.trim(),
        business_name: businessName.trim(),
        business_type: businessType,
        region: region.trim(),
        email: email.trim(),
        phone: phone.trim(),
        preferred_zone: zone,
        slot_iso: slotIso,
        slot_label: slot ? slot.label : '',
        headline_challenge: headlineChallenge.trim(),
        hopes_from_review: hopes.trim()
      };
      record.updatedAt = new Date().toISOString();

      const res = await fetch(appsScriptUrl, {
        method: 'POST',
        // Apps Script Web Apps with anonymous access reject preflighted requests,
        // so we use text/plain to keep this as a CORS "simple" POST.
        headers: { 'Content-Type': 'text/plain;charset=utf-8' },
        body: JSON.stringify({ action: 'create_booking', record })
      });
      if (!res.ok) throw new Error('HTTP ' + res.status);
      const body = await res.json().catch(() => ({}));
      if (body && body.error) throw new Error(body.error);

      setSubmitted({ ...record, slot_label: slot ? slot.label : '' });
    } catch (e) {
      setError('Could not save your booking: ' + (e.message || e) + '. Please show this to a Brook team member at the stand.');
    } finally {
      setLoading(false);
    }
  };

  if (submitted) {
    return <BookingSuccess record={submitted} />;
  }

  return (
    <div className="booking-page">
      <BookingHero />

      <form className="booking-card" onSubmit={submit} noValidate>
        <div className="booking-section">
          <h2 className="booking-section-title">Your details</h2>
          <div className="booking-grid">
            <div className="field">
              <label className="field-label">Your name <span className="req">*</span></label>
              <input className="input" value={contactName} onChange={e => setContactName(e.target.value)} placeholder="First and last name" autoComplete="name" required />
            </div>
            <div className="field">
              <label className="field-label">Business / organisation name <span className="req">*</span></label>
              <input className="input" value={businessName} onChange={e => setBusinessName(e.target.value)} placeholder="The organisation you lead or work in" autoComplete="organization" required />
            </div>
            <div className="field">
              <label className="field-label">Business type <span className="req">*</span></label>
              <select className="select" value={businessType} onChange={e => setBusinessType(e.target.value)} required>
                <option value="">— Choose —</option>
                {BUSINESS_TYPES.map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </div>
            <div className="field">
              <label className="field-label">Region / area <span className="muted-help">(optional)</span></label>
              <input className="input" value={region} onChange={e => setRegion(e.target.value)} placeholder="e.g. Greater Manchester" />
            </div>
            <div className="field">
              <label className="field-label">Email <span className="req">*</span></label>
              <input type="email" className="input" value={email} onChange={e => setEmail(e.target.value)} placeholder="So we can send your one-pager" autoComplete="email" required />
            </div>
            <div className="field">
              <label className="field-label">Phone <span className="muted-help">(optional)</span></label>
              <input type="tel" className="input" value={phone} onChange={e => setPhone(e.target.value)} placeholder="If you'd like a follow-up call" autoComplete="tel" />
            </div>
          </div>
        </div>

        <div className="booking-section">
          <h2 className="booking-section-title">Which zone fits best?</h2>
          <p className="booking-section-help">Brook has three teams at the stand. Pick the one closest to where you are right now — we'll route you to the right consultant.</p>
          <div className="zone-grid">
            {ZONES.map(z => (
              <button
                key={z.id}
                type="button"
                className={`zone-card${zone === z.label ? ' active' : ''}`}
                onClick={() => setZone(z.label)}
              >
                <div className="zone-card-name">{z.label}</div>
                <div className="zone-card-sub">{z.sub}</div>
              </button>
            ))}
          </div>
        </div>

        <div className="booking-section">
          <h2 className="booking-section-title">Pick a 30-minute slot</h2>
          <p className="booking-section-help">
            Slots fill up fast. Greyed-out slots are full. {loading ? <em>Refreshing availability…</em> : null}
          </p>

          <div className="booking-date-row">
            <label className="field-label" htmlFor="booking-date">Date</label>
            <input
              id="booking-date"
              type="date"
              className="input booking-date-input"
              value={bookingDate}
              onChange={e => setBookingDate(e.target.value)}
            />
            <span className="booking-date-pretty">
              {new Date(bookingDate + 'T00:00:00').toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })}
            </span>
          </div>

          <div className="slot-grid">
            {slots.map(s => {
              const full = isSlotFull(s.iso, s.capacity);
              const past = new Date(s.iso).getTime() < Date.now();
              const disabled = full || past;
              return (
                <button
                  key={s.iso}
                  type="button"
                  className={`slot-chip${slotIso === s.iso ? ' active' : ''}${disabled ? ' disabled' : ''}`}
                  onClick={() => !disabled && setSlotIso(s.iso)}
                  disabled={disabled}
                  title={past ? 'Slot has passed' : full ? 'Fully booked' : 'Available'}
                >
                  <span className="slot-time">{s.label}</span>
                  {full && <span className="slot-tag slot-tag-full">Full</span>}
                  {!full && past && <span className="slot-tag slot-tag-past">Past</span>}
                  {!full && !past && <span className="slot-tag slot-tag-open">{Math.max(0, s.capacity - (taken[_isoSlotKey(s.iso)] || 0))} open</span>}
                </button>
              );
            })}
          </div>
          {slots.length === 0 && (
            <div className="empty-state" style={{ padding: '24px' }}>
              <strong>No slots configured</strong>
              The Brook team will switch booking on shortly. Come back to this page in a few minutes.
            </div>
          )}
        </div>

        <div className="booking-section">
          <h2 className="booking-section-title">A few quick questions</h2>
          <p className="booking-section-help">This lets your consultant arrive at the table ready to talk about what matters most. You can keep it short — we'll do the rest in person.</p>
          <div className="field">
            <label className="field-label">In one line — what's your biggest challenge right now?</label>
            <input className="input" value={headlineChallenge} onChange={e => setHeadlineChallenge(e.target.value)} placeholder="e.g. CQC report just came back, finances need a reset, growth has stalled..." maxLength={140} />
          </div>
          <div className="field">
            <label className="field-label">What would make this conversation valuable for you?</label>
            <textarea className="textarea" rows={3} value={hopes} onChange={e => setHopes(e.target.value)} placeholder="A new perspective, a sense of what 'good' looks like, a concrete next step — whatever you're hoping to walk away with." />
          </div>
        </div>

        {error && (
          <div className="app-banner error" style={{ borderRadius: 6, marginBottom: 12, border: '1px solid #f0bfb9' }}>
            <span><strong>•</strong> {error}</span>
          </div>
        )}

        <div className="booking-submit-row">
          <div className="booking-submit-fineprint">
            By submitting, you consent to Brook Consultancy holding the details above for the purpose of arranging your free strategic review. We will not share them with anyone outside Brook.
          </div>
          <button className="btn btn-primary booking-submit-btn" type="submit" disabled={loading || !valid}>
            {loading ? 'Saving…' : 'Book my 30 minutes →'}
          </button>
        </div>
      </form>

      <BookingFooter />
    </div>
  );
}

function BookingHero() {
  return (
    <header className="booking-hero">
      <div className="booking-hero-inner">
        <img src="assets/brook-logo-white.png" alt="Brook Consultancy Partners Ltd" className="booking-hero-logo" />
        <div className="booking-hero-eyebrow">Free strategic business review</div>
        <h1 className="booking-hero-title">30 minutes. Confidential. Honest insight.</h1>
        <p className="booking-hero-sub">
          Sit down with a Brook Consultancy partner at our J‑Trade stand, G19. Talk through where you are, where you want to be, and what's getting in the way. Leave with a tailored written one‑pager in your inbox before you’re back in the office.
        </p>
        <div className="booking-hero-pills">
          <span className="booking-hero-pill">✓ Confidential</span>
          <span className="booking-hero-pill">✓ Practical next steps</span>
          <span className="booking-hero-pill">✓ Written one-pager by email</span>
        </div>
      </div>
    </header>
  );
}

function BookingFooter() {
  return (
    <footer className="booking-footer">
      <div className="booking-footer-inner">
        <img src="assets/brook-mark.png" alt="" className="booking-footer-mark" />
        <div>
          <div><strong>Brook Consultancy Partners Ltd</strong></div>
          <div className="booking-footer-sub">Operational, regulatory & financial recovery for organisations that matter.</div>
        </div>
      </div>
    </footer>
  );
}

function BookingSuccess({ record }) {
  const b = record.booking;
  const slotDate = new Date(b.slot_iso);
  return (
    <div className="booking-page">
      <BookingHero />
      <div className="booking-success-card">
        <div className="booking-success-icon">✓</div>
        <h2 className="booking-success-title">You're booked.</h2>
        <p className="booking-success-sub">
          See you at <strong>{slotDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</strong> on the <strong>{b.preferred_zone}</strong> table.
        </p>

        <div className="booking-success-detail">
          <div className="booking-success-detail-row">
            <span className="label">Slot</span>
            <span className="value">{b.slot_label || slotDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}, {slotDate.toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' })}</span>
          </div>
          <div className="booking-success-detail-row">
            <span className="label">Zone</span>
            <span className="value">{b.preferred_zone}</span>
          </div>
          <div className="booking-success-detail-row">
            <span className="label">For</span>
            <span className="value">{b.business_name}</span>
          </div>
          <div className="booking-success-detail-row">
            <span className="label">One-pager will be sent to</span>
            <span className="value">{b.email}</span>
          </div>
        </div>

        <ol className="booking-success-steps">
          <li>Come to the Brook stand a few minutes before your slot.</li>
          <li>A team member will check you in and seat you at the <strong>{b.preferred_zone}</strong> table.</li>
          <li>You'll have a 30-minute structured conversation with a Brook consultant.</li>
          <li>Your one-pager will land in your inbox by the time you're back at your own stand.</li>
        </ol>

        <div className="booking-success-fineprint">
          If your plans change, just come and tell us at the stand — we'll release your slot.
        </div>
      </div>
      <BookingFooter />
    </div>
  );
}

Object.assign(window, { BookingPage, generateSlots, countTaken });
