/* Galeria Ślubna — main application */
const { useState, useRef, useCallback, useEffect } = React;

const COVER = { image: 'assets/cover.jpg', type: 'photo' };

const FONT_STACKS = {
  Cormorant: "'Cormorant Garamond', Georgia, serif",
  Playfair:  "'Playfair Display', Georgia, serif",
  Tenor:     "'Tenor Sans', Georgia, serif"
};

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "sage": "#ADB26C",
  "purple": "#AE98AB",
  "headingFont": "Cormorant",
  "bend": 3,
  "borderRadius": 0.05,
  "showMonogram": true
}/*EDITMODE-END*/;

function scrollToRef(ref) {
  if (!ref.current) return;
  const y = ref.current.getBoundingClientRect().top + window.pageYOffset - 8;
  window.scrollTo({ top: y, behavior: 'smooth' });
}

/* ── Podgląd przed dodaniem ── */
function UploadPreviewModal({ files, uploading, onConfirm, onCancel }) {
  const [previews] = useState(() =>
    files.map(f => ({ url: URL.createObjectURL(f), type: f.type, name: f.name }))
  );

  useEffect(() => {
    return () => previews.forEach(p => URL.revokeObjectURL(p.url));
  }, []);

  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape' && !uploading) onCancel(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [uploading, onCancel]);

  const count = files.length;
  const label = count === 1 ? '1 plik' : (count >= 2 && count <= 4) ? `${count} pliki` : `${count} plików`;

  return (
    <div className="dl-modal" onClick={!uploading ? onCancel : undefined}>
      <div className="dl-modal-inner" onClick={e => e.stopPropagation()}>
        <div className="dl-modal-head">
          <h3 className="dl-modal-title">Dodaj {label} do galerii</h3>
          {!uploading && <button className="lb-close" style={{position:'static'}} onClick={onCancel}>✕</button>}
        </div>
        <div className="dl-grid">
          {previews.map((p, i) => (
            <div key={i} className={'dl-item' + (p.type.startsWith('video/') ? ' is-video' : '')}>
              {p.type.startsWith('video/')
                ? <video src={p.url} muted playsInline preload="metadata" className="dl-media" />
                : <img   src={p.url} alt="" className="dl-media" />
              }
              {p.type.startsWith('video/') && (
                <div className="thumb-play" style={{pointerEvents:'none'}} aria-hidden="true">▶</div>
              )}
            </div>
          ))}
        </div>
        <div className="dl-modal-footer">
          <button className="btn btn-ghost" onClick={onCancel} disabled={uploading}>Anuluj</button>
          <button className="btn btn-primary" onClick={onConfirm} disabled={uploading}>
            {uploading ? 'Wysyłanie…' : 'Dodaj do galerii'}
          </button>
        </div>
      </div>
    </div>
  );
}

/* ── Potwierdzenie usunięcia ── */
function DeleteConfirmModal({ item, onConfirm, onCancel }) {
  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onCancel(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onCancel]);

  return (
    <div className="dl-modal" style={{zIndex:1010}} onClick={onCancel}>
      <div className="dl-modal-inner dl-modal-inner--sm" onClick={e => e.stopPropagation()}>
        <div className="dl-modal-head">
          <h3 className="dl-modal-title">Usunąć ten plik?</h3>
          <button className="lb-close" style={{position:'static'}} onClick={onCancel}>✕</button>
        </div>
        <div className="delete-preview">
          {item.type === 'video'
            ? <video src={item.image} muted playsInline preload="metadata" className="delete-media" />
            : <img   src={item.image} alt="" className="delete-media" />
          }
        </div>
        <div className="dl-modal-footer">
          <button className="btn btn-ghost" onClick={onCancel}>Anuluj</button>
          <button className="btn btn-danger" onClick={onConfirm}>Usuń</button>
        </div>
      </div>
    </div>
  );
}

/* ── Modal galerii ── */
function GalleryModal({ items, onClose, onDelete }) {
  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);

  return (
    <div className="dl-modal" onClick={onClose}>
      <div className="dl-modal-inner" onClick={e => e.stopPropagation()}>
        <div className="dl-modal-head">
          <h3 className="dl-modal-title">Wszystkie zdjęcia i filmy</h3>
          <button className="lb-close" style={{position:'static'}} onClick={onClose}>✕</button>
        </div>

        {items.length === 0 ? (
          <p className="dl-empty">Brak zdjęć — wrzuć pierwsze zdjęcie powyżej!</p>
        ) : (
          <div className="dl-grid">
            {items.map((it, i) => (
              <div key={i} className={'dl-item' + (it.type === 'video' ? ' is-video' : '')}>
                {it.type === 'video'
                  ? <video src={it.image} muted playsInline preload="metadata" className="dl-media" />
                  : <img   src={it.image} alt="" className="dl-media" loading="lazy" />
                }
                {it.type === 'video' && (
                  <div className="thumb-play" style={{pointerEvents:'none'}} aria-hidden="true">▶</div>
                )}
                <button className="dl-delete" aria-label="Usuń" onClick={() => onDelete(it)}>
                  🗑
                </button>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

/* ── Lightbox (bez pobierania) ── */
function Lightbox({ items, startIndex, onClose }) {
  const [idx, setIdx] = useState(startIndex);
  const item = items[idx];
  const isVideo = item && item.type === 'video';

  useEffect(() => {
    document.body.style.overflow = 'hidden';
    return () => { document.body.style.overflow = ''; };
  }, []);

  useEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape')     onClose();
      if (e.key === 'ArrowRight') setIdx(i => Math.min(i + 1, items.length - 1));
      if (e.key === 'ArrowLeft')  setIdx(i => Math.max(i - 1, 0));
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [items.length, onClose]);

  const goFullscreen = () => {
    const el = document.querySelector('.lb-media');
    if (el && el.requestFullscreen) el.requestFullscreen();
  };

  if (!item) return null;

  return (
    <div className="lightbox" onClick={onClose}>
      <div className="lb-inner" onClick={e => e.stopPropagation()}>
        <button className="lb-close" onClick={onClose} aria-label="Zamknij">✕</button>

        {isVideo
          ? <video className="lb-media" src={item.image} controls autoPlay loop playsInline />
          : <img   className="lb-media" src={item.image} alt="" />
        }

        {idx > 0 && (
          <button className="lb-nav lb-prev"
            onClick={e => { e.stopPropagation(); setIdx(i => i - 1); }}
            aria-label="Poprzednie">‹</button>
        )}
        {idx < items.length - 1 && (
          <button className="lb-nav lb-next"
            onClick={e => { e.stopPropagation(); setIdx(i => i + 1); }}
            aria-label="Następne">›</button>
        )}

        {!isVideo && (
          <div className="lb-actions">
            <button className="lb-btn" onClick={goFullscreen}>⛶ Pełny ekran</button>
          </div>
        )}

        <div className="lb-counter">{idx + 1} / {items.length}</div>
      </div>
    </div>
  );
}

/* ── Upload zone ── */
function UploadZone({ onFiles, uploading, error }) {
  const inputRef = useRef(null);
  const [drag, setDrag] = useState(false);

  const handleFiles = useCallback((fileList) => {
    const files = Array.from(fileList).filter(
      f => f.type.startsWith('image/') || f.type.startsWith('video/')
    );
    if (!files.length) return;
    onFiles(files);
  }, [onFiles]);

  return (
    <div
      className={'dropzone' + (drag ? ' is-drag' : '') + (uploading ? ' is-uploading' : '')}
      onClick={() => !uploading && inputRef.current && inputRef.current.click()}
      onDragOver={e  => { e.preventDefault(); setDrag(true); }}
      onDragLeave={e => { e.preventDefault(); setDrag(false); }}
      onDrop={e      => { e.preventDefault(); setDrag(false); handleFiles(e.dataTransfer.files); }}
    >
      <input ref={inputRef} type="file" accept="image/*,video/*" multiple
        style={{ display: 'none' }}
        onChange={e => { handleFiles(e.target.files); e.target.value = ''; }} />
      <div className="dropzone-icon" aria-hidden="true">
        <svg viewBox="0 0 48 48" width="44" height="44" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" strokeLinejoin="round">
          <path d="M24 31V13"/><path d="M16 21l8-8 8 8"/>
          <path d="M10 31v5a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2v-5"/>
        </svg>
      </div>
      <p className="dropzone-title">{uploading ? 'Wysyłanie…' : 'Przeciągnij zdjęcia i filmy tutaj'}</p>
      <p className="dropzone-sub">{uploading ? 'Proszę czekać' : 'lub kliknij, aby wybrać z urządzenia'}</p>
      {error && <p className="dropzone-error">{error}</p>}
    </div>
  );
}

/* ── App ── */
function App() {
  const [t, setTweak]     = useTweaks(TWEAK_DEFAULTS);
  const [items, setItems] = useState([COVER]);
  const [uploading, setUploading]     = useState(false);
  const [uploadError, setUploadError] = useState('');
  const [lightboxIndex, setLightboxIndex] = useState(null);
  const [showGallery, setShowGallery]     = useState(false);
  const [showAllRecent, setShowAllRecent] = useState(false);
  const [pendingUpload, setPendingUpload] = useState(null);  // File[] czeka na potwierdzenie
  const [pendingDelete, setPendingDelete] = useState(null);  // item czeka na potwierdzenie

  const uploadRef  = useRef(null);
  const galleryRef = useRef(null);

  useEffect(() => {
    fetch('/api/photos')
      .then(r => r.json())
      .then(data => {
        if (data.length) {
          setItems([COVER, ...data.map(d => ({ image: d.url, type: d.type }))]);
        }
      })
      .catch(() => {});
  }, []);

  // Etap 1: pokaż podgląd
  const addItems = useCallback((files) => {
    setPendingUpload(files);
  }, []);

  // Etap 2: wyślij po potwierdzeniu
  const confirmUpload = useCallback(() => {
    const files = pendingUpload;
    if (!files) return;
    const formData = new FormData();
    files.forEach(f => formData.append('photos', f));
    setUploading(true);
    setUploadError('');
    fetch('/api/upload', { method: 'POST', body: formData })
      .then(r => { if (!r.ok) throw new Error(); return r.json(); })
      .then(data => {
        if (data.ok) {
          setItems(prev => [...prev, ...data.items.map(d => ({ image: d.url, type: d.type }))]);
          setPendingUpload(null);
        }
      })
      .catch(() => setUploadError('Nie udało się wysłać. Upewnij się że serwer działa (npm start).'))
      .finally(() => setUploading(false));
  }, [pendingUpload]);

  // Etap 1: pokaż potwierdzenie
  const promptDelete = useCallback((item) => {
    setPendingDelete(item);
  }, []);

  // Etap 2: usuń po potwierdzeniu
  const confirmDelete = useCallback(() => {
    const item = pendingDelete;
    if (!item) return;
    setPendingDelete(null);
    const filename = item.image.split('/').pop();
    fetch(`/api/photo/${encodeURIComponent(filename)}`, { method: 'DELETE' })
      .then(r => r.json())
      .then(data => {
        if (data.ok) setItems(prev => prev.filter(it => it.image !== item.image));
      })
      .catch(() => {});
  }, [pendingDelete]);

  const recent          = items.slice(1).reverse();
  const galleryPhotos   = items.filter(it => it.type === 'photo');
  const RECENT_DEFAULT  = 8;
  const displayedRecent = showAllRecent ? recent : recent.slice(0, RECENT_DEFAULT);

  const cssVars = {
    '--sage':         t.sage,
    '--purple':       t.purple,
    '--heading-font': FONT_STACKS[t.headingFont] || FONT_STACKS.Cormorant
  };

  return (
    <div className="page" style={cssVars}>

      {/* ===== HERO ===== */}
      <header className="hero">
        <div className="hero-bloom hero-bloom--sage" />
        <div className="hero-bloom hero-bloom--purple" />
        <div className="hero-inner">
          {t.showMonogram && (
            <div className="monogram">
              <span>P</span><span className="monogram-amp">&amp;</span><span>R</span>
            </div>
          )}
          <p className="eyebrow">Z radością dzielimy się chwilami</p>
          <h1 className="couple">
            <span className="couple-name">Patrycja</span>
            <span className="couple-and">i</span>
            <span className="couple-name">Rafał</span>
          </h1>
          <div className="date-row">
            <span className="rule" /><span className="date">22.05.2026</span><span className="rule" />
          </div>
          <div className="hero-actions">
            <button className="btn btn-primary" onClick={() => scrollToRef(uploadRef)}>Wrzuć zdjęcia i filmy</button>
            <button className="btn btn-ghost"   onClick={() => scrollToRef(galleryRef)}>Zobacz galerię</button>
          </div>
        </div>
        <button className="scroll-cue" onClick={() => scrollToRef(uploadRef)} aria-label="Przewiń w dół">
          <svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
            <path d="M6 9l6 6 6-6"/>
          </svg>
        </button>
      </header>

      {/* ===== UPLOAD ===== */}
      <section className="section--upload" ref={uploadRef}>
        <div className="upload-inner">
          <div className="section-head">
            <p className="section-kicker">Podziel się</p>
            <h2 className="section-title">Twoje spojrzenie na ten dzień</h2>
            <p className="section-lead">
              Masz zdjęcie lub film z naszego ślubu? Dodaj je do wspólnej galerii —
              każda chwila uchwycona Waszymi oczami jest dla nas bezcenna.
            </p>
          </div>
          <UploadZone onFiles={addItems} uploading={uploading} error={uploadError} />

          {recent.length > 0 && (
            <div className="recent">
              <div className="recent-toolbar">
                <p className="recent-label">Ostatnio dodane</p>
                {recent.length > RECENT_DEFAULT && (
                  <button className="tb-btn" onClick={() => setShowAllRecent(m => !m)}>
                    {showAllRecent ? 'Zwiń' : `Zobacz wszystkie (${recent.length})`}
                  </button>
                )}
              </div>
              <div className="recent-grid">
                {displayedRecent.map((it, i) => (
                  <div
                    key={i}
                    className={'recent-thumb' + (it.type === 'video' ? ' is-video' : '')}
                    style={it.type !== 'video' ? { backgroundImage: `url(${it.image})` } : undefined}
                    onClick={() => setLightboxIndex(recent.indexOf(it))}
                  >
                    {it.type === 'video' && (
                      <video src={it.image} muted playsInline preload="metadata" className="thumb-video" />
                    )}
                    {it.type === 'video' && (
                      <div className="thumb-play" aria-hidden="true">▶</div>
                    )}
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      </section>

      {/* ===== GALLERY ===== */}
      <section className="section section--gallery" ref={galleryRef}>
        <div className="section-head">
          <p className="section-kicker">Galeria</p>
          <h2 className="section-title">Karuzela wspomnień</h2>
          <p className="section-lead">Przeciągnij w bok lub przewiń, aby odkrywać kolejne kadry.</p>
        </div>
        <div className="gallery-stage">
          <CircularGallery
            items={galleryPhotos}
            bend={t.bend}
            borderRadius={t.borderRadius}
            scrollSpeed={2}
            scrollEase={0.05}
          />
        </div>
        <div className="gallery-download-bar">
          <button className="btn btn-ghost" onClick={() => setShowGallery(true)}>
            Zobacz wszystkie
          </button>
        </div>
      </section>

      {/* ===== FOOTER ===== */}
      <footer className="footer">
        <div className="footer-mono">P &amp; R</div>
        <p>Dziękujemy, że jesteście częścią naszej historii.</p>
        <span className="footer-date">22 maja 2026</span>
      </footer>

      {/* ===== TWEAKS ===== */}
      <TweaksPanel>
        <TweakSection label="Kolory" />
        <TweakColor label="Główny (szałwia)" value={t.sage}
          options={['#ADB26C', '#9BA85E', '#C0BE84', '#8E9A66']}
          onChange={v => setTweak('sage', v)} />
        <TweakColor label="Dodatkowy (wrzos)" value={t.purple}
          options={['#AE98AB', '#B7A6B9', '#9E8AA0', '#C4A9BE']}
          onChange={v => setTweak('purple', v)} />
        <TweakSection label="Typografia" />
        <TweakRadio label="Nagłówki" value={t.headingFont}
          options={['Cormorant', 'Playfair', 'Tenor']}
          onChange={v => setTweak('headingFont', v)} />
        <TweakSection label="Karuzela" />
        <TweakSlider label="Wygięcie"     value={t.bend}         min={0} max={6}   step={0.5}  onChange={v => setTweak('bend', v)} />
        <TweakSlider label="Zaokrąglenie" value={t.borderRadius} min={0} max={0.2} step={0.01} onChange={v => setTweak('borderRadius', v)} />
        <TweakSection label="Detale" />
        <TweakToggle label="Monogram" value={t.showMonogram} onChange={v => setTweak('showMonogram', v)} />
      </TweaksPanel>

      {/* ===== LIGHTBOX ===== */}
      {lightboxIndex !== null && (
        <Lightbox
          items={recent}
          startIndex={lightboxIndex}
          onClose={() => setLightboxIndex(null)}
        />
      )}

      {/* ===== PODGLĄD UPLOADU ===== */}
      {pendingUpload && (
        <UploadPreviewModal
          files={pendingUpload}
          uploading={uploading}
          onConfirm={confirmUpload}
          onCancel={() => { setPendingUpload(null); setUploadError(''); }}
        />
      )}

      {/* ===== GALLERY MODAL ===== */}
      {showGallery && (
        <GalleryModal
          items={items}
          onClose={() => setShowGallery(false)}
          onDelete={promptDelete}
        />
      )}

      {/* ===== POTWIERDZENIE USUNIĘCIA ===== */}
      {pendingDelete && (
        <DeleteConfirmModal
          item={pendingDelete}
          onConfirm={confirmDelete}
          onCancel={() => setPendingDelete(null)}
        />
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
