/* Public booking widget — booking.ooniq.app/{slug}
   Lives outside <AuthGate>. Reads the public tenant entry to figure out
   which Firestore tenant to write into. Steps: pax → date → time →
   details → policy → confirm. */

const { useState: bS, useEffect: bE, useMemo: bM } = React;

function PublicBookingApp() {
  const fb = window.fb;
  const slug = decodeURIComponent(window.location.pathname.replace(/^\/+|\/+$/g, "").split("/")[0] || "");
  const [phase, setPhase] = bS("loading"); // loading | notfound | disabled | ready
  const [tenant, setTenant] = bS(null);
  const [step, setStep] = bS(0); // 0:pax 1:date 2:time 3:details 4:policy 5:done

  const [pax, setPax] = bS(null);
  const [date, setDate] = bS(null);
  const [time, setTime] = bS(null);
  const [details, setDetails] = bS({ first: '', last: '', email: '', phone: '', company: '', notes: '', marketingConsent: false, privacyAccepted: false });
  const [submitting, setSubmitting] = bS(false);
  const [error, setError] = bS('');
  const [confirmation, setConfirmation] = bS(null);

  bE(() => {
    document.documentElement.dataset.theme = "light";
  }, []);

  bE(() => {
    (async () => {
      try {
        // 1. Custom domain takes precedence — if booking.cafestrand.dk
        //    maps to a tenant, we resolve via /domainMappings and don't
        //    care what's in the URL path.
        const host = (window.location.hostname || '').toLowerCase();
        if (host && !host.startsWith('booking.ooniq.') && !host.startsWith('seatiq.ooniq.') && host !== 'localhost' && !host.endsWith('.web.app') && !host.endsWith('.firebaseapp.com')) {
          const dSnap = await fb.getDoc(fb.doc(fb.db, "domainMappings", host));
          if (dSnap.exists()) {
            const map = dSnap.data();
            // Find the tenant's slug and load its public doc
            const tSnap = await fb.getDoc(fb.doc(fb.db, "tenants", map.tenantId));
            if (tSnap.exists()) {
              const t = tSnap.data();
              if (t.slug) {
                const pSnap = await fb.getDoc(fb.doc(fb.db, "publicTenants", t.slug));
                if (pSnap.exists()) {
                  const pub = pSnap.data();
                  setTenant(pub);
                  setPhase(pub.enabled ? "ready" : "disabled");
                  return;
                }
              }
            }
          }
        }
        // 2. Fallback: standard /{slug} routing on booking.ooniq.app
        if (!slug) { setPhase("notfound"); return; }
        const pSnap = await fb.getDoc(fb.doc(fb.db, "publicTenants", slug));
        if (!pSnap.exists()) { setPhase("notfound"); return; }
        const pub = pSnap.data();
        if (!pub.enabled) { setPhase("disabled"); setTenant(pub); return; }
        setTenant(pub);
        setPhase("ready");
      } catch (e) {
        console.error(e);
        setPhase("notfound");
      }
    })();
  }, [slug]);

  if (phase === "loading") {
    return (
      <div className="pb-host">
        <div className="pb-loading"><div className="auth-spinner"/></div>
      </div>
    );
  }
  if (phase === "notfound") return <NotFoundScreen slug={slug}/>;
  if (phase === "disabled") return <DisabledScreen tenant={tenant}/>;

  const tenantId = tenant.tenantId;
  const total = 5;
  const progress = Math.min(1, (step) / total);

  const goBack = () => {
    if (step === 0) return;
    setStep(step - 1);
  };

  const submit = async () => {
    setSubmitting(true);
    setError('');
    try {
      const start = time;
      const end = time + (tenant.defaultDurationMin || 105);
      const id = 'rOL' + Math.random().toString(36).slice(2, 8);
      const fullName = [details.first, details.last].filter(Boolean).join(' ').trim() || 'Online gæst';
      // Pick a candidate table by capacity — staff can reassign later.
      const reservation = {
        id,
        name: fullName,
        phone: details.phone || '',
        email: details.email || '',
        pax: Number(pax),
        table: tenant.fallbackTableId || '',
        start, end,
        status: 'confirmed',
        notes: details.notes || '',
        tags: ['Online'],
        deposit: 0,
        source: 'Online',
        created: new Date().toISOString(),
        allergies: [],
        company: details.company || '',
        marketingConsent: !!details.marketingConsent,
        privacyAccepted: !!details.privacyAccepted,
      };
      await fb.setDoc(fb.doc(fb.db, "tenants", tenantId, "reservations", id), reservation);
      // Bump tenant lastActivityAt so it shows up in admin activity log.
      fb.setDoc(fb.doc(fb.db, "tenants", tenantId), {
        lastActivityAt: fb.serverTimestamp(),
      }, { merge: true }).catch(() => {});
      setConfirmation({ id, start, end, pax, name: fullName, email: details.email });
      setStep(5);
    } catch (e) {
      console.error(e);
      setError(e.message || 'Kunne ikke gemme reservationen — prøv igen.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="pb-host">
      <header className="pb-header">
        <button className="pb-back" onClick={() => step === 0 ? null : goBack()} aria-label="Tilbage">
          {step > 0 && step < 5 && <Icon name="chev-left" size={20}/>}
        </button>
        <div className="pb-title">{(tenant.name || tenant.tenantId || '').toUpperCase()}</div>
        <div className="pb-lang">DA</div>
      </header>
      <div className="pb-progress">
        <div className="pb-progress-fill" style={{width: `${(step >= 5 ? 1 : progress) * 100}%`}}/>
      </div>

      <main className="pb-main">
        {step === 0 && <StepPax pax={pax} setPax={setPax} onNext={() => setStep(1)}/>}
        {step === 1 && <StepDate value={date} tenant={tenant} onChange={(d) => { setDate(d); setStep(2); }}/>}
        {step === 2 && <StepTime date={date} pax={pax} tenant={tenant}
          value={time} onChange={(t) => { setTime(t); setStep(3); }}/>}
        {step === 3 && <StepDetails details={details} setDetails={setDetails}
          onNext={() => setStep(4)}/>}
        {step === 4 && <StepPolicy tenant={tenant} onAccept={submit} busy={submitting} error={error}/>}
        {step === 5 && confirmation && <StepDone tenant={tenant} confirmation={confirmation} date={date}/>}
      </main>
    </div>
  );
}

// ============= STEPS =============

function StepPax({ pax, setPax, onNext }) {
  return (
    <div className="pb-step">
      <h2 className="pb-step-title">Vælg antal gæster</h2>
      <div className="pb-pax-grid">
        {[1,2,3,4,5,6,7,8].map(n => (
          <button key={n}
            className={`pb-pax-cell ${pax === n ? 'active' : ''}`}
            onClick={() => { setPax(n); onNext(); }}>{n}</button>
        ))}
      </div>
      <div className="pb-help">
        Selskaber over 8<br/>
        <a href="#" onClick={e => e.preventDefault()}>Kontakt os her</a>
      </div>
    </div>
  );
}

// Maps JS Date.getDay() (Sun=0) to our weekday keys
const DAY_KEYS = ['sun','mon','tue','wed','thu','fri','sat'];
function isDayClosed(date, openingHours) {
  if (!openingHours) return false;
  const key = DAY_KEYS[date.getDay()];
  const row = openingHours[key];
  return row && row.open === false;
}

function StepDate({ value, onChange, tenant }) {
  const today = new Date(); today.setHours(0,0,0,0);
  const [month, setMonth] = bS(() => {
    const d = value ? new Date(value) : today;
    return new Date(d.getFullYear(), d.getMonth(), 1);
  });

  const year = month.getFullYear();
  const mo = month.getMonth();
  const first = new Date(year, mo, 1);
  const dayOffset = (first.getDay() + 6) % 7; // Monday=0
  const daysInMonth = new Date(year, mo + 1, 0).getDate();
  const cells = [];
  for (let i = 0; i < dayOffset; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(year, mo, d));

  const shift = (n) => setMonth(new Date(year, mo + n, 1));
  const monthName = new Intl.DateTimeFormat('da-DK', { month: 'long', year: 'numeric' }).format(month).toUpperCase();

  return (
    <div className="pb-step">
      <h2 className="pb-step-title pb-step-title-center">Vælg dato</h2>
      <div className="pb-cal-divider"/>
      <div className="pb-cal-nav">
        <button onClick={() => shift(-1)} aria-label="Forrige måned"><Icon name="chev-left" size={18}/></button>
        <span>{monthName}</span>
        <button onClick={() => shift(1)} aria-label="Næste måned"><Icon name="chev-right" size={18}/></button>
      </div>
      <div className="pb-cal-headers">
        {['MAN','TIR','ONS','TOR','FRE','LØR','SØN'].map(d => <div key={d}>{d}</div>)}
      </div>
      <div className="pb-cal-grid">
        {cells.map((d, i) => {
          if (!d) return <div key={i} className="pb-cal-empty"/>;
          const past = d.getTime() < today.getTime();
          const closed = isDayClosed(d, tenant?.openingHours);
          const disabled = past || closed;
          const selected = value && d.getTime() === new Date(value).setHours(0,0,0,0);
          return (
            <button key={i}
              disabled={disabled}
              title={closed ? 'Lukket' : undefined}
              className={`pb-cal-cell ${disabled ? 'past' : ''} ${selected ? 'selected' : ''}`}
              onClick={() => onChange(d.getTime())}>
              {String(d.getDate()).padStart(2,'0')}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function StepTime({ date, pax, tenant, value, onChange }) {
  // Derive open/close window from the tenant's openingHours for the
  // selected weekday. lastBookingOffsetMin trims the close time so
  // guests always have time to be seated and served.
  const dayKey = DAY_KEYS[new Date(date).getDay()];
  const hours = tenant?.openingHours?.[dayKey];
  const offset = Number(tenant?.lastBookingOffsetMin ?? 60);

  const isClosedToday = !hours || hours.open === false;
  const windowStart = hours?.o ?? (14*60);
  const windowEnd = (hours?.c ?? (21*60)) - offset;

  const slots = bM(() => {
    if (isClosedToday || windowEnd < windowStart) return [];
    const out = [];
    for (let m = windowStart; m <= windowEnd; m += 15) out.push(m);
    return out;
  }, [windowStart, windowEnd, isClosedToday]);

  const dateLabel = new Intl.DateTimeFormat('da-DK', { month: 'long', year: 'numeric' }).format(new Date(date));
  const weekday = new Intl.DateTimeFormat('da-DK', { weekday: 'short', day: 'numeric' }).format(new Date(date));

  return (
    <div className="pb-step pb-time-step">
      <div className="pb-time-header">
        <div className="pb-time-date">{dateLabel.toUpperCase()}</div>
        <div className="pb-time-weekday">{weekday}</div>
      </div>

      <div className="pb-area-label">Restaurant</div>

      {isClosedToday ? (
        <div className="pb-empty-slot">
          Lukket denne dag — vælg en anden dato.
        </div>
      ) : slots.length === 0 ? (
        <div className="pb-empty-slot">
          Ingen ledige tider på denne dag.
        </div>
      ) : (
        <div className="pb-time-grid">
          {slots.map(m => {
            const lbl = `${String(Math.floor(m/60)).padStart(2,'0')}:${String(m%60).padStart(2,'0')}`;
            return (
              <button key={m}
                className={`pb-time-cell ${value === m ? 'active' : ''}`}
                onClick={() => onChange(m)}>{lbl}</button>
            );
          })}
        </div>
      )}
    </div>
  );
}

function StepDetails({ details, setDetails, onNext }) {
  const can = details.first && details.last && details.email && details.phone && details.privacyAccepted;
  return (
    <div className="pb-step">
      <h2 className="pb-step-title pb-step-title-center">Indtast dine oplysninger</h2>

      <div className="pb-form">
        <Field label="Fornavn" value={details.first} onChange={v => setDetails({...details, first: v})}/>
        <Field label="Efternavn" value={details.last} onChange={v => setDetails({...details, last: v})}/>
        <Field label="Email" type="email" value={details.email} onChange={v => setDetails({...details, email: v})}/>
        <Field label="Mobil" type="tel" value={details.phone} onChange={v => setDetails({...details, phone: v})}
          prefix="+45"/>
        <Field label="Virksomhed — valgfrit" value={details.company} onChange={v => setDetails({...details, company: v})}/>
        <Field label="Noter — valgfrit" value={details.notes} onChange={v => setDetails({...details, notes: v})}
          multiline/>
      </div>

      <div className="pb-consents">
        <Consent
          checked={details.marketingConsent}
          onChange={v => setDetails({...details, marketingConsent: v})}
          label="Jeg vil gerne modtage tilbud og nyheder via email."/>
        <Consent
          checked={details.privacyAccepted}
          onChange={v => setDetails({...details, privacyAccepted: v})}
          required
          label={<>Jeg accepterer <a href="/privatlivspolitik" target="_blank" rel="noopener noreferrer">privatlivspolitikken</a>.</>}/>
      </div>

      <button className="pb-cta" disabled={!can} onClick={onNext}>Fortsæt</button>

      <p className="pb-fine">
        Hvis du booker på vegne af en anden gæst, så indtast deres oplysninger ovenfor. Vi bruger informationen til at klargøre gæstelisten.
      </p>
    </div>
  );
}

function Consent({ checked, onChange, label, required }) {
  return (
    <label className="pb-consent">
      <input type="checkbox" checked={checked} onChange={e => onChange(e.target.checked)}/>
      <span className="pb-consent-box" aria-hidden="true">
        {checked && <Icon name="check" size={14} stroke={3}/>}
      </span>
      <span className="pb-consent-text">
        {label}
        {required && <span className="pb-required"> *</span>}
      </span>
    </label>
  );
}

function Field({ label, value, onChange, type='text', prefix, multiline }) {
  return (
    <div className="pb-field">
      <label>{label}</label>
      <div className={`pb-input-wrap ${prefix ? 'has-prefix' : ''}`}>
        {prefix && <span className="pb-prefix">🇩🇰 {prefix}</span>}
        {multiline ? (
          <textarea value={value} onChange={e => onChange(e.target.value)} rows={2}/>
        ) : (
          <input type={type} value={value} onChange={e => onChange(e.target.value)}/>
        )}
      </div>
    </div>
  );
}

function StepPolicy({ tenant, onAccept, busy, error }) {
  return (
    <div className="pb-step">
      <h2 className="pb-step-title">Reservations-betingelser</h2>
      <div className="pb-policy-box">
        <p>{tenant.policy || 'Reservationen er bindende. Ved afbud senere end 24 timer før ankomst kan der opkræves et gebyr svarende til kuvertprisen. Vi holder bordet i 15 minutter efter aftalt tid.'}</p>
        <p>Ved at acceptere giver du samtykke til at vi sender dig en bekræftelse og en påmindelse via email eller SMS.</p>
      </div>
      {error && <div className="auth-error">{error}</div>}
      <button className="pb-cta" onClick={onAccept} disabled={busy}>
        {busy ? 'Bekræfter…' : 'Accepter & bekræft'}
      </button>
    </div>
  );
}

function StepDone({ tenant, confirmation, date }) {
  const time = `${String(Math.floor(confirmation.start/60)).padStart(2,'0')}:${String(confirmation.start%60).padStart(2,'0')}`;
  const dateLabel = new Intl.DateTimeFormat('da-DK', { weekday: 'long', day: 'numeric', month: 'long' }).format(new Date(date));
  return (
    <div className="pb-step pb-done">
      <div className="pb-done-tick">
        <Icon name="check" size={40} stroke={3}/>
      </div>
      <h2 className="pb-done-title">VI GLÆDER OS</h2>
      <p className="pb-done-sub">Din reservation hos {tenant.name} er bekræftet.</p>
      <div className="pb-done-card">
        <div className="pb-done-row"><span>Hvornår</span><strong>{dateLabel} · {time}</strong></div>
        <div className="pb-done-row"><span>Antal</span><strong>{confirmation.pax} pers</strong></div>
        <div className="pb-done-row"><span>Reference</span><strong style={{fontFamily: 'var(--mono)'}}>{confirmation.id}</strong></div>
      </div>
      <p className="pb-fine">En bekræftelse er sendt til {confirmation.email || 'din email'}.</p>
    </div>
  );
}

function NotFoundScreen({ slug }) {
  return (
    <div className="pb-host">
      <div className="pb-empty">
        <h2>Restauranten kunne ikke findes</h2>
        <p>Vi kender ikke en restaurant ved navn „{slug || '?'}“.</p>
        <p className="pb-fine">Tjek linket fra restauranten — eller kontakt dem direkte.</p>
      </div>
    </div>
  );
}

function DisabledScreen({ tenant }) {
  return (
    <div className="pb-host">
      <div className="pb-empty">
        <h2>{(tenant?.name || 'Restauranten').toUpperCase()}</h2>
        <p>Online booking er midlertidigt lukket for denne restaurant.</p>
        <p className="pb-fine">Prøv at ringe direkte for at høre om der er ledige tider.</p>
      </div>
    </div>
  );
}

window.PublicBookingApp = PublicBookingApp;
