// scheduler.jsx — AI scheduling assistant: chat drives a live calendar + time slots, then books.
const { useState, useRef, useEffect } = React;

const TODAY = (() => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), d.getDate()); })();
const DOW = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const DOW_FULL = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const MON = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const SLOTS = ['09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30'];

const fmtISO = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
const parseISO = (s) => { const [y, m, d] = s.split('-').map(Number); return new Date(y, m - 1, d); };
const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
const addDays = (d, n) => { const x = new Date(d); x.setDate(x.getDate() + n); return x; };
const hashStr = (s) => { let h = 0; for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) % 100000; return h; };

const isWeekend = (d) => d.getDay() === 0 || d.getDay() === 6;
const isBookable = (d) => !isWeekend(d) && startOfDay(d) > startOfDay(TODAY);

// Deterministic "already booked" slots per day.
function bookedSet(iso) {
  const h = hashStr(iso);
  const set = new Set();
  SLOTS.forEach((t, i) => { if ((h >> i) % 3 === 0) set.add(t); });
  return set;
}
function freeSlots(iso) { const b = bookedSet(iso); return SLOTS.filter((t) => !b.has(t)); }
function firstOpenDay() { let d = addDays(TODAY, 1); for (let i = 0; i < 30; i++) { if (isBookable(d) && freeSlots(fmtISO(d)).length) return d; d = addDays(d, 1); } return addDays(TODAY, 3); }

const to12 = (t) => { let [h, m] = t.split(':').map(Number); const ap = h >= 12 ? 'PM' : 'AM'; h = h % 12 || 12; return `${h}:${String(m).padStart(2, '0')} ${ap}`; };

function buildSchedulefPrompt(history, topic) {
  const days = [];
  let d = addDays(TODAY, 1);
  for (let i = 0; days.length < 12 && i < 30; i++) { if (isBookable(d)) days.push(fmtISO(d)); d = addDays(d, 1); }
  const convo = history.map((m) => `${m.role === 'user' ? 'Customer' : 'Assistant'}: ${m.text}`).join('\n');
  return `You are the scheduling assistant for ITbyPeople, a human-first managed IT provider. Voice: warm, honest, clear, jargon-free. Lead with the person; AI is just the tool. No exclamation marks. Never use fear language.

Today is Friday, June 12, 2026. Calls are 30 minutes by default with a real engineer, Mon–Fri.
Bookable dates (YYYY-MM-DD): ${days.join(', ')}.
Slot times available each day: ${SLOTS.join(', ')} (24h).

Conversation so far:
${convo}

Reply to the customer's latest message in ONE or TWO short sentences, then propose a concrete date and 2–3 times that fit what they said (pick from the bookable dates/slots; if they named a day like "Thursday afternoon", map it to the matching date and afternoon slots). If they have not hinted at timing, suggest the soonest sensible date.

Return ONLY minified JSON, no prose, in exactly this shape:
{"reply":"<your 1-2 sentence reply>","topic":"<short summary of what they need, <=6 words>","durationMins":30,"suggestedDate":"<YYYY-MM-DD or empty>","suggestedTimes":["HH:MM","HH:MM"]}`;
}

// Heuristic fallback so the demo always works (rate limit / offline).
function heuristicSchedule(history, prevTopic) {
  const last = (history.filter((m) => m.role === 'user').slice(-1)[0] || {}).text || '';
  const l = last.toLowerCase();
  let topic = prevTopic || 'IT support call';
  if (/fire ?wall|network|wifi|wi-fi|internet|slow/.test(l)) topic = 'Network / firewall issue';
  else if (/secur|phish|virus|ransom|breach|suspici/.test(l)) topic = 'Security review';
  else if (/email|outlook|microsoft|365|mailbox/.test(l)) topic = 'Email & accounts';
  else if (/cloud|backup|server|migrat/.test(l)) topic = 'Cloud & infrastructure';
  else if (/onboard|new hire|laptop|setup|set up/.test(l)) topic = 'New-hire onboarding';
  else if (/audit|assess|review|consult|strategy|roadmap|ai/.test(l)) topic = 'IT strategy consult';
  let day = firstOpenDay();
  if (/today/.test(l)) day = firstOpenDay();
  if (/tomorrow/.test(l)) { let d = addDays(TODAY, 1); while (!isBookable(d)) d = addDays(d, 1); day = d; }
  const named = DOW_FULL.findIndex((n) => l.includes(n.toLowerCase()));
  if (named >= 0) { let d = addDays(TODAY, 1); for (let i = 0; i < 14; i++) { if (d.getDay() === named && isBookable(d) && freeSlots(fmtISO(d)).length) { day = d; break; } d = addDays(d, 1); } }
  const iso = fmtISO(day);
  const pm = /after ?noon|pm|lunch|after lunch/.test(l);
  const am = /morning|am|early/.test(l);
  let pool = freeSlots(iso);
  if (pm) pool = pool.filter((t) => Number(t.split(':')[0]) >= 13);
  if (am) pool = pool.filter((t) => Number(t.split(':')[0]) < 12);
  if (!pool.length) pool = freeSlots(iso);
  const times = pool.slice(0, 3);
  const reply = `Happy to get you set up — it sounds like ${topic.toLowerCase()}. A few times that work are below; pick whatever suits and a real engineer will be on the call.`;
  return { reply, topic, durationMins: 30, suggestedDate: iso, suggestedTimes: times };
}

function makeICS({ iso, time, topic, name }) {
  const [y, m, d] = iso.split('-');
  const [hh, mm] = time.split(':');
  const dt = `${y}${m}${d}T${hh}${mm}00`;
  const endH = String(Number(hh) + (Number(mm) + 30 >= 60 ? 1 : 0)).padStart(2, '0');
  const endM = String((Number(mm) + 30) % 60).padStart(2, '0');
  const dtEnd = `${y}${m}${d}T${endH}${endM}00`;
  const body = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-//ITbyPeople//Scheduler//EN', 'BEGIN:VEVENT',
    `UID:${Date.now()}@itbypeople.com`, `DTSTART:${dt}`, `DTEND:${dtEnd}`,
    `SUMMARY:ITbyPeople call — ${topic}`, `DESCRIPTION:30-minute call with an ITbyPeople engineer for ${name || 'you'}.`,
    'LOCATION:Video call (link emailed)', 'END:VEVENT', 'END:VCALENDAR'].join('\r\n');
  return 'data:text/calendar;charset=utf-8,' + encodeURIComponent(body);
}

function Scheduler() {
  const ns = window.ITbyPeopleDesignSystem_44acd8 || {};
  const { Button, Input, Badge } = ns;
  const [messages, setMessages] = useState([
    { role: 'assistant', text: "Hi — I'm here to get you on the calendar with a real engineer. Tell me what's going on and when works for you, and I'll find a time." },
  ]);
  const [draft, setDraft] = useState('');
  const [loading, setLoading] = useState(false);
  const [topic, setTopic] = useState('');
  const [visMonth, setVisMonth] = useState(new Date(firstOpenDay().getFullYear(), firstOpenDay().getMonth(), 1));
  const [selDate, setSelDate] = useState(fmtISO(firstOpenDay()));
  const [suggested, setSuggested] = useState({ date: '', times: [] });
  const [selTime, setSelTime] = useState('');
  const [step, setStep] = useState('pick'); // pick | details | confirmed
  const [form, setForm] = useState({ name: '', email: '', phone: '' });
  const [availCache, setAvailCache] = useState({});
  const [availLoading, setAvailLoading] = useState(false);
  const chatRef = useRef(null);

  useEffect(() => { if (chatRef.current) chatRef.current.scrollTop = chatRef.current.scrollHeight; }, [messages, loading]);

  useEffect(() => {
    if (!selDate || availCache[selDate]) return;
    setAvailLoading(true);
    fetch(`/api/scheduling/availability?date=${selDate}`)
      .then((r) => r.json())
      .then((d) => setAvailCache((prev) => ({ ...prev, [selDate]: new Set(d.booked || []) })))
      .catch(() => setAvailCache((prev) => ({ ...prev, [selDate]: bookedSet(selDate) })))
      .finally(() => setAvailLoading(false));
  }, [selDate]);

  async function send(text) {
    const t = (text || '').trim();
    if (!t || loading) return;
    const next = [...messages, { role: 'user', text: t }];
    setMessages(next); setDraft(''); setLoading(true);
    const fb = heuristicSchedule(next, topic);
    const res = await askClaudeJSON(buildSchedulefPrompt(next, topic), fb);
    const r = res && res.reply ? res : fb;
    setMessages((m) => [...m, { role: 'assistant', text: r.reply || fb.reply }]);
    if (r.topic) setTopic(r.topic);
    if (r.suggestedDate && /^\d{4}-\d{2}-\d{2}$/.test(r.suggestedDate)) {
      const dd = parseISO(r.suggestedDate);
      if (isBookable(dd)) {
        setVisMonth(new Date(dd.getFullYear(), dd.getMonth(), 1));
        setSelDate(r.suggestedDate);
        const valid = (r.suggestedTimes || []).filter((x) => freeSlots(r.suggestedDate).includes(x));
        setSuggested({ date: r.suggestedDate, times: valid });
        setSelTime(valid[0] || '');
        setStep('pick');
      }
    }
    setLoading(false);
  }

  // calendar grid for visible month
  const first = new Date(visMonth.getFullYear(), visMonth.getMonth(), 1);
  const startPad = first.getDay();
  const daysInMonth = new Date(visMonth.getFullYear(), visMonth.getMonth() + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < startPad; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(visMonth.getFullYear(), visMonth.getMonth(), d));
  const canPrevMonth = new Date(visMonth.getFullYear(), visMonth.getMonth(), 1) > new Date(TODAY.getFullYear(), TODAY.getMonth(), 1);

  const selDateObj = parseISO(selDate);
  const slotsForSel = SLOTS;
  const bookedNow = availCache[selDate] || bookedSet(selDate);
  const chips = ['Our firewall is acting up', 'Onboard a new hire next week', 'Quick security check-in'];

  const cardStyle = { backgroundColor: '#fff', border: '0.5px solid var(--color-line)', borderRadius: 'var(--radius-xl)', boxShadow: 'var(--shadow-md)', overflow: 'hidden' };

  if (step === 'confirmed') {
    return (
      <div style={{ ...cardStyle, maxWidth: 720, margin: '0 auto', padding: 0 }}>
        <div style={{ background: 'linear-gradient(180deg,#0F2645,#13315B)', padding: '40px 40px 34px', color: '#fff', position: 'relative', overflow: 'hidden' }}>
          <Constellation opacity={0.4} seed={21} />
          <div style={{ position: 'relative' }}>
            <div style={{ width: 52, height: 52, borderRadius: '50%', backgroundColor: 'var(--color-teal)', display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 18 }}>
              <Icon name="check" size={28} color="#fff" strokeWidth={2.2} />
            </div>
            <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 30, margin: '0 0 6px', letterSpacing: '-0.02em' }}>You're on the calendar.</h3>
            <p style={{ margin: 0, color: 'rgba(255,255,255,0.78)', fontSize: 15.5, lineHeight: 1.6 }}>A real engineer will call you. We've sent a confirmation and a calendar invite to your email.</p>
          </div>
        </div>
        <div style={{ padding: '28px 40px 34px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 18, marginBottom: 22 }}>
            {[['When', `${DOW_FULL[selDateObj.getDay()]}, ${MON[selDateObj.getMonth()]} ${selDateObj.getDate()}`], ['Time', `${to12(selTime)} · 30 min`], ['About', topic || 'IT support call'], ['For', form.name || 'You']].map(([k, v]) => (
              <div key={k}>
                <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase', color: 'var(--color-slate)', marginBottom: 5 }}>{k}</div>
                <div style={{ fontSize: 15.5, color: 'var(--color-navy)', fontWeight: 600 }}>{v}</div>
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap' }}>
            <a href={makeICS({ iso: selDate, time: selTime, topic, name: form.name })} download="itbypeople-call.ics" style={{ textDecoration: 'none' }}>
              <Button variant="primary" iconLeft={<Icon name="calendar" size={17} color="#fff" />}>Add to calendar</Button>
            </a>
            <Button variant="secondary" onClick={() => { setStep('pick'); setSelTime(''); setForm({ name: '', email: '', phone: '' }); setMessages([{ role: 'assistant', text: "Glad that's set. Need to book another? Tell me what's next." }]); setTopic(''); }}>Book another</Button>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div style={{ ...cardStyle, display: 'grid', gridTemplateColumns: '1fr 1.05fr' }} className="sched-grid">
      {/* LEFT — AI chat */}
      <div style={{ display: 'flex', flexDirection: 'column', backgroundColor: 'var(--color-cloud)', borderRight: '0.5px solid var(--color-line)', minHeight: 540 }}>
        <div style={{ padding: '20px 22px 16px', borderBottom: '0.5px solid var(--color-line)', display: 'flex', alignItems: 'center', gap: 11 }}>
          <div style={{ width: 38, height: 38, borderRadius: '50%', backgroundColor: 'var(--color-navy)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
            <Icon name="sparkles" size={19} color="var(--color-teal)" />
          </div>
          <div>
            <div style={{ fontWeight: 700, color: 'var(--color-navy)', fontSize: 15 }}>Schedule with AI</div>
            <div style={{ fontSize: 12.5, color: 'var(--color-slate)' }}>Describe it in plain words — a person takes the call</div>
          </div>
        </div>
        <div ref={chatRef} style={{ flex: 1, overflowY: 'auto', padding: '20px 22px', display: 'flex', flexDirection: 'column', gap: 12 }}>
          {messages.map((m, i) => (
            <div key={i} style={{ alignSelf: m.role === 'user' ? 'flex-end' : 'flex-start', maxWidth: '88%', backgroundColor: m.role === 'user' ? 'var(--color-teal)' : '#fff', color: m.role === 'user' ? '#fff' : 'var(--color-ink)', border: m.role === 'user' ? 'none' : '0.5px solid var(--color-line)', borderRadius: m.role === 'user' ? '14px 14px 4px 14px' : '14px 14px 14px 4px', padding: '11px 14px', fontSize: 14.5, lineHeight: 1.5, boxShadow: 'var(--shadow-xs)' }}>{m.text}</div>
          ))}
          {loading && (
            <div style={{ alignSelf: 'flex-start', backgroundColor: '#fff', border: '0.5px solid var(--color-line)', borderRadius: '14px 14px 14px 4px', padding: '13px 16px', display: 'flex', gap: 5 }}>
              {[0, 1, 2].map((i) => <span key={i} className="typedot" style={{ animationDelay: `${i * 0.16}s` }} />)}
            </div>
          )}
          {messages.length <= 1 && !loading && (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginTop: 4 }}>
              {chips.map((c) => (
                <button key={c} onClick={() => send(c)} style={{ textAlign: 'left', backgroundColor: '#fff', border: '1px solid var(--color-teal-mid)', color: 'var(--color-teal-deep)', borderRadius: 'var(--radius-md)', padding: '9px 13px', fontSize: 13.5, fontFamily: 'var(--font-sans)', cursor: 'pointer', fontWeight: 500 }}>{c}</button>
              ))}
            </div>
          )}
        </div>
        <form onSubmit={(e) => { e.preventDefault(); send(draft); }} style={{ padding: '14px 16px', borderTop: '0.5px solid var(--color-line)', display: 'flex', gap: 8, backgroundColor: '#fff' }}>
          <input value={draft} onChange={(e) => setDraft(e.target.value)} placeholder="e.g. Thursday afternoon works…" className="itp-input" style={{ flex: 1, height: 44, border: '1px solid var(--color-line)', borderRadius: 'var(--radius-md)', padding: '0 14px', fontFamily: 'var(--font-sans)', fontSize: 14, outline: 'none' }} />
          <button type="submit" disabled={!draft.trim() || loading} style={{ width: 44, height: 44, borderRadius: 'var(--radius-md)', border: 'none', backgroundColor: 'var(--color-teal)', color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: draft.trim() ? 'pointer' : 'default', opacity: draft.trim() && !loading ? 1 : 0.5, flexShrink: 0 }}><Icon name="send" size={18} color="#fff" /></button>
        </form>
      </div>

      {/* RIGHT — calendar + slots / details */}
      <div style={{ padding: '22px 26px 26px', display: 'flex', flexDirection: 'column' }}>
        {step === 'pick' && (
          <>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
              <div style={{ fontFamily: 'var(--font-display)', fontSize: 20, color: 'var(--color-navy)' }}>{MON[visMonth.getMonth()]} {visMonth.getFullYear()}</div>
              <div style={{ display: 'flex', gap: 6 }}>
                <button onClick={() => canPrevMonth && setVisMonth(new Date(visMonth.getFullYear(), visMonth.getMonth() - 1, 1))} disabled={!canPrevMonth} style={navBtn(!canPrevMonth)}><Icon name="chevronLeft" size={18} color="var(--color-navy)" /></button>
                <button onClick={() => setVisMonth(new Date(visMonth.getFullYear(), visMonth.getMonth() + 1, 1))} style={navBtn(false)}><Icon name="chevronRight" size={18} color="var(--color-navy)" /></button>
              </div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 4, marginBottom: 6 }}>
              {DOW.map((d) => <div key={d} style={{ textAlign: 'center', fontSize: 11, fontWeight: 600, color: 'var(--color-slate)', padding: '2px 0' }}>{d[0]}</div>)}
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7,1fr)', gap: 4 }}>
              {cells.map((c, i) => {
                if (!c) return <div key={i} />;
                const iso = fmtISO(c);
                const ok = isBookable(c) && freeSlots(iso).length > 0;
                const isSel = iso === selDate;
                const isSug = iso === suggested.date;
                return (
                  <button key={i} disabled={!ok} onClick={() => { setSelDate(iso); setSelTime(''); }} style={{
                    aspectRatio: '1', borderRadius: 9, border: isSug && !isSel ? '1.5px solid var(--color-teal)' : '1px solid transparent',
                    backgroundColor: isSel ? 'var(--color-teal)' : ok ? '#fff' : 'transparent', color: isSel ? '#fff' : ok ? 'var(--color-navy)' : 'var(--color-line)',
                    fontFamily: 'var(--font-sans)', fontSize: 13.5, fontWeight: isSel ? 700 : 500, cursor: ok ? 'pointer' : 'default',
                    boxShadow: isSel ? 'var(--shadow-sm)' : 'none', transition: 'all 120ms', position: 'relative',
                  }}>{c.getDate()}{isSug && !isSel && <span style={{ position: 'absolute', bottom: 4, left: '50%', transform: 'translateX(-50%)', width: 4, height: 4, borderRadius: '50%', backgroundColor: 'var(--color-teal)' }} />}</button>
                );
              })}
            </div>

            <div style={{ marginTop: 18, marginBottom: 10, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
              <div style={{ fontSize: 14, fontWeight: 700, color: 'var(--color-navy)' }}>{DOW_FULL[selDateObj.getDay()]}, {MON[selDateObj.getMonth()]} {selDateObj.getDate()}</div>
              {suggested.date === selDate && suggested.times.length > 0 && (
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 11.5, fontWeight: 600, color: 'var(--color-teal-deep)', backgroundColor: 'var(--color-mist)', padding: '4px 9px', borderRadius: 999 }}><Icon name="sparkles" size={12} color="var(--color-teal)" />AI suggested</span>
              )}
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 8, overflowY: 'auto', maxHeight: 168 }}>
              {slotsForSel.map((t) => {
                const booked = bookedNow.has(t);
                const isSel = t === selTime;
                const isSug = suggested.date === selDate && suggested.times.includes(t);
                return (
                  <button key={t} disabled={booked} onClick={() => setSelTime(t)} style={{
                    height: 40, borderRadius: 'var(--radius-md)', fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600,
                    cursor: booked ? 'default' : 'pointer', transition: 'all 120ms',
                    border: isSel ? '1.5px solid var(--color-teal)' : isSug ? '1.5px solid var(--color-teal-mid)' : '1px solid var(--color-line)',
                    backgroundColor: isSel ? 'var(--color-teal)' : booked ? 'var(--color-cloud)' : isSug ? 'var(--color-mist)' : '#fff',
                    color: isSel ? '#fff' : booked ? 'var(--color-line)' : isSug ? 'var(--color-teal-deep)' : 'var(--color-navy)',
                    textDecoration: booked ? 'line-through' : 'none',
                  }}>{to12(t)}</button>
                );
              })}
            </div>
            <div style={{ marginTop: 'auto', paddingTop: 18 }}>
              <Button variant="primary" fullWidth disabled={!selTime} onClick={() => setStep('details')} iconRight={<Icon name="arrowRight" size={17} color="#fff" />}>
                {selTime ? `Continue · ${to12(selTime)}` : 'Pick a time to continue'}
              </Button>
            </div>
          </>
        )}

        {step === 'details' && (
          <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
            <button onClick={() => setStep('pick')} style={{ alignSelf: 'flex-start', display: 'inline-flex', alignItems: 'center', gap: 4, backgroundColor: 'transparent', border: 'none', color: 'var(--color-slate)', cursor: 'pointer', fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, padding: 0, marginBottom: 16 }}><Icon name="chevronLeft" size={15} color="var(--color-slate)" />Back to times</button>
            <h3 style={{ fontFamily: 'var(--font-display)', fontSize: 22, color: 'var(--color-navy)', margin: '0 0 4px' }}>Last step — who are we calling?</h3>
            <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, marginBottom: 20, color: 'var(--color-teal-deep)', backgroundColor: 'var(--color-mist)', border: '1px solid var(--color-teal-mid)', borderRadius: 'var(--radius-md)', padding: '9px 13px', fontSize: 13.5, fontWeight: 600, alignSelf: 'flex-start' }}>
              <Icon name="calendar" size={15} color="var(--color-teal)" />{DOW_FULL[selDateObj.getDay()]}, {MON[selDateObj.getMonth()]} {selDateObj.getDate()} · {to12(selTime)}
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
              <Input label="Your name" placeholder="Jordan Rivera" value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} />
              <Input label="Work email" type="email" placeholder="you@company.com" value={form.email} onChange={(e) => setForm({ ...form, email: e.target.value })} />
              <Input label="Phone (optional)" placeholder="(555) 010-2840" value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })} />
              <div>
                <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--color-navy)', marginBottom: 6 }}>What it's about</div>
                <div style={{ fontSize: 14, color: 'var(--color-ink)', backgroundColor: 'var(--color-cloud)', border: '1px solid var(--color-line)', borderRadius: 'var(--radius-md)', padding: '11px 14px' }}>{topic || 'IT support call'}</div>
              </div>
            </div>
            <div style={{ marginTop: 'auto', paddingTop: 20 }}>
              <Button variant="primary" fullWidth disabled={!form.name.trim() || !form.email.trim()} onClick={async () => {
                try {
                  const r = await fetch('/api/scheduling/bookings', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ date: selDate, time: selTime, duration_mins: 30, topic: topic || 'IT support call', name: form.name, email: form.email, phone: form.phone }),
                  });
                  if (r.status === 409) {
                    alert('Sorry — that slot was just taken. Please pick another time.');
                    setStep('pick');
                    setAvailCache((prev) => { const n = { ...prev }; delete n[selDate]; return n; });
                    return;
                  }
                } catch { /* save failed silently — still show confirmation */ }
                setStep('confirmed');
              }}>Confirm booking</Button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function navBtn(disabled) {
  return { width: 34, height: 34, borderRadius: 'var(--radius-md)', border: '1px solid var(--color-line)', backgroundColor: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: disabled ? 'default' : 'pointer', opacity: disabled ? 0.4 : 1 };
}

Object.assign(window, { Scheduler });
