// shared.jsx — primitives shared across the landing page.
// All user-facing text lives in copy/<locale>.json, loaded into
// window.COPY before any component renders. This file no longer
// contains copy — only the UI primitives that consume it.
// ------------------------------------------------------------

// ===== PRIMITIVES =====

// Striped placeholder for imagery — mono label inside
function StripedPlaceholder({ label, ratio='16/9', tone='warm', style={}, className='' }) {
  const tones = {
    warm:  { a: '#e8ddc8', b: '#d9c8a8', txt: '#6b5a3e' },
    cream: { a: '#f4ede0', b: '#e6d8bf', txt: '#7a6944' },
    clay:  { a: '#d4a48a', b: '#b8866c', txt: '#4a2e1e' },
    sage:  { a: '#b8c4a8', b: '#98a888', txt: '#2e3a24' },
    dark:  { a: '#2a2520', b: '#1a1612', txt: '#8a7a5a' },
    paper: { a: '#ece3d0', b: '#e0d5b8', txt: '#5a4a2a' },
    ink:   { a: '#141210', b: '#0a0908', txt: '#b8a77a' },
  };
  const t = tones[tone] || tones.warm;
  return (
    <div className={className} style={{
      aspectRatio: ratio,
      background: `repeating-linear-gradient(135deg, ${t.a} 0 18px, ${t.b} 18px 36px)`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      position: 'relative', overflow: 'hidden', ...style,
    }}>
      <span style={{
        fontFamily: "'DM Mono', ui-monospace, monospace",
        fontSize: 10, letterSpacing: 1.5, textTransform: 'uppercase',
        color: t.txt, background: `${t.a}cc`, padding: '4px 10px',
        border: `1px solid ${t.txt}40`, borderRadius: 1,
      }}>{label}</span>
    </div>
  );
}

// Glossary tooltip — wraps a term, shows definition on hover.
// Definitions come from window.COPY.glossario.
function Gloss({ term, children, color='currentColor' }) {
  const key = (term || (typeof children === 'string' ? children : '')).toLowerCase();
  const def = (window.COPY && window.COPY.glossario) ? window.COPY.glossario[key] : null;
  const [show, setShow] = React.useState(false);
  if (!def) return <span>{children}</span>;
  return (
    <span
      onMouseEnter={() => setShow(true)}
      onMouseLeave={() => setShow(false)}
      onFocus={() => setShow(true)}
      onBlur={() => setShow(false)}
      tabIndex={0}
      style={{
        position: 'relative',
        borderBottom: `1px dotted ${color}`,
        cursor: 'help',
        outline: 'none',
      }}
    >
      {children}
      {show && (
        <span style={{
          position: 'absolute', bottom: '120%', left: '50%',
          transform: 'translateX(-50%)',
          background: '#1a1612', color: '#f4ede0',
          padding: '10px 14px', borderRadius: 4,
          fontSize: 12, lineHeight: 1.45,
          fontFamily: "'Inter', sans-serif",
          width: 240, zIndex: 50,
          boxShadow: '0 12px 30px rgba(0,0,0,.25)',
          fontWeight: 400, letterSpacing: 0,
          textTransform: 'none', fontStyle: 'normal',
        }}>
          <span style={{
            display: 'block', fontFamily: "'DM Mono', monospace",
            fontSize: 9, letterSpacing: 1.5, textTransform: 'uppercase',
            color: '#b8a77a', marginBottom: 4,
          }}>{term || key}</span>
          {def}
        </span>
      )}
    </span>
  );
}

// Diet tag chip — labels come from window.COPY.menu (filter_*).

// ===== BOOKING FLOW (multi-step, functional) =====
function BookingModal({ open, onClose, palette }) {
  const c = window.COPY.booking;
  const [step, setStep] = React.useState(0);
  const [sending, setSending] = React.useState(false);
  const [error, setError] = React.useState('');
  const [data, setData] = React.useState({
    people: 2, date: '', time: '', name: '', phone: '', email: '', notes: '', consent: false,
  });

  React.useEffect(() => {
    if (open) {
      setStep(0); setError(''); setSending(false);
      setData(d => ({ ...d, date: '', time: '', consent: false }));
    }
  }, [open]);

  if (!open) return null;

  const p = palette || { bg:'#faf5ea', fg:'#1a1612', accent:'#c25a3a', muted:'#8a7a5a', line:'#1a161220' };

  // Bookable days. closed_weekdays holds JS weekday numbers (0 = domenica,
  // 1 = lunedì ...) and is edited from the CMS, so closures change without a
  // deploy. We scan further than 14 days because excluding days thins the grid.
  const closed = Array.isArray(c.closed_weekdays) ? c.closed_weekdays.map(Number) : [];
  const horizon = Number(c.booking_horizon_days) > 0 ? Number(c.booking_horizon_days) : 90;
  const today = new Date();
  const dates = [];
  for (let i = 0; i < horizon; i++) {
    const d = new Date(today); d.setDate(today.getDate() + i);
    if (closed.includes(d.getDay())) continue;
    dates.push({
      iso: d.toISOString().slice(0,10),
      dow: window.COPY.days_short[d.getDay()],
      day: d.getDate(),
      mon: window.COPY.months_short[d.getMonth()],
      monIdx: d.getMonth(),
    });
  }
  // Two services every open day: lunch and dinner. `times` was dinner-only.
  // Kept as two labelled lists so the CMS can change either service alone.
  const services = [
    { label: c.service_lunch_label,  slots: c.times_lunch  || [] },
    { label: c.service_dinner_label, slots: c.times_dinner || c.times || [] },
  ].filter(s => s.slots.length);

  // Loose on purpose — a rejected address costs a booking; the Worker checks too.
  const emailLooksValid = (s) => /^[^@\s]+@[^@\s.]+\.[^@\s]{2,}$/.test((s || '').trim());

  const canNext = [
    data.people > 0,
    !!data.date,
    !!data.time,
    data.name.length > 1 && data.phone.length > 5 && emailLooksValid(data.email),
  ][step];

  const steps = c.steps;

  const advance = () => {
    if (step < 3) { setStep(step + 1); return; }
    submit();
  };

  // Posts to Formspree, which emails the request to the restaurant. The
  // confirmation step is only reached once the POST actually succeeds — showing
  // "tutto a posto" for a request that never left the browser would be worse
  // than showing an error.
  const submit = async () => {
    const endpoint = window.BOOKING_ENDPOINT;
    if (!endpoint || endpoint.includes('XXXX')) {
      setError(c.error_unconfigured);
      return;
    }
    // Honeypot. No human sees this field; Formspree drops any submission that
    // fills _gotcha.
    const gotcha = (document.getElementById('gb-website') || {}).value || '';
    setSending(true);
    setError('');
    try {
      const res = await fetch(endpoint, {
        method: 'POST',
        headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
        body: JSON.stringify({
          // Underscore keys are Formspree directives, the rest become the body
          // of the email exactly as named.
          _subject: `Prenotazione — ${data.name}, ${data.people} p. il ${data.date} alle ${data.time}`,
          _gotcha: gotcha,
          Persone: data.people,
          Giorno: data.date,
          Orario: data.time,
          Nome: data.name,
          Telefono: data.phone,
          email: data.email,          // Formspree uses this as Reply-To
          'Consenso eventi': data.consent ? 'sì' : 'no',
          Note: data.notes || '—',
        }),
      });
      if (!res.ok) throw new Error('HTTP ' + res.status);
      setStep(4);
    } catch (err) {
      setError(c.error_send);
    } finally {
      setSending(false);
    }
  };

  const stepQuestions = [
    c.step_persone_question,
    c.step_giorno_question,
    c.step_orario_question,
    c.step_contatti_question,
  ];

  return (
    <div
      onClick={onClose}
      style={{
        position: 'fixed', inset: 0, zIndex: 1000,
        background: 'rgba(10,8,6,.6)', backdropFilter: 'blur(6px)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        padding: 20, fontFamily: "'Inter', sans-serif",
      }}
    >
      <div
        onClick={e => e.stopPropagation()}
        style={{
          background: p.bg, color: p.fg,
          width: '100%', maxWidth: 560, borderRadius: 4,
          boxShadow: '0 30px 80px rgba(0,0,0,.4)',
          overflow: 'hidden', border: `1px solid ${p.line}`,
        }}
      >
        <div style={{
          padding: '16px 22px', display: 'flex', justifyContent: 'space-between',
          alignItems: 'center', borderBottom: `1px solid ${p.line}`,
        }}>
          <div>
            <div style={{
              fontFamily: "'DM Mono', monospace", fontSize: 10,
              letterSpacing: 2, textTransform: 'uppercase', color: p.muted,
            }}>{c.label}</div>
            <div style={{ fontFamily: "'Fraunces', serif", fontSize: 20, marginTop: 2 }}>
              {step < 4 ? steps[step] : c.confirmation_title}
            </div>
          </div>
          <button onClick={onClose} style={{
            background: 'none', border: `1px solid ${p.line}`, width: 32, height: 32,
            borderRadius: 50, cursor: 'pointer', color: p.fg, fontSize: 16,
          }}>×</button>
        </div>

        {step < 4 && (
          <div style={{ padding: '6px 22px', display: 'flex', gap: 6 }}>
            {steps.map((s, i) => (
              <div key={i} style={{
                flex: 1, height: 3, borderRadius: 2,
                background: i <= step ? p.accent : p.line,
              }}/>
            ))}
          </div>
        )}

        <div style={{ padding: '26px 22px 20px', minHeight: 220 }}>
          {step < 4 && (
            <div style={{ color: p.muted, fontSize: 13, marginBottom: 18 }}>
              {stepQuestions[step]}
            </div>
          )}

          {step === 0 && (
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
              {[1,2,3,4,5,6,7,8].map(n => (
                <button key={n} onClick={() => setData({...data, people: n})} style={{
                  width: 56, height: 56, borderRadius: 50,
                  border: `1px solid ${data.people === n ? p.accent : p.line}`,
                  background: data.people === n ? p.accent : 'transparent',
                  color: data.people === n ? p.bg : p.fg,
                  fontFamily: "'Fraunces', serif", fontSize: 20, cursor: 'pointer',
                }}>{n}</button>
              ))}
              <button onClick={() => setData({...data, people: 9})} style={{
                height: 56, padding: '0 18px', borderRadius: 50,
                border: `1px solid ${data.people >= 9 ? p.accent : p.line}`,
                background: data.people >= 9 ? p.accent : 'transparent',
                color: data.people >= 9 ? p.bg : p.fg, cursor: 'pointer', fontSize: 13,
              }}>9+</button>
            </div>
          )}

          {step === 1 && (
            <div style={{ maxHeight: 260, overflowY: 'auto', paddingRight: 4 }}>
             <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 6 }}>
              {dates.map((d, i) => {
                const sel = data.date === d.iso;
                const newMonth = i === 0 || d.monIdx !== dates[i - 1].monIdx;
                return (
                  <React.Fragment key={d.iso}>
                  {newMonth && (
                    <div style={{
                      gridColumn: '1 / -1', marginTop: i === 0 ? 0 : 10, marginBottom: 2,
                      fontFamily: "'DM Mono', monospace", fontSize: 9, letterSpacing: 2,
                      textTransform: 'uppercase', color: p.muted,
                    }}>{window.COPY.months[d.monIdx]}</div>
                  )}
                  <button onClick={() => setData({...data, date: d.iso})} style={{
                    padding: '8px 4px', borderRadius: 4,
                    border: `1px solid ${sel ? p.accent : p.line}`,
                    background: sel ? p.accent : 'transparent',
                    color: sel ? p.bg : p.fg, cursor: 'pointer',
                    display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
                  }}>
                    <span style={{ fontSize: 9, letterSpacing: 1, opacity: .7, textTransform: 'uppercase' }}>{d.dow}</span>
                    <span style={{ fontFamily: "'Fraunces', serif", fontSize: 18 }}>{d.day}</span>
                    <span style={{ fontSize: 9, opacity: .7 }}>{d.mon}</span>
                  </button>
                  </React.Fragment>
                );
              })}
             </div>
            </div>
          )}

          {step === 2 && (
            <div>
              {services.map((svc, si) => (
                <div key={svc.label} style={{ marginTop: si ? 20 : 0 }}>
                  <div style={{
                    fontFamily: "'DM Mono', monospace", fontSize: 9, letterSpacing: 2,
                    textTransform: 'uppercase', color: p.muted, marginBottom: 8,
                  }}>{svc.label}</div>
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                    {svc.slots.map(t => {
                      const sel = data.time === t;
                      return (
                        <button key={t} onClick={() => setData({...data, time: t})} style={{
                          padding: '12px 18px', borderRadius: 50,
                          border: `1px solid ${sel ? p.accent : p.line}`,
                          background: sel ? p.accent : 'transparent',
                          color: sel ? p.bg : p.fg, cursor: 'pointer',
                          fontFamily: "'Fraunces', serif", fontSize: 16,
                        }}>{t}</button>
                      );
                    })}
                  </div>
                </div>
              ))}
              <div style={{ marginTop: 20, fontSize: 12, color: p.muted, fontStyle: 'italic' }}>
                {c.step_orario_note}
              </div>
            </div>
          )}

          {step === 3 && (
            <div style={{ display: 'grid', gap: 12 }}>
              {/* Honeypot. Off-screen rather than display:none, which some bots
                  know to skip; hidden from a11y and from autofill. */}
              <input id="gb-website" name="website" tabIndex={-1} autoComplete="off"
                aria-hidden="true"
                style={{
                  position: 'absolute', left: '-9999px', width: 1, height: 1,
                  opacity: 0, pointerEvents: 'none',
                }}/>
              <input value={data.name} onChange={e => setData({...data, name: e.target.value})}
                placeholder={c.placeholder_name}
                style={{
                  padding: '12px 14px', border: `1px solid ${p.line}`, borderRadius: 4,
                  fontSize: 15, background: 'transparent', color: p.fg,
                  fontFamily: "'Inter', sans-serif", outline: 'none',
                }}/>
              <input value={data.phone} onChange={e => setData({...data, phone: e.target.value})}
                placeholder={c.placeholder_phone}
                inputMode="tel" autoComplete="tel"
                style={{
                  padding: '12px 14px', border: `1px solid ${p.line}`, borderRadius: 4,
                  fontSize: 15, background: 'transparent', color: p.fg,
                  fontFamily: "'Inter', sans-serif", outline: 'none',
                }}/>
              <input value={data.email} onChange={e => setData({...data, email: e.target.value})}
                placeholder={c.placeholder_email}
                type="email" inputMode="email" autoComplete="email"
                style={{
                  padding: '12px 14px', border: `1px solid ${p.line}`, borderRadius: 4,
                  fontSize: 15, background: 'transparent', color: p.fg,
                  fontFamily: "'Inter', sans-serif", outline: 'none',
                }}/>
              <textarea value={data.notes} onChange={e => setData({...data, notes: e.target.value})}
                placeholder={c.placeholder_notes}
                rows={2}
                style={{
                  padding: '12px 14px', border: `1px solid ${p.line}`, borderRadius: 4,
                  fontSize: 14, background: 'transparent', color: p.fg, resize: 'none',
                  fontFamily: "'Inter', sans-serif", outline: 'none',
                }}/>
            </div>
          )}

          {step === 4 && (
            <div style={{ textAlign: 'center', padding: '10px 0 20px' }}>
              <div style={{ fontFamily: "'Caveat', cursive", fontSize: 42, color: p.accent, lineHeight: 1 }}>
                {c.confirmation_caveat}
              </div>
              <div style={{ fontFamily: "'Fraunces', serif", fontSize: 22, marginTop: 16 }}>
                {data.name} · {data.people} {c.confirmation_summary_persone}
              </div>
              <div style={{ color: p.muted, marginTop: 6, fontSize: 14 }}>
                {data.date} {c.confirmation_detail_connector} {data.time}
              </div>
              <div style={{
                marginTop: 22, fontSize: 12, color: p.muted,
                fontStyle: 'italic', maxWidth: 340, margin: '22px auto 0',
              }}>
                {c.confirmation_note}
              </div>
            </div>
          )}
        </div>

        {step < 4 && (
          <div style={{ borderTop: `1px solid ${p.line}` }}>
            {error && (
              <div role="alert" style={{
                padding: '12px 22px 0', color: '#a33',
                fontFamily: "'Inter', sans-serif", fontSize: 13, lineHeight: 1.45,
              }}>{error}</div>
            )}
            {/* Consent notice. Sits with the send button because submitting is
                what gives the permission. */}
            {step === 3 && (
              <label style={{
                display: 'flex', gap: 10, alignItems: 'flex-start', cursor: 'pointer',
                padding: '12px 22px 0', color: p.muted,
                fontFamily: "'Inter', sans-serif", fontSize: 11.5, lineHeight: 1.45,
              }}>
                <input
                  type="checkbox"
                  checked={data.consent}
                  onChange={e => setData({ ...data, consent: e.target.checked })}
                  style={{ marginTop: 2, width: 15, height: 15, flexShrink: 0, accentColor: p.accent }}
                />
                <span>{c.consent_notice}</span>
              </label>
            )}
            <div style={{
              padding: '14px 22px',
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            }}>
              <button onClick={() => step > 0 && !sending && setStep(step - 1)} style={{
                background: 'none', border: 'none', color: p.muted,
                fontSize: 13, cursor: step > 0 && !sending ? 'pointer' : 'default',
                opacity: step > 0 && !sending ? 1 : 0.3,
              }}>{c.nav_back}</button>
              <button disabled={!canNext || sending} onClick={advance} style={{
                background: canNext && !sending ? p.accent : p.line,
                color: canNext && !sending ? p.bg : p.muted,
                border: 'none', padding: '12px 28px', borderRadius: 50,
                fontSize: 14, cursor: canNext && !sending ? 'pointer' : 'not-allowed',
                fontFamily: "'Inter', sans-serif", fontWeight: 500,
              }}>
                {sending ? c.nav_sending : step === 3 ? c.nav_book : c.nav_continue}
              </button>
            </div>
          </div>
        )}

        {step === 4 && (
          <div style={{ padding: '14px 22px', borderTop: `1px solid ${p.line}` }}>
            <button onClick={onClose} style={{
              width: '100%', background: p.btn || p.fg, color: p.bg,
              border: 'none', padding: '14px', borderRadius: 50,
              fontSize: 14, cursor: 'pointer', fontFamily: "'Inter', sans-serif",
            }}>{c.nav_close}</button>
          </div>
        )}
      </div>
    </div>
  );
}

// ===== WINE DETAIL MODAL =====


// Expose primitives globally so direction-editorial-v2.jsx can reference them.
Object.assign(window, {
  StripedPlaceholder, Gloss,
  BookingModal,
});
