// Sitar — Reservation wizard. 5 steps: date → time → party → details → confirm.
// Talks to the backend API:
//   GET  /api/availability?date=YYYY-MM-DD  →  { slots: { '12:00': 7, ... }, totalTables: 30 }
//   POST /api/reservations                  →  { id, date, time, party, ... } | 409 slot_full
// Availability is fetched when a date is picked, then re-fetched after each
// confirmed booking so a second reservation in the same session sees the update.

const { c: rc, f: rf } = window.SITAR;

const API_BASE = (window.SITAR_API_BASE || '').replace(/\/$/, ''); // e.g. '' or 'https://api.example.com'
const TOTAL_TABLES = 30;

const tablesNeeded = (party) => party <= 4 ? 1 : 2;

// availability: { '12:00': 7, '12:30': 12, ... } — tables booked at each slot.
// `null` = not loaded yet; `{}` = loaded but empty (no bookings).
const tablesBookedAt = (time, availability) => {
  if (!availability) return 0;
  return availability[time] || 0;
};

const fmtDate = (d, lang) => {
  const days = lang === 'de'
    ? ['So','Mo','Di','Mi','Do','Fr','Sa']
    : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
  const months = lang === 'de'
    ? ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez']
    : ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
  return `${days[d.getDay()]} · ${d.getDate()} ${months[d.getMonth()]}`;
};
const fmtDateLong = (d, lang) => {
  const days = lang === 'de'
    ? ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag']
    : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  const months = lang === 'de'
    ? ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember']
    : ['January','February','March','April','May','June','July','August','September','October','November','December'];
  return lang === 'de'
    ? `${days[d.getDay()]}, ${d.getDate()}. ${months[d.getMonth()]} ${d.getFullYear()}`
    : `${days[d.getDay()]}, ${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`;
};

// ─── Reusable bits ─────────────────────────────────────────

const ProgressBar = ({ step }) => (
  <div style={{ height: 2, background: rc.lineDark, position:'relative' }}>
    <div style={{
      position:'absolute', left: 0, top:0, bottom:0,
      width: `${(step / 5) * 100}%`, background: rc.tandoor,
      transition:'width .3s cubic-bezier(.2,.7,.3,1)',
    }}/>
  </div>
);

const ModalShell = ({ step, title, onClose, onBack, onNext, nextLabel, nextDisabled = false, hideFooter, children, summary }) => {
  const { t } = useLang();
  const { mobile } = useBreakpoint();
  const defaultNext = t('Weiter →', 'Continue →');
  const label = nextLabel !== undefined ? nextLabel : defaultNext;
  return (
    <div style={{
      width: mobile ? '100%' : 760, maxWidth: 760,
      maxHeight: mobile ? '100%' : '92vh',
      height: mobile ? '100%' : 'auto',
      background: rc.bone, color: rc.night,
      boxShadow: '0 40px 100px rgba(0,0,0,0.5)', display: 'flex', flexDirection: 'column',
      fontFamily: rf.sans,
    }}>
      <div style={{ padding: mobile ? '18px 20px 16px' : '24px 36px 22px', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', borderBottom: `1px solid ${rc.lineDark}` }}>
        <div>
          <div style={{ fontFamily: rf.mono, fontSize: 11, letterSpacing: 2.5, color: rc.tandoor, textTransform:'uppercase' }}>
            {t(`Schritt ${String(step).padStart(2,'0')} von 05`, `Step ${String(step).padStart(2,'0')} of 05`)}
          </div>
          <div style={{ fontFamily: rf.serif, fontSize: mobile ? 26 : 36, fontStyle: 'italic', fontWeight: 500, marginTop: 4, letterSpacing: -0.5, lineHeight: 1.1 }}>{title}</div>
        </div>
        <div
          onClick={onClose}
          style={{ fontSize: 28, opacity: 0.5, cursor:'pointer', fontFamily: rf.serif, lineHeight: 1, padding: 4 }}
          onMouseEnter={e => e.currentTarget.style.opacity = 1}
          onMouseLeave={e => e.currentTarget.style.opacity = 0.5}
        >×</div>
      </div>
      <ProgressBar step={step} />
      {summary && (
        <div style={{ padding: mobile ? '10px 20px' : '14px 36px', background: rc.boneDeep + '50', display: 'flex', gap: 14, fontFamily: rf.mono, fontSize: 11, letterSpacing: 1.8, textTransform: 'uppercase', opacity: 0.75, flexWrap: 'wrap' }}>
          {summary.map((s, i) => (
            <React.Fragment key={i}>
              {i > 0 && <span style={{ opacity: 0.4 }}>·</span>}
              <span>{s}</span>
            </React.Fragment>
          ))}
        </div>
      )}
      <div style={{ padding: mobile ? 20 : 36, overflowY: 'auto', flex: 1 }}>{children}</div>
      {!hideFooter && (
        <div style={{ padding: mobile ? '14px 20px' : '18px 36px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderTop: `1px solid ${rc.lineDark}`, background: rc.boneDeep + '40' }}>
          <button
            onClick={onBack}
            disabled={!onBack}
            style={{
              background:'none', border:'none', fontFamily: rf.sans, fontSize: 12,
              letterSpacing: 1.5, textTransform:'uppercase', cursor: onBack ? 'pointer' : 'default',
              color: rc.night, opacity: onBack ? 0.7 : 0.25,
            }}
          >{t('← Zurück', '← Back')}</button>
          <button
            onClick={onNext}
            disabled={nextDisabled}
            style={{
              background: nextDisabled ? rc.night + '30' : rc.night,
              color: rc.bone, border:'none',
              padding:'14px 28px', fontFamily: rf.sans, fontSize: 12, fontWeight: 600,
              letterSpacing: 2, textTransform:'uppercase',
              cursor: nextDisabled ? 'not-allowed' : 'pointer',
            }}
          >{label}</button>
        </div>
      )}
    </div>
  );
};

// ─── Step 1: Date ─────────────────────────────────────────

const StepDate = ({ value, onChange }) => {
  const { lang, t } = useLang();
  const today = new Date(); today.setHours(0,0,0,0);
  const [monthOffset, setMonthOffset] = React.useState(0);
  const ref = new Date(today.getFullYear(), today.getMonth() + monthOffset, 1);
  const monthName = ref.toLocaleDateString(lang === 'de' ? 'de-DE' : 'en-US', { month: 'long', year: 'numeric' });
  const firstDow = (ref.getDay() + 6) % 7; // Mon=0
  const daysInMonth = new Date(ref.getFullYear(), ref.getMonth() + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < firstDow; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(ref.getFullYear(), ref.getMonth(), d));
  const localISO = (d) => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
  const dayHeaders = lang === 'de'
    ? ['Mo','Di','Mi','Do','Fr','Sa','So']
    : ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];

  return (
    <div>
      <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom: 24 }}>
        <button
          onClick={() => setMonthOffset(o => Math.max(0, o - 1))}
          disabled={monthOffset === 0}
          style={{ background:'none', border:`1px solid ${rc.lineDark}`, width:36, height:36, cursor: monthOffset === 0 ? 'default' : 'pointer', opacity: monthOffset === 0 ? 0.3 : 1, fontFamily: rf.serif, fontSize: 18 }}
        >‹</button>
        <div style={{ fontFamily: rf.serif, fontSize: 24, fontStyle:'italic', fontWeight: 500 }}>{monthName}</div>
        <button
          onClick={() => setMonthOffset(o => Math.min(2, o + 1))}
          style={{ background:'none', border:`1px solid ${rc.lineDark}`, width:36, height:36, cursor:'pointer', fontFamily: rf.serif, fontSize: 18 }}
        >›</button>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4, fontFamily: rf.mono, fontSize: 10, letterSpacing: 1.5, textTransform: 'uppercase', opacity: 0.5, marginBottom: 8, textAlign: 'center' }}>
        {dayHeaders.map(d => <div key={d}>{d}</div>)}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4 }}>
        {cells.map((d, i) => {
          if (!d) return <div key={i}/>;
          const iso = localISO(d);
          const past = d < today;
          const tooFar = (d - today) / (1000*60*60*24) > 30;
          const disabled = past || tooFar;
          const sel = value === iso;
          return (
            <div
              key={i}
              onClick={() => !disabled && onChange(iso)}
              style={{
                padding: window.innerWidth < 640 ? '10px 0' : '14px 0', textAlign: 'center',
                fontFamily: rf.serif, fontSize: 19, fontWeight: 500,
                background: sel ? rc.night : 'transparent',
                color: sel ? rc.bone : (disabled ? rc.night + '25' : rc.night),
                border: `1px solid ${sel ? rc.night : rc.lineDark}`,
                cursor: disabled ? 'not-allowed' : 'pointer',
                transition:'background .12s, color .12s',
              }}
              onMouseEnter={e => { if (!disabled && !sel) e.currentTarget.style.background = rc.boneDeep; }}
              onMouseLeave={e => { if (!disabled && !sel) e.currentTarget.style.background = 'transparent'; }}
            >{d.getDate()}</div>
          );
        })}
      </div>
      <div style={{ marginTop: 20, fontFamily: rf.mono, fontSize: 11, letterSpacing: 1.5, opacity: 0.55 }}>
        {t('Reservierungen bis zu 30 Tage im Voraus möglich.', 'Reservations open up to 30 days in advance.')}
      </div>
    </div>
  );
};

// ─── Step 2: Time ─────────────────────────────────────────

const StepTime = ({ date, party, value, onChange, availability, loading }) => {
  const { t } = useLang();
  const lunch = window.SITAR_HOURS.lunch.slots;
  const dinner = window.SITAR_HOURS.dinner.slots;
  const need = tablesNeeded(party || 2);

  const renderSlot = (slot) => {
    const booked = tablesBookedAt(slot, availability);
    const free = TOTAL_TABLES - booked;
    const taken = !loading && free < need;
    const sel = value === slot;
    return (
      <div
        key={slot}
        onClick={() => !taken && !loading && onChange(slot)}
        style={{
          padding:'18px 0', textAlign:'center', position:'relative',
          fontFamily: rf.serif, fontSize: 22, fontWeight: 500,
          background: sel ? rc.night : (taken ? 'transparent' : rc.boneDeep + '50'),
          color: sel ? rc.bone : (taken ? rc.night + '30' : rc.night),
          textDecoration: taken ? 'line-through' : 'none',
          border: `1px solid ${sel ? rc.night : rc.lineDark}`,
          cursor: loading ? 'wait' : (taken ? 'not-allowed' : 'pointer'),
          opacity: loading ? 0.5 : 1,
          transition: 'background .12s, color .12s, opacity .15s',
        }}
      >
        {slot}
        {!taken && !sel && !loading && (
          <div style={{ position:'absolute', bottom: 4, left: 0, right: 0, fontFamily: rf.mono, fontSize: 9, letterSpacing: 1, opacity: 0.5 }}>
            {free} {t('frei', 'free')}
          </div>
        )}
      </div>
    );
  };

  return (
    <div>
      <div style={{ fontFamily: rf.mono, fontSize: 11, letterSpacing: 2, opacity: 0.6, textTransform: 'uppercase', marginBottom: 12 }}>{t('Mittagstisch', 'Lunch')}</div>
      <div style={{ display: 'grid', gridTemplateColumns: window.innerWidth < 640 ? 'repeat(3, 1fr)' : 'repeat(5, 1fr)', gap: 8, marginBottom: 28 }}>
        {lunch.map(renderSlot)}
      </div>
      <div style={{ fontFamily: rf.mono, fontSize: 11, letterSpacing: 2, opacity: 0.6, textTransform: 'uppercase', marginBottom: 12 }}>{t('Abendessen', 'Dinner')}</div>
      <div style={{ display: 'grid', gridTemplateColumns: window.innerWidth < 640 ? 'repeat(3, 1fr)' : 'repeat(5, 1fr)', gap: 8 }}>
        {dinner.map(renderSlot)}
      </div>
      {value && (
        <div style={{ marginTop: 24, padding:'14px 16px', background: rc.night, color: rc.bone, fontFamily: rf.mono, fontSize: 11, letterSpacing: 1.5, display:'flex', alignItems:'center', gap: 10 }}>
          <span style={{ color: rc.tandoor }}>●</span>
          {value} {t('ausgewählt —', 'selected —')} {need === 1 ? t('ein Tisch', 'one table') : t('zwei Tische zusammen', 'two tables joined')} {t('für 90 Minuten reserviert', 'reserved for 90 minutes')}
        </div>
      )}
      {loading && (
        <div style={{ marginTop: 16, fontFamily: rf.mono, fontSize: 10, letterSpacing: 1.5, opacity: 0.55 }}>
          {t('Verfügbarkeit wird geladen…', 'Loading availability…')}
        </div>
      )}
    </div>
  );
};

// ─── Step 3: Party size ─────────────────────────────────────

const StepParty = ({ value, onChange, date, time, availability }) => {
  const { t } = useLang();
  const checkAvail = (p) => {
    if (!date || !time || !availability) return true;
    const need = tablesNeeded(p);
    const free = TOTAL_TABLES - tablesBookedAt(time, availability);
    return free >= need;
  };

  return (
    <div>
      <div style={{ fontFamily: rf.serif, fontSize: 22, fontStyle:'italic', opacity: 0.7, marginBottom: 28 }}>
        {t('Gruppen von 5–8 Personen werden an zwei Tischen platziert.', 'Parties of 5–8 get two tables joined together.')}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: window.innerWidth < 640 ? 'repeat(2, 1fr)' : 'repeat(4, 1fr)', gap: 10 }}>
        {[1,2,3,4,5,6,7,8].map(p => {
          const sel = value === p;
          const ok = checkAvail(p);
          return (
            <div
              key={p}
              onClick={() => ok && onChange(p)}
              style={{
                padding: window.innerWidth < 640 ? '18px 0 14px' : '28px 0 22px', textAlign: 'center',
                background: sel ? rc.night : (ok ? rc.boneDeep + '50' : 'transparent'),
                color: sel ? rc.bone : (ok ? rc.night : rc.night + '30'),
                border: `1px solid ${sel ? rc.night : rc.lineDark}`,
                cursor: ok ? 'pointer' : 'not-allowed',
                transition:'background .12s',
              }}
            >
              <div style={{ fontFamily: rf.serif, fontSize: window.innerWidth < 640 ? 32 : 44, fontWeight: 500, lineHeight: 1 }}>{p}</div>
              <div style={{ fontFamily: rf.mono, fontSize: 9, letterSpacing: 1.5, marginTop: 8, opacity: 0.7, textTransform:'uppercase' }}>
                {p === 1 ? t('Gast', 'guest') : t('Gäste', 'guests')}{p > 4 ? t(' · 2 Tische', ' · 2 tables') : ''}
              </div>
            </div>
          );
        })}
      </div>
      <div style={{ marginTop: 24, fontFamily: rf.mono, fontSize: 10, letterSpacing: 1.5, opacity: 0.55 }}>
        {t('Größere Gruppe? Schreiben Sie uns: hallo@sitar-muenchen.de', 'Larger party? Email hallo@sitar-muenchen.de')}
      </div>
    </div>
  );
};

// ─── Step 4: Details ─────────────────────────────────────

const Field = ({ label, value, onChange, type = 'text', placeholder, error }) => (
  <div style={{ marginBottom: 18 }}>
    <div style={{ fontFamily: rf.mono, fontSize: 10, letterSpacing: 2, color: error ? rc.tandoor : rc.night + 'a0', textTransform:'uppercase', marginBottom: 6 }}>
      {label}{error ? ' · ' + error : ''}
    </div>
    <input
      type={type}
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      style={{
        width:'100%', background: rc.boneSoft, border: `1px solid ${error ? rc.tandoor : rc.lineDark}`,
        padding:'14px 16px', fontFamily: rf.serif, fontSize: 19, color: rc.night,
        outline:'none', borderRadius: 0,
      }}
      onFocus={e => e.currentTarget.style.borderColor = rc.night}
      onBlur={e => e.currentTarget.style.borderColor = error ? rc.tandoor : rc.lineDark}
    />
  </div>
);

const StepDetails = ({ value, onChange, errors }) => {
  const { t } = useLang();
  return (
    <div>
      <div style={{ display: 'grid', gridTemplateColumns: window.innerWidth < 640 ? '1fr' : '1fr 1fr', gap: 16 }}>
        <Field label={t('Vorname', 'First name')} value={value.first} onChange={v => onChange({ ...value, first: v })} placeholder="Anna" error={errors.first} />
        <Field label={t('Nachname', 'Last name')} value={value.last} onChange={v => onChange({ ...value, last: v })} placeholder="Schmidt" error={errors.last} />
      </div>
      <Field label="E-Mail" type="email" value={value.email} onChange={v => onChange({ ...value, email: v })} placeholder="anna@beispiel.de" error={errors.email} />
      <Field label={t('Telefon', 'Phone')} type="tel" value={value.phone} onChange={v => onChange({ ...value, phone: v })} placeholder="+49 ···" error={errors.phone} />
      <div style={{ marginTop: 24, padding:'14px 16px', background: rc.boneDeep + '60', fontFamily: rf.mono, fontSize: 10, letterSpacing: 1.5, opacity: 0.7, lineHeight: 1.5 }}>
        {t('Wir halten Ihren Tisch 15 Minuten frei. Eine Bestätigung erhalten Sie per E-Mail.', "We hold tables for 15 minutes after your reservation time. We'll send a confirmation to your email.")}
      </div>
    </div>
  );
};

// ─── Step 5: Confirm ─────────────────────────────────────

const StepConfirm = ({ data, submitError }) => {
  const { lang, t } = useLang();
  const d = new Date(data.date);
  const need = tablesNeeded(data.party);
  return (
    <div>
      <div style={{ background: rc.night, color: rc.bone, padding: window.innerWidth < 640 ? 20 : 32, marginBottom: 24 }}>
        <div style={{ fontFamily: rf.mono, fontSize: 11, letterSpacing: 2.5, color: rc.tandoor, textTransform: 'uppercase', marginBottom: 12 }}>{t('Reservierung', 'Reservation')}</div>
        <div style={{ fontFamily: rf.serif, fontSize: window.innerWidth < 640 ? 28 : 44, fontStyle: 'italic', fontWeight: 500, lineHeight: 1.1, letterSpacing: -0.5 }}>
          {fmtDateLong(d, lang)}<br/>
          {t(`um ${data.time} Uhr`, `at ${data.time}`)}
        </div>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: window.innerWidth < 640 ? '1fr' : '1fr 1fr', gap: 0, border: `1px solid ${rc.lineDark}` }}>
        {[
          [t('Gast', 'Guest'), `${data.first} ${data.last}`],
          [t('Personen', 'Party'), `${data.party} ${data.party === 1 ? t('Person','guest') : t('Personen','guests')} · ${need === 1 ? t('1 Tisch','1 table') : t('2 Tische','2 tables joined')}`],
          ['E-Mail', data.email],
          [t('Telefon', 'Phone'), data.phone],
        ].map((row, i) => (
          window.innerWidth < 640 ? (
            <div key={i} style={{ padding: '12px 16px', borderBottom: `1px solid ${rc.lineDark}` }}>
              <div style={{ fontFamily: rf.mono, fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', opacity: 0.5, marginBottom: 4 }}>{row[0]}</div>
              <div style={{ fontFamily: rf.serif, fontSize: 16 }}>{row[1]}</div>
            </div>
          ) : (
            <React.Fragment key={i}>
              <div style={{ padding: '16px 20px', borderBottom: i < 2 ? `1px solid ${rc.lineDark}` : 'none', borderRight: `1px solid ${rc.lineDark}`, fontFamily: rf.mono, fontSize: 10, letterSpacing: 2, textTransform: 'uppercase', opacity: 0.6, background: rc.boneDeep + '40' }}>{row[0]}</div>
              <div style={{ padding: '16px 20px', borderBottom: i < 2 ? `1px solid ${rc.lineDark}` : 'none', fontFamily: rf.serif, fontSize: 18 }}>{row[1]}</div>
            </React.Fragment>
          )
        ))}
      </div>
      {submitError && (
        <div style={{ marginTop: 20, padding:'14px 16px', background: rc.tandoor, color: rc.bone, fontFamily: rf.mono, fontSize: 11, letterSpacing: 1.2, lineHeight: 1.5 }}>
          {submitError}
        </div>
      )}
      <div style={{ marginTop: 20, fontFamily: rf.mono, fontSize: 10, letterSpacing: 1.5, opacity: 0.6, lineHeight: 1.5 }}>
        {t('Mit der Bestätigung stimmen Sie unserer 15-Minuten-Haltefrist zu. Stornierungen bis 4 Stunden vorher sind kostenfrei.', 'By confirming, you agree to our 15-minute hold policy. Cancellations up to 4 hours before are free.')}
      </div>
    </div>
  );
};

// ─── Confirmation screen ─────────────────────────────────

const Confirmed = ({ data, onClose, onAnother }) => {
  const { lang, t } = useLang();
  const { mobile } = useBreakpoint();
  const d = new Date(data.date);
  const ref = data.id ? data.id.slice(-6).toUpperCase() : 'XXXXXX';
  return (
    <div style={{
      width: mobile ? '100%' : 720, maxWidth: 720,
      height: mobile ? '100%' : 'auto',
      background: rc.bone, color: rc.night,
      boxShadow: '0 40px 100px rgba(0,0,0,0.5)', fontFamily: rf.sans,
      overflowY: 'auto',
    }}>
      <div style={{ background: rc.tandoor, color: rc.bone, padding: mobile ? '28px 20px 24px' : '40px 36px 36px', position: 'relative' }}>
        <div style={{ fontFamily: rf.mono, fontSize: 11, letterSpacing: 2.5, opacity: 0.85, textTransform: 'uppercase', marginBottom: 12 }}>
          —— {t('Bestätigt', 'Confirmed')}
        </div>
        <div style={{ fontFamily: rf.serif, fontSize: mobile ? 40 : 64, fontStyle: 'italic', fontWeight: 500, lineHeight: 0.95, letterSpacing: -1.5 }}>
          {t('Wir freuen uns', "We'll see you")}<br/>{t('auf Sie!', `${fmtDate(d, lang).split('·')[1].trim()}.`)}
        </div>
        <div
          onClick={onClose}
          style={{ position:'absolute', top: 24, right: 28, fontSize: 28, cursor:'pointer', fontFamily: rf.serif, opacity: 0.8 }}
        >×</div>
      </div>
      <div style={{ padding: mobile ? 20 : 36 }}>
        <div style={{ fontFamily: rf.serif, fontSize: mobile ? 17 : 22, fontStyle: 'italic', lineHeight: 1.4, opacity: 0.85, marginBottom: 28 }}>
          {t('Bestätigung gesendet an', 'Confirmation sent to')} <strong style={{ fontStyle: 'normal' }}>{data.email}</strong>. {t('Referenz', 'Reference')} <strong style={{ fontStyle: 'normal', color: rc.tandoor }}>#{ref}</strong>.
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: mobile ? '1fr' : '1fr 1fr 1fr', gap: 0, border: `1px solid ${rc.lineDark}` }}>
          {[
            [t('Datum', 'Date'),    fmtDate(d, lang)],
            [t('Uhrzeit', 'Time'),  lang === 'de' ? data.time + ' Uhr' : data.time],
            [t('Personen', 'Party'), `${data.party} ${data.party === 1 ? t('Person','guest') : t('Personen','guests')}`],
          ].map((row, i) => (
            <div key={i} style={{ padding: mobile ? '12px 16px' : 18, borderRight: (!mobile && i < 2) ? `1px solid ${rc.lineDark}` : 'none', borderBottom: (mobile && i < 2) ? `1px solid ${rc.lineDark}` : 'none' }}>
              <div style={{ fontFamily: rf.mono, fontSize: 10, letterSpacing: 2, opacity: 0.55, textTransform:'uppercase', marginBottom: 6 }}>{row[0]}</div>
              <div style={{ fontFamily: rf.serif, fontSize: 22, fontWeight: 500 }}>{row[1]}</div>
            </div>
          ))}
        </div>
        <div style={{ marginTop: 28, padding:'18px 20px', background: rc.boneDeep + '60', fontFamily: rf.serif, fontSize: 17, fontStyle:'italic', lineHeight: 1.4 }}>
          Sitar · Robert-Koch-Straße 4 · 80538 München · Lehel<br/>
          {t('U-Bahn Lehel (U4 / U5) · 2 Min. Fußweg', 'U-Bahn Lehel (U4 / U5) · 2 min walk')}
        </div>
      </div>
      <div style={{ padding: mobile ? '14px 20px' : '18px 36px', display: 'flex', justifyContent: 'space-between', borderTop: `1px solid ${rc.lineDark}`, background: rc.boneDeep + '40' }}>
        <button
          onClick={onAnother}
          style={{ background: 'none', border: 'none', fontFamily: rf.sans, fontSize: 12, letterSpacing: 1.5, textTransform: 'uppercase', cursor: 'pointer', color: rc.night, opacity: 0.7 }}
        >{t('+ Weitere Reservierung', '+ Another reservation')}</button>
        <button
          onClick={onClose}
          style={{ background: rc.night, color: rc.bone, border: 'none', padding: '14px 28px', fontFamily: rf.sans, fontSize: 12, fontWeight: 600, letterSpacing: 2, textTransform: 'uppercase', cursor: 'pointer' }}
        >{t('Fertig', 'Done')}</button>
      </div>
    </div>
  );
};

// ─── Wizard root ─────────────────────────────────────────

const ReservationWizard = ({ onClose }) => {
  const { lang, t } = useLang();
  const [step, setStep] = React.useState(1);
  const [data, setData] = React.useState({
    date: '', time: '', party: 0,
    first: '', last: '', email: '', phone: '',
  });
  const [errors, setErrors] = React.useState({});
  const [confirmed, setConfirmed] = React.useState(null);

  // availability for the currently picked date — { '12:00': 7, ... } or null while loading
  const [availability, setAvailability] = React.useState(null);
  const [availLoading, setAvailLoading] = React.useState(false);

  // submission state
  const [submitting, setSubmitting] = React.useState(false);
  const [submitError, setSubmitError] = React.useState('');

  const setField = (k, v) => setData(d => ({ ...d, [k]: v }));

  // Fetch availability whenever the date changes (or after a successful booking).
  // Tracks the latest request via a ref so a stale slow response can't overwrite
  // a fresh one if the user changes the date quickly.
  const reqRef = React.useRef(0);
  const fetchAvailability = React.useCallback(async (date) => {
    if (!date) { setAvailability(null); return; }
    const myReq = ++reqRef.current;
    setAvailLoading(true);
    try {
      const res = await fetch(`${API_BASE}/api/availability?date=${encodeURIComponent(date)}`);
      if (!res.ok) throw new Error('availability request failed');
      const json = await res.json();
      if (myReq === reqRef.current) {
        setAvailability(json.slots || {});
      }
    } catch (e) {
      console.error('availability fetch failed', e);
      if (myReq === reqRef.current) {
        // Fail open: empty map means everything looks free. Server will reject
        // any actual booking that violates capacity, so nothing is overbooked.
        setAvailability({});
      }
    } finally {
      if (myReq === reqRef.current) setAvailLoading(false);
    }
  }, []);

  React.useEffect(() => { fetchAvailability(data.date); }, [data.date, fetchAvailability]);

  // Re-clear time if party size makes it invalid given current availability
  React.useEffect(() => {
    if (data.time && data.date && data.party && availability) {
      const free = TOTAL_TABLES - tablesBookedAt(data.time, availability);
      if (free < tablesNeeded(data.party)) setField('time', '');
    }
  }, [data.party, availability]);

  const stepValid = {
    1: !!data.date,
    2: !!data.time,
    3: data.party >= 1 && data.party <= 8,
    4: ['first','last','email','phone'].every(k => data[k].trim()) && /\S+@\S+\.\S+/.test(data.email),
    5: !submitting,
  };

  const validateDetails = () => {
    const e = {};
    if (!data.first.trim()) e.first = t('Pflichtfeld', 'required');
    if (!data.last.trim())  e.last  = t('Pflichtfeld', 'required');
    if (!data.email.trim()) e.email = t('Pflichtfeld', 'required');
    else if (!/\S+@\S+\.\S+/.test(data.email)) e.email = t('ungültig', 'invalid');
    if (!data.phone.trim()) e.phone = t('Pflichtfeld', 'required');
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const submitReservation = async () => {
    setSubmitting(true);
    setSubmitError('');
    try {
      const res = await fetch(`${API_BASE}/api/reservations`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok) {
        if (res.status === 409) {
          setSubmitError(json.message || t('Diese Uhrzeit ist leider ausgebucht. Bitte wählen Sie einen anderen Zeitslot.', 'That time just filled up. Please go back and pick another slot.'));
          fetchAvailability(data.date);
        } else if (res.status === 400 && json.fields) {
          const firstField = Object.keys(json.fields)[0];
          setSubmitError(t(`Bitte prüfen Sie: ${firstField}`, `Please check your ${firstField}.`));
        } else if (res.status === 429) {
          setSubmitError(t('Zu viele Versuche. Bitte versuchen Sie es in Kürze erneut.', 'Too many attempts. Please try again in a little while.'));
        } else {
          setSubmitError(json.message || t('Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut.', 'Something went wrong. Please try again.'));
        }
        return;
      }
      setConfirmed(json);
    } catch (e) {
      console.error('reservation submit failed', e);
      setSubmitError(t('Netzwerkfehler — bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut.', 'Network problem — please check your connection and try again.'));
    } finally {
      setSubmitting(false);
    }
  };

  const handleNext = () => {
    if (step === 4 && !validateDetails()) return;
    if (step < 5) { setStep(step + 1); return; }
    submitReservation();
  };

  const handleAnother = () => {
    setConfirmed(null);
    setStep(1);
    setData({ date:'', time:'', party: 0, first:'', last:'', email:'', phone:'' });
    setErrors({});
    setSubmitError('');
    setAvailability(null);
  };

  const summary = [];
  if (data.date && step >= 2) summary.push(fmtDate(new Date(data.date), lang));
  if (data.time && step >= 3) summary.push(lang === 'de' ? data.time + ' Uhr' : data.time);
  if (data.party && step >= 4) summary.push(`${data.party} ${data.party === 1 ? t('Person','guest') : t('Personen','guests')}`);

  const titles = {
    1: t('Wann möchten Sie kommen?',   'When would you like to come?'),
    2: t('Wählen Sie Ihre Uhrzeit',    'Choose your time'),
    3: t('Wie viele Personen?',        'How many of you?'),
    4: t('Noch ein paar Angaben',      'Just a few details'),
    5: t('Überprüfen & bestätigen',    'Review & confirm'),
  };

  const { mobile } = useBreakpoint();

  return (
    <div style={{
      position: 'fixed', inset: 0, background: mobile ? 'rgba(7,32,32,0.95)' : 'rgba(7,32,32,0.78)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      zIndex: 100, padding: mobile ? 0 : 20, animation: 'sitarFadeIn .25s ease-out',
    }}
      onClick={(e) => { if (e.target === e.currentTarget && !submitting) onClose(); }}
    >
      {confirmed ? (
        <Confirmed data={confirmed} onClose={onClose} onAnother={handleAnother} />
      ) : (
        <ModalShell
          step={step}
          title={titles[step]}
          summary={summary.length ? summary : null}
          onClose={onClose}
          onBack={step > 1 && !submitting ? () => setStep(step - 1) : null}
          onNext={handleNext}
          nextDisabled={!stepValid[step]}
          nextLabel={step === 5 ? (submitting ? t('Wird gesendet…','Sending…') : t('Reservierung bestätigen ✓','Confirm reservation ✓')) : t('Weiter →','Continue →')}
        >
          {step === 1 && <StepDate value={data.date} onChange={v => setField('date', v)} />}
          {step === 2 && <StepTime date={data.date} party={data.party || 2} value={data.time} onChange={v => setField('time', v)} availability={availability} loading={availLoading} />}
          {step === 3 && <StepParty value={data.party} onChange={v => setField('party', v)} date={data.date} time={data.time} availability={availability} />}
          {step === 4 && <StepDetails value={data} onChange={d => setData(d)} errors={errors} />}
          {step === 5 && <StepConfirm data={data} submitError={submitError} />}
        </ModalShell>
      )}
    </div>
  );
};

Object.assign(window, { ReservationWizard });
