const { useState, useEffect, useMemo, useRef } = React;

// ——— Supabase ———
const SUPABASE_URL = 'https://zyenbntrmtaaeiyiuuqj.supabase.co';
const SUPABASE_KEY = 'sb_publishable_hfmLh4KKFCprG_fjrOxifA_5cpAmv5M';
const supabase = window.supabase.createClient(SUPABASE_URL, SUPABASE_KEY);

// ——— Ornaments ———
const Ornament = ({ size = 28 }) => (
  <svg viewBox="0 0 40 40" width={size} height={size} aria-hidden="true">
    <g fill="none" stroke="currentColor" strokeWidth="0.8">
      <circle cx="20" cy="20" r="2.4" />
      <circle cx="20" cy="20" r="6" opacity="0.55" />
      <path d="M20 4 C 22 12, 22 12, 28 14 C 22 16, 22 16, 20 24 C 18 16, 18 16, 12 14 C 18 12, 18 12, 20 4 Z" opacity="0.85" />
      <path d="M4 20 C 12 18, 12 18, 14 12 M36 20 C 28 18, 28 18, 26 12 M4 20 C 12 22, 12 22, 14 28 M36 20 C 28 22, 28 22, 26 28" opacity="0.75" />
      <circle cx="6" cy="20" r="1" fill="currentColor" stroke="none" />
      <circle cx="34" cy="20" r="1" fill="currentColor" stroke="none" />
    </g>
  </svg>
);

const Sprig = ({ rotate = 0, size = 70, opacity = 0.5, style = {} }) => (
  <svg viewBox="0 0 80 80" width={size} height={size}
       style={{ transform: `rotate(${rotate}deg)`, opacity, ...style }}>
    <g fill="none" stroke="currentColor" strokeWidth="0.9" strokeLinecap="round">
      <path d="M40 78 Q 38 50, 42 22 Q 44 8, 40 4" />
      <path d="M42 60 Q 56 56, 62 46" />
      <path d="M40 50 Q 24 46, 18 36" />
      <path d="M42 38 Q 56 32, 60 22" />
      <path d="M40 28 Q 26 22, 22 14" />
      <circle cx="62" cy="46" r="3.5" fill="currentColor" stroke="none" opacity="0.55" />
      <circle cx="18" cy="36" r="3"   fill="currentColor" stroke="none" opacity="0.55" />
      <circle cx="60" cy="22" r="3"   fill="currentColor" stroke="none" opacity="0.55" />
      <circle cx="22" cy="14" r="2.5" fill="currentColor" stroke="none" opacity="0.55" />
      <circle cx="40" cy="4"  r="3.5" fill="currentColor" stroke="none" opacity="0.55" />
    </g>
  </svg>
);

const BookIcon = () => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.2">
    <path d="M3 4.5C 3 4, 3.5 3.5, 4 3.5L 11 3.5L 11 20.5L 4 20.5C 3.5 20.5, 3 20, 3 19.5Z" />
    <path d="M21 4.5C 21 4, 20.5 3.5, 20 3.5L 13 3.5L 13 20.5L 20 20.5C 20.5 20.5, 21 20, 21 19.5Z" />
    <line x1="12" y1="3.5" x2="12" y2="20.5" />
  </svg>
);

const RuleRow = ({ children, color }) => (
  <div className="ornament-row" style={color ? { color } : undefined}>
    <span className="rule"></span>
    {children || <Ornament />}
    <span className="rule"></span>
  </div>
);

// ——— Countdown ———
const TARGET = new Date('2026-07-27T00:00:00');

function useCountdown(target) {
  const [now, setNow] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const diff = Math.max(0, target - now);
  const d = Math.floor(diff / 86400000);
  const h = Math.floor((diff % 86400000) / 3600000);
  const m = Math.floor((diff % 3600000) / 60000);
  const s = Math.floor((diff % 60000) / 1000);
  return { d, h, m, s };
}

const Countdown = () => {
  const { d, h, m, s } = useCountdown(TARGET);
  const pad = (n) => String(n).padStart(2, '0');
  return (
    <div className="countdown" aria-label="Compte à rebours jusqu'au 27 juillet">
      <div className="cd-cell"><div className="cd-num">{d}</div><div className="cd-lbl">Jours</div></div>
      <div className="cd-sep">·</div>
      <div className="cd-cell"><div className="cd-num">{pad(h)}</div><div className="cd-lbl">Heures</div></div>
      <div className="cd-sep">·</div>
      <div className="cd-cell"><div className="cd-num">{pad(m)}</div><div className="cd-lbl">Minutes</div></div>
      <div className="cd-sep">·</div>
      <div className="cd-cell"><div className="cd-num">{pad(s)}</div><div className="cd-lbl">Secondes</div></div>
    </div>
  );
};

// ——— Hero ———
const Hero = () => (
  <section className="hero" data-screen-label="01 Hero">
    <div className="hero-inner">
      <div className="drift" style={{ top: 10, left: '4%', color: 'var(--sage-d)' }}>
        <Sprig rotate={-20} size={90} opacity={0.45} />
      </div>
      <div className="drift" style={{ top: 24, right: '5%', color: 'var(--blue-d)' }}>
        <Sprig rotate={28} size={90} opacity={0.45} />
      </div>
      <div className="drift" style={{ bottom: -20, left: '12%', color: 'var(--lavender-d)' }}>
        <Sprig rotate={170} size={70} opacity={0.4} />
      </div>
      <div className="drift" style={{ bottom: -10, right: '14%', color: 'var(--sage-d)' }}>
        <Sprig rotate={195} size={70} opacity={0.4} />
      </div>

      <div className="hero-frame">
        <span className="hero-cornu tl"></span>
        <span className="hero-cornu tr"></span>
        <span className="hero-cornu bl"></span>
        <span className="hero-cornu br"></span>

        <div className="eyebrow-script">Pour l'anniversaire de</div>
        <h1 className="name">Anaïlys<em>,</em></h1>
        <div className="age">21 ans</div>

        <div className="date-line">
          <span className="rule"></span>
          <span>XXVII · Juillet · MMXXVI</span>
          <span className="rule"></span>
        </div>

        <Countdown />

        <RuleRow color="var(--lavender-d)" />
        <div style={{ fontFamily: "'Cormorant Garamond', serif", fontStyle: 'italic',
                       color: 'var(--ink-soft)', fontSize: 18, marginTop: 14 }}>
          Une liste de livres, pour qu'une bibliothèque déjà débordante
          <br/>déborde tout à fait.
        </div>
      </div>
    </div>
  </section>
);

// ——— Books ———
const Card = ({ book, onState, onEditCover, onDelete }) => {
  const state = book.state || 'available';
  const initial = book.person_name ? book.person_name[0].toUpperCase() : '❦';

  return (
    <article className="card" data-state={state}>
      <div className="card-top">
        <div className="cover" onClick={onEditCover} role="button" aria-label="Modifier la couverture">
          {book.cover ? (
            <img src={book.cover} alt="" onError={(e) => { e.currentTarget.style.display = 'none'; }} />
          ) : (
            <div className="cover-placeholder">
              <BookIcon />
              <div className="label">Ajouter<br/>une image</div>
            </div>
          )}
          <div className="edit-cover">{book.cover ? 'Modifier' : 'Cliquer pour ajouter'}</div>
        </div>

        <div className="card-body">
          <div className="field-title" data-placeholder="Titre du livre">
            {book.title || ''}
          </div>
          <div className="field-author" data-placeholder="Auteur · Autrice">
            {book.author || ''}
          </div>
        </div>
      </div>

      {state === 'bought' && (
        <div className="wax" aria-label="Acheté">{initial}</div>
      )}

      <div className="card-foot">
        {state === 'available' && (
          <>
            <button className="btn primary" onClick={() => onState('reserved')}>Réserver</button>
            <button className="btn" onClick={() => onState('bought')}>Acheté</button>
            <button className="btn ghost" style={{ marginLeft: 'auto', borderColor: 'rgba(139,59,84,.25)', color: 'var(--ink-faint)' }} onClick={onDelete} title="Supprimer ce livre">✕</button>
          </>
        )}
        {state === 'reserved' && (
          <>
            <span className="state-label reserved-l">
              — Réservé{book.person_name ? ` · ${book.person_name}` : ''}
            </span>
            <button className="btn ghost" style={{ marginLeft: 'auto' }} onClick={() => onState('bought')}>Acheté</button>
            <button className="btn ghost" onClick={() => onState('available')}>Annuler</button>
          </>
        )}
        {state === 'bought' && (
          <>
            <span className="state-label">
              — Acheté ❀{book.person_name ? ` · ${book.person_name}` : ''}
            </span>
            <button className="btn ghost" style={{ marginLeft: 'auto' }} onClick={() => onState('available')}>Annuler</button>
          </>
        )}
      </div>
    </article>
  );
};

// ——— Name Picker Modal ———
const NamePickerModal = ({ action, currentName, knownNames, onConfirm, onClose }) => {
  const [name, setName] = useState(currentName || '');
  const inputRef = useRef(null);

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

  const submit = (e) => {
    e.preventDefault();
    const trimmed = name.trim();
    if (!trimmed) return;
    onConfirm(trimmed);
  };

  const label = action === 'reserved' ? 'Réserver' : 'Acheté';
  const question = action === 'reserved' ? 'Qui réserve ce livre ?' : 'Qui achète ce livre ?';

  return (
    <div className="modal-back" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <form className="modal" onSubmit={submit} style={{ maxWidth: 400 }}>
        <button type="button" className="close" onClick={onClose} aria-label="Fermer">×</button>
        <h3>{label}</h3>
        <div className="sub">{question}</div>

        <label>Votre nom</label>
        <input
          ref={inputRef}
          list="name-suggestions"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Entrez votre nom…"
          autoComplete="off"
        />
        <datalist id="name-suggestions">
          {knownNames.map((n) => <option key={n} value={n} />)}
        </datalist>

        <div className="modal-actions">
          <button type="button" className="btn ghost" onClick={onClose}>Annuler</button>
          <button type="submit" className="btn primary" disabled={!name.trim()}>
            Confirmer
          </button>
        </div>
      </form>
    </div>
  );
};

// ——— Book Modal ———
const BookModal = ({ initial, mode, onSave, onClose }) => {
  const [title, setTitle] = useState(initial?.title || '');
  const [author, setAuthor] = useState(initial?.author || '');
  const [cover, setCover] = useState(initial?.cover || '');
  const [saving, setSaving] = useState(false);
  const titleInputRef = useRef(null);

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

  const submit = async (e) => {
    e?.preventDefault?.();
    setSaving(true);
    await onSave({
      title: title.trim(),
      author: author.trim(),
      cover: cover.trim(),
    });
    setSaving(false);
  };

  return (
    <div className="modal-back" onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <form className="modal" onSubmit={submit}>
        <button type="button" className="close" onClick={onClose} aria-label="Fermer">×</button>
        <h3>{mode === 'edit' ? 'Modifier le livre' : 'Ajouter un livre'}</h3>
        <div className="sub">à la liste d'Ana</div>

        <label>Titre du livre</label>
        <input
          ref={titleInputRef}
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          placeholder="Orgueil et Préjugés"
        />

        <label>Auteur · Autrice</label>
        <input
          type="text"
          value={author}
          onChange={(e) => setAuthor(e.target.value)}
          placeholder="Jane Austen"
        />

        <label>URL de l'image de couverture</label>
        <input
          type="url"
          value={cover}
          onChange={(e) => setCover(e.target.value)}
          placeholder="https://..."
        />

        <div className="modal-preview">
          {cover ? (
            <img src={cover} alt="" onError={(e) => { e.currentTarget.style.display = 'none'; }} />
          ) : (
            <div className="ph">aperçu</div>
          )}
        </div>

        <div className="modal-actions">
          <button type="button" className="btn ghost" onClick={onClose} disabled={saving}>Annuler</button>
          <button type="submit" className="btn primary" disabled={saving}>
            {saving ? '…' : (mode === 'edit' ? 'Enregistrer' : 'Ajouter à la liste')}
          </button>
        </div>
      </form>
    </div>
  );
};

// ——— App ———
const App = () => {
  const [books, setBooks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [filter, setFilter] = useState('all');
  const [modal, setModal] = useState(null);
  const [nameModal, setNameModal] = useState(null);

  // Initial load
  useEffect(() => {
    const load = async () => {
      const { data, error } = await supabase
        .from('books')
        .select('*')
        .order('position', { ascending: true });
      if (error) {
        console.error(error);
        setError(error.message);
      } else {
        setBooks(data || []);
      }
      setLoading(false);
    };
    load();
  }, []);

  // Realtime subscription
  useEffect(() => {
    const channel = supabase
      .channel('books-changes')
      .on('postgres_changes', { event: '*', schema: 'public', table: 'books' }, (payload) => {
        setBooks((prev) => {
          if (payload.eventType === 'INSERT') {
            if (prev.find((b) => b.id === payload.new.id)) return prev;
            return [...prev, payload.new].sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
          }
          if (payload.eventType === 'UPDATE') {
            return prev.map((b) => b.id === payload.new.id ? payload.new : b);
          }
          if (payload.eventType === 'DELETE') {
            return prev.filter((b) => b.id !== payload.old.id);
          }
          return prev;
        });
      })
      .subscribe();
    return () => { supabase.removeChannel(channel); };
  }, []);

  const counts = useMemo(() => {
    let a = 0, r = 0, b = 0;
    books.forEach((bk) => {
      if (bk.state === 'reserved') r++;
      else if (bk.state === 'bought') b++;
      else a++;
    });
    return { all: books.length, available: a, reserved: r, bought: b };
  }, [books]);

  const filtered = useMemo(() => {
    const sorted = [...books].sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
    if (filter === 'all') return sorted.map((b, i) => ({ b, i }));
    return sorted
      .map((b, i) => ({ b, i }))
      .filter(({ b }) => (b.state || 'available') === filter);
  }, [books, filter]);

  const knownNames = useMemo(() => {
    const names = books.map((b) => b.person_name).filter(Boolean);
    return [...new Set(names)];
  }, [books]);

  const setStateOf = async (id, state, personName) => {
    const update = { state, person_name: state === 'available' ? null : personName };
    setBooks((prev) => prev.map((b) => b.id === id ? { ...b, ...update } : b));
    const { error } = await supabase.from('books').update(update).eq('id', id);
    if (error) { console.error(error); alert('Erreur : ' + error.message); }
  };

  const requestState = (book, state) => {
    if (state === 'available') {
      setStateOf(book.id, 'available', null);
    } else if (state === 'bought' && book.person_name) {
      setStateOf(book.id, 'bought', book.person_name);
    } else {
      setNameModal({ id: book.id, state, currentName: book.person_name || '' });
    }
  };

  const confirmName = (name) => {
    if (!nameModal) return;
    setStateOf(nameModal.id, nameModal.state, name);
    setNameModal(null);
  };

  const removeBook = async (id) => {
    setBooks((prev) => prev.filter((b) => b.id !== id));
    const { error } = await supabase.from('books').delete().eq('id', id);
    if (error) { console.error(error); alert('Erreur : ' + error.message); }
  };

  const handleSave = async (data) => {
    if (modal?.mode === 'edit') {
      const id = modal.id;
      setBooks((prev) => prev.map((b) => b.id === id ? { ...b, ...data } : b));
      const { error } = await supabase.from('books').update(data).eq('id', id);
      if (error) { console.error(error); alert('Erreur : ' + error.message); return; }
    } else {
      const id = 'b' + Date.now();
      const maxPos = books.reduce((m, b) => Math.max(m, b.position ?? 0), 0);
      const row = { id, ...data, state: 'available', position: maxPos + 1 };
      setBooks((prev) => [...prev, row]);
      const { error } = await supabase.from('books').insert(row);
      if (error) { console.error(error); alert('Erreur : ' + error.message); return; }
    }
    setModal(null);
  };

  const editingBook = modal?.mode === 'edit' ? books.find((b) => b.id === modal.id) : null;

  return (
    <>
      <Hero />

      <div className="section-head" data-screen-label="03 La liste">
        <RuleRow color="var(--ink-faint)" />
        <h2>La liste</h2>
        <div className="sub">à compléter, à réserver, à acheter</div>
      </div>

      {error && (
        <div style={{ textAlign: 'center', color: '#8b3b54', fontStyle: 'italic',
                      maxWidth: 600, margin: '0 auto 20px', padding: '0 24px' }}>
          Impossible de charger la liste — {error}
        </div>
      )}

      <div className="stats">
        <span><b>{counts.all}</b>livres</span>
        <span><b>{counts.reserved}</b>réservés</span>
        <span><b>{counts.bought}</b>achetés</span>
      </div>

      <div className="filters" role="tablist">
        {[
          ['all',       'Tous',       counts.all],
          ['available', 'À réserver', counts.available],
          ['reserved',  'Réservés',   counts.reserved],
          ['bought',    'Achetés',    counts.bought],
        ].map(([k, label, n]) => (
          <button
            key={k}
            className="chip"
            aria-pressed={filter === k}
            onClick={() => setFilter(k)}>
            {label}<span className="count">· {n}</span>
          </button>
        ))}
      </div>

      {loading ? (
        <div style={{ textAlign: 'center', padding: '40px 24px', color: 'var(--ink-faint)',
                       fontFamily: "'Cormorant Garamond', serif", fontStyle: 'italic', fontSize: 20 }}>
          Chargement de la bibliothèque…
        </div>
      ) : filtered.length === 0 ? (
        <div style={{ textAlign: 'center', padding: '40px 24px', color: 'var(--ink-faint)',
                       fontFamily: "'Cormorant Garamond', serif", fontStyle: 'italic', fontSize: 20 }}>
          {books.length === 0
            ? "La liste est encore vierge — ajoute le premier livre ↓"
            : "Aucun livre dans cette catégorie."}
        </div>
      ) : (
        <div className="grid">
          {filtered.map(({ b }) => (
            <Card
              key={b.id}
              book={b}
              onState={(state) => requestState(b, state)}
              onEditCover={() => setModal({ mode: 'edit', id: b.id })}
              onDelete={() => {
                if (confirm('Supprimer ce livre de la liste ?')) removeBook(b.id);
              }}
            />
          ))}
        </div>
      )}

      <div style={{ textAlign: 'center', padding: '18px 24px 0' }}>
        <button className="btn primary" onClick={() => setModal({ mode: 'add' })}>
          ❦ &nbsp; Ajouter un livre
        </button>
      </div>

      <footer>
        <RuleRow color="var(--lavender-d)" />
        <div className="quote">
          <span className="open">«</span> Il n'y a pas de plus fidèle ami qu'un livre.
          <span className="close">»</span>
        </div>
        <div className="credit">avec tendresse · pour Ana · juillet MMXXVI</div>
      </footer>

      {nameModal && (
        <NamePickerModal
          action={nameModal.state}
          currentName={nameModal.currentName}
          knownNames={knownNames}
          onConfirm={confirmName}
          onClose={() => setNameModal(null)}
        />
      )}

      {modal && (
        <BookModal
          mode={modal.mode}
          initial={editingBook}
          onSave={handleSave}
          onClose={() => setModal(null)}
        />
      )}
    </>
  );
};

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