// MLuppens Website — Private Client Gallery
//
// Renders /<slug> for each couple. Visits without a valid session cookie show
// a password prompt; correct password → HttpOnly cookie → photo grid + lightbox.
//
// Backend contract:
//   GET  /api/galleries/<slug>          → 200 {gallery, photos[]} | 401 (needs auth) | 404
//   POST /api/auth/<slug> {password}    → 200 (sets cookie)        | 401 | 429 (rate-limited)
//   GET  /api/galleries/<slug>/download/<photoId>  → file with Content-Disposition
//   (zip-all endpoint deferred to Phase 2 — needs a depless ZIP writer)
//
// Auth state machine:
//   loading  → checking the cookie via GET
//   locked   → cookie invalid / missing; show password prompt
//   ready    → photos rendered
//   missing  → slug doesn't exist (404)
//   error    → network or unexpected server error

function ClientGalleryScreen({ slug, go }) {
  const t = useT();
  const lang = useLang();

  const [phase, setPhase] = React.useState('loading'); // loading|locked|ready|missing|error
  const [data, setData] = React.useState(null);        // {gallery, photos[]}
  const [password, setPassword] = React.useState('');
  const [authError, setAuthError] = React.useState('');
  const [submitting, setSubmitting] = React.useState(false);
  const [lightboxIdx, setLightboxIdx] = React.useState(null);

  // Initial probe — do we already have a valid cookie?
  React.useEffect(() => {
    if (!slug) { setPhase('missing'); return; }
    let cancelled = false;
    fetch(`/api/galleries/${encodeURIComponent(slug)}`, { credentials: 'include' })
      .then(async (res) => {
        if (cancelled) return;
        if (res.status === 200) {
          const body = await res.json();
          setData(body);
          setPhase('ready');
        } else if (res.status === 401) {
          setPhase('locked');
        } else if (res.status === 404) {
          setPhase('missing');
        } else {
          setPhase('error');
        }
      })
      .catch(() => { if (!cancelled) setPhase('error'); });
    return () => { cancelled = true; };
  }, [slug]);

  const onSubmit = async (e) => {
    e.preventDefault();
    if (!password.trim()) return;
    setSubmitting(true);
    setAuthError('');
    try {
      const res = await fetch(`/api/auth/${encodeURIComponent(slug)}`, {
        method: 'POST',
        credentials: 'include',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ password: password.trim() }),
      });
      if (res.status === 200) {
        // cookie set — refetch the gallery
        const gres = await fetch(`/api/galleries/${encodeURIComponent(slug)}`, { credentials: 'include' });
        if (gres.status === 200) {
          setData(await gres.json());
          setPhase('ready');
          setPassword('');
        } else {
          setPhase('error');
        }
      } else if (res.status === 429) {
        setAuthError(t(
          'Too many attempts. Please wait 15 minutes and try again.',
          'Te veel pogingen. Wacht 15 minuten en probeer opnieuw.'
        ));
      } else {
        setAuthError(t(
          "The password doesn't match. Please try again or write me a quick note.",
          'Het wachtwoord klopt niet. Probeer het opnieuw of stuur me een kort bericht.'
        ));
      }
    } catch (_err) {
      setAuthError(t(
        "Couldn't reach the server. Please try again.",
        'Geen verbinding met de server. Probeer het opnieuw.'
      ));
    } finally {
      setSubmitting(false);
    }
  };

  // Keyboard nav in the lightbox
  React.useEffect(() => {
    function onKey(e) {
      if (lightboxIdx === null || !data) return;
      if (e.key === 'Escape')    setLightboxIdx(null);
      if (e.key === 'ArrowRight') setLightboxIdx((i) => Math.min(i + 1, data.photos.length - 1));
      if (e.key === 'ArrowLeft')  setLightboxIdx((i) => Math.max(i - 1, 0));
    }
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [lightboxIdx, data]);

  // ── LOADING ─────────────────────────────────────────────
  if (phase === 'loading') {
    return (
      <section style={{ minHeight: '70vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <div className="small" style={{ color: 'var(--ink-mute)', fontStyle: 'italic' }}>
          {t('Opening your album…', 'Album openen…')}
        </div>
      </section>
    );
  }

  // ── 404 — slug doesn't exist ────────────────────────────
  if (phase === 'missing') {
    return (
      <section style={{ minHeight: '70vh', display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: '120px 40px' }}>
        <div style={{ maxWidth: 480 }}>
          <Eyebrow>{t('Private album', 'Privé-album')}</Eyebrow>
          <h1 className="display" style={{ marginTop: 24, marginBottom: 24, fontSize: 'clamp(40px, 5.5vw, 76px)' }}>{t('Not here.', 'Niet hier.')}</h1>
          <Rule className="center" />
          <p className="body" style={{ color: 'var(--ink-soft)', marginTop: 28, marginBottom: 44, fontWeight: 300 }}>
            {t(
              "This album doesn't exist — or your private link may have expired. If I sent you here, please write back and I'll send you a fresh one.",
              "Dit album bestaat niet — of jullie privélink is verlopen. Als ik jullie hier heen stuurde, schrijf me terug en ik stuur een nieuwe."
            )}
          </p>
          <button className="btn" onClick={() => go('home')}>{t('Back home', 'Terug naar home')}</button>
        </div>
      </section>
    );
  }

  // ── ERROR ───────────────────────────────────────────────
  if (phase === 'error') {
    return (
      <section style={{ minHeight: '70vh', display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: '120px 40px' }}>
        <div style={{ maxWidth: 480 }}>
          <p className="body" style={{ color: 'var(--velvet)', fontStyle: 'italic' }}>
            {t(
              "Something went wrong reaching the album. Please refresh, or send me a quick note.",
              "Er ging iets mis bij het openen van het album. Vernieuw de pagina, of stuur me een kort bericht."
            )}
          </p>
          <p className="small" style={{ marginTop: 24 }}>
            <a href="mailto:mluppensfotografie@gmail.com" style={{ color: 'var(--ink)', borderBottom: '1px solid var(--hair)' }}>mluppensfotografie@gmail.com</a>
          </p>
        </div>
      </section>
    );
  }

  // ── LOCKED — password prompt ────────────────────────────
  if (phase === 'locked') {
    return (
      <section style={{ minHeight: '88vh', display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '120px 40px 80px', position: 'relative', overflow: 'hidden' }}>
        <div style={{
          position: 'absolute', inset: 0,
          backgroundImage: `url(assets/photos/portfolio/4U4A1551n.jpg)`,
          backgroundSize: 'cover', backgroundPosition: 'center 20%',
          opacity: 0.18,
        }}></div>
        <div style={{ position: 'relative', maxWidth: 480, width: '100%', textAlign: 'center' }}>
          <Eyebrow>{t('Private album', 'Privé-album')}</Eyebrow>
          <h1 className="display" style={{ marginTop: 24, marginBottom: 24, fontSize: 'clamp(40px, 5.5vw, 76px)', letterSpacing: '-0.015em' }}>
            {t(<>A private<br/>door.</>, <>Een privé-<br/>deur.</>)}
          </h1>
          <Rule className="center" />
          <p className="body" style={{ color: 'var(--ink-soft)', marginTop: 28, marginBottom: 44, fontWeight: 300 }}>
            {t(
              'Enter the password from the email I sent you. The album stays private to you, your family, and anyone you choose to share it with.',
              'Gebruik het wachtwoord uit de e-mail die ik jullie stuurde. Het album blijft privé voor jullie, jullie familie en iedereen die jullie ervoor uitnodigen.'
            )}
          </p>

          <form onSubmit={onSubmit} style={{ textAlign: 'left' }}>
            <FormField
              label={t('Password', 'Wachtwoord')}
              type="password"
              placeholder=""
              value={password}
              onChange={(e) => setPassword(e.target.value)}
            />
            {authError && (
              <div style={{
                marginTop: 8, marginBottom: 8, padding: '12px 14px',
                background: 'rgba(92, 34, 48, 0.08)',
                fontFamily: 'var(--font-body)', fontSize: 13, color: 'var(--velvet)',
                fontStyle: 'italic',
              }}>{authError}</div>
            )}
            <div style={{ marginTop: 28 }}>
              <button type="submit" className="btn" disabled={submitting} style={{ width: '100%', justifyContent: 'center' }}>
                {submitting ? t('Opening…', 'Openen…') : t('Open Album', 'Open album')}
              </button>
            </div>
          </form>

          <p className="small" style={{ marginTop: 36, fontStyle: 'italic', color: 'var(--ink-mute)' }}>
            {t('Lost your details? Send me a quick note at', 'Gegevens kwijt? Stuur me een bericht via')} <a href="mailto:mluppensfotografie@gmail.com" style={{ color: 'var(--ink)', borderBottom: '1px solid var(--hair)', textDecoration: 'none' }}>mluppensfotografie@gmail.com</a>.
          </p>
        </div>
      </section>
    );
  }

  // ── READY — unlocked gallery view ───────────────────────
  const { gallery, photos } = data;
  const eventDate = gallery.event_date || '';
  const location  = gallery.location || '';
  const coverUrl  = (gallery.cover_url) || (photos[0] && photos[0].full_url);
  const coverPos  = gallery.cover_pos || 'center';

  return (
    <>
      {/* Cover */}
      <section style={{ position: 'relative', minHeight: '76vh', overflow: 'hidden', display: 'flex', alignItems: 'flex-end' }}>
        {coverUrl && (
          <div style={{
            position: 'absolute', inset: 0,
            backgroundImage: `url(${coverUrl})`,
            backgroundSize: 'cover', backgroundPosition: coverPos,
          }}></div>
        )}
        <div style={{
          position: 'absolute', inset: 0,
          background: 'linear-gradient(to bottom, rgba(26,24,22,.2) 0%, rgba(26,24,22,0) 40%, rgba(26,24,22,.7) 100%)',
        }}></div>
        <div style={{ position: 'relative', zIndex: 1, padding: '80px 40px', color: 'var(--linen)', maxWidth: 'var(--max-w)', margin: '0 auto', width: '100%' }}>
          <div style={{ fontFamily: 'var(--font-body)', fontSize: 11, letterSpacing: '0.42em', textTransform: 'uppercase', opacity: 0.85, marginBottom: 20 }}>{t('Private album', 'Privé-album')}</div>
          <h1 style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontWeight: 300, fontSize: 'clamp(48px, 8vw, 128px)', lineHeight: 0.96, letterSpacing: '-0.02em', margin: 0, color: 'var(--linen)' }}>
            {gallery.display_name}
          </h1>
          {(eventDate || location) && (
            <div style={{ marginTop: 24, display: 'flex', gap: 32, alignItems: 'baseline', flexWrap: 'wrap' }}>
              {eventDate && <span style={{ fontFamily: 'var(--font-body)', fontSize: 12, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'rgba(242,237,229,.85)' }}>{eventDate}</span>}
              {location && <span style={{ fontFamily: 'var(--font-body)', fontSize: 12, letterSpacing: '0.22em', textTransform: 'uppercase', color: 'rgba(242,237,229,.85)' }}>{eventDate ? '· ' : ''}{location}</span>}
            </div>
          )}
        </div>
      </section>

      {/* Note */}
      <section className="section">
        <div className="container narrow" style={{ textAlign: 'center' }}>
          {gallery.note && (
            <p style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontWeight: 300, fontSize: 'clamp(22px, 2.4vw, 30px)', lineHeight: 1.5, color: 'var(--ink)', margin: 0 }}>
              "{gallery.note}"
            </p>
          )}
          <Rule className="center" />
          <p className="small" style={{ marginTop: 14, fontStyle: 'italic', color: 'var(--ink-mute)' }}>
            {t(`${photos.length} photos · click any image to view full size, then Download to save`, `${photos.length} foto’s · klik op een beeld voor volledig formaat en download het via de knop`)}
          </p>
        </div>
      </section>

      {/* Gallery grid — mixed aspect editorial.
          Layout (col-spans + wide-tile cadence) lives in styles.css under
          .client-gallery-grid so it can collapse responsively. */}
      <section style={{ padding: '0 40px 96px' }}>
        <div className="container">
          <div className="client-gallery-grid">
            {photos.map((p, i) => {
              const isWide = i % 4 === 0;
              const aspect = isWide ? '21/9' : '3/4';
              return (
                <div
                  key={p.id}
                  style={{ aspectRatio: aspect, cursor: 'pointer', overflow: 'hidden', background: 'var(--ink)' }}
                  onClick={() => setLightboxIdx(i)}
                >
                  <div style={{
                    width: '100%', height: '100%',
                    backgroundImage: `url(${p.thumb_url || p.full_url})`,
                    backgroundSize: 'cover', backgroundPosition: 'center',
                    transition: 'transform .8s var(--ease)',
                  }}
                  onMouseEnter={(e) => { e.currentTarget.style.transform = 'scale(1.03)'; }}
                  onMouseLeave={(e) => { e.currentTarget.style.transform = 'scale(1)'; }}
                  ></div>
                </div>
              );
            })}
          </div>
          <p className="small" style={{ textAlign: 'center', marginTop: 48, fontStyle: 'italic', color: 'var(--ink-mute)' }}>
            {t(
              'Click any image to view full size. Use the arrow keys to move through the album.',
              'Klik op een beeld voor volledig formaat. Gebruik de pijltjestoetsen om door het album te bewegen.'
            )}
          </p>
        </div>
      </section>

      {/* Signature close */}
      <section style={{ padding: '64px 40px 96px', textAlign: 'center', background: 'var(--linen)' }}>
        <Signature size={72} />
        <p className="small" style={{ marginTop: 24, color: 'var(--ink-mute)', fontStyle: 'italic' }}>
          {t('Your album stays here as long as you want it to.', 'Jullie album blijft hier zolang jullie willen.')}
        </p>
      </section>

      {/* Lightbox */}
      {lightboxIdx !== null && data && (
        <div
          style={{
            position: 'fixed', inset: 0, zIndex: 200,
            background: 'rgba(26, 24, 22, 0.96)',
            display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 32,
          }}
          onClick={() => setLightboxIdx(null)}
        >
          <button
            onClick={(e) => { e.stopPropagation(); setLightboxIdx(null); }}
            style={{
              position: 'absolute', top: 24, right: 32, background: 'transparent', border: 0,
              color: 'var(--linen)', fontFamily: 'var(--font-body)', fontSize: 11,
              letterSpacing: '0.32em', textTransform: 'uppercase', cursor: 'pointer', opacity: 0.7,
            }}
          >{t('Close ×', 'Sluiten ×')}</button>
          <button
            onClick={(e) => { e.stopPropagation(); setLightboxIdx((i) => Math.max(i - 1, 0)); }}
            style={{
              position: 'absolute', left: 32, top: '50%', transform: 'translateY(-50%)',
              background: 'transparent', border: 0, color: 'var(--linen)',
              fontSize: 32, cursor: 'pointer', padding: '12px 18px',
              opacity: lightboxIdx === 0 ? 0.2 : 0.7,
            }}
          >←</button>
          <img
            src={photos[lightboxIdx].full_url}
            alt=""
            onClick={(e) => e.stopPropagation()}
            style={{ maxHeight: '88vh', maxWidth: '90vw', objectFit: 'contain' }}
          />
          <button
            onClick={(e) => { e.stopPropagation(); setLightboxIdx((i) => Math.min(i + 1, photos.length - 1)); }}
            style={{
              position: 'absolute', right: 32, top: '50%', transform: 'translateY(-50%)',
              background: 'transparent', border: 0, color: 'var(--linen)',
              fontSize: 32, cursor: 'pointer', padding: '12px 18px',
              opacity: lightboxIdx === photos.length - 1 ? 0.2 : 0.7,
            }}
          >→</button>
          {/* Per-photo download */}
          <a
            href={`/api/galleries/${encodeURIComponent(slug)}/download/${photos[lightboxIdx].id}`}
            onClick={(e) => e.stopPropagation()}
            style={{
              position: 'absolute', bottom: 24, right: 32,
              color: 'var(--linen)', fontFamily: 'var(--font-body)', fontSize: 11,
              letterSpacing: '0.32em', textTransform: 'uppercase',
              opacity: 0.7, textDecoration: 'none', borderBottom: '1px solid rgba(242,237,229,.4)',
              paddingBottom: 2,
            }}
          >{t('Download', 'Download')}</a>
          <div style={{
            position: 'absolute', bottom: 24, left: '50%', transform: 'translateX(-50%)',
            color: 'rgba(242,237,229,.6)', fontFamily: 'var(--font-body)',
            fontSize: 11, letterSpacing: '0.32em',
          }}>{lightboxIdx + 1} / {photos.length}</div>
        </div>
      )}
    </>
  );
}

Object.assign(window, { ClientGalleryScreen });
