/* Brand Lens — Library / repository view */
function Library({ recs, reload, goReview }) {
  const [filter, setFilter] = useState('all');
  const [busy, setBusy] = useState(null); // {done,total}
  const [drag, setDrag] = useState(false);
  const [note, setNote] = useState(null);
  const fileRef = useRef(null);
  const importRef = useRef(null);

  const ordered = useMemo(
    () => [...recs].sort((a, b) => a.shuffleKey - b.shuffleKey),
    [recs]
  );
  const counts = useMemo(() => {
    let reviewed = 0, aligned = 0, unrev = 0;
    for (const r of recs) {
      if (r.user) {
        reviewed++;
        if (r.ai && (r.ai.verdict === 'keep') === !!r.user.like) aligned++;
      } else unrev++;
    }
    return { total: recs.length, reviewed, aligned, unrev };
  }, [recs]);

  const shown = ordered.filter((r) => {
    if (filter === 'all') return true;
    if (filter === 'unrev') return !r.user;
    if (filter === 'liked') return r.user && r.user.like;
    if (filter === 'disliked') return r.user && !r.user.like;
    return true;
  });

  async function handleFiles(list) {
    if (!list || !list.length) return;
    setBusy({ done: 0, total: Array.from(list).filter((f) => /^image\//.test(f.type)).length });
    await window.LensDB.addFiles(list, (done, total) => setBusy({ done, total }));
    setBusy(null);
    reload();
  }

  async function removeOne(id) {
    await window.LensDB.del(id);
    reload();
  }
  async function resetOne(id) {
    await window.LensDB.patch(id, { ai: null, user: null });
    reload();
  }
  async function clearAll() {
    if (!confirm('Remove ALL images and their feedback? This cannot be undone.')) return;
    await window.LensDB.clearAll();
    reload();
  }
  async function shuffle() { await window.LensDB.reshuffle(); reload(); }

  async function exportData() {
    const bundle = await window.LensDB.exportBundle();
    const blob = new Blob([JSON.stringify(bundle)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    const d = new Date();
    a.href = url;
    a.download = `brand-lens-backup-${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}.json`;
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 2000);
    setNote('Backup downloaded — keep it safe or move it to another machine.');
  }
  async function importData(file) {
    if (!file) return;
    try {
      const bundle = JSON.parse(await file.text());
      const mode = recs.length > 0
        ? (confirm(`Import ${bundle.count || (bundle.images || []).length} images.\n\nOK = MERGE into your current ${recs.length}.\nCancel = REPLACE everything with the backup.`) ? 'merge' : 'replace')
        : 'replace';
      const added = await window.LensDB.importBundle(bundle, mode);
      reload();
      setNote(`Imported ${added} images (${mode}).`);
    } catch (e) { setNote('Could not read that file — is it a Brand Lens backup?'); }
  }

  const filters = [
    ['all', 'All', counts.total],
    ['unrev', 'Not reviewed', counts.unrev],
    ['liked', 'Kept', recs.filter((r) => r.user && r.user.like).length],
    ['disliked', 'Rejected', recs.filter((r) => r.user && !r.user.like).length],
  ];

  return (
    <div>
      {/* header row */}
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', gap: 20, flexWrap: 'wrap', marginBottom: 24 }}>
        <div>
          <h2 style={{ fontSize: 'clamp(26px,2.8vw,34px)', margin: 0, fontWeight: 500, letterSpacing: '-.015em' }}>The repository</h2>
          <p style={{ fontSize: 16, color: 'var(--fg-2)', margin: '10px 0 0', maxWidth: '60ch', lineHeight: 1.6 }}>
            Your taste library. Drop in photos, stock, and clip-art — they're shuffled, not served in upload order.
            Review them blind, then watch a style guide build itself from your calls.
          </p>
        </div>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
          <Btn kind="primary" icon="upload" onClick={() => fileRef.current && fileRef.current.click()}>Add images</Btn>
          {counts.unrev > 0 && <Btn kind="dark" icon="arrow" onClick={goReview}>Review {counts.unrev} blind</Btn>}
        </div>
      </div>

      <input ref={fileRef} type="file" accept="image/*" multiple style={{ display: 'none' }}
        onChange={(e) => { handleFiles(e.target.files); e.target.value = ''; }} />
      <input ref={importRef} type="file" accept="application/json,.json" style={{ display: 'none' }}
        onChange={(e) => { importData(e.target.files[0]); e.target.value = ''; }} />

      {note && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '11px 16px', marginBottom: 18, fontSize: 13.5,
          background: 'var(--ps-dark-blue-100)', color: 'var(--ps-dark-blue-700)', borderRadius: 10 }}>
          <Icon name="save" size={15} /> {note}
          <button onClick={() => setNote(null)} style={{ marginLeft: 'auto', background: 'none', border: 'none', cursor: 'pointer', color: 'inherit' }}><Icon name="x" size={14} /></button>
        </div>
      )}

      {/* stat strip */}
      {counts.total > 0 && (
        <div style={{ display: 'flex', gap: 28, flexWrap: 'wrap', padding: '16px 20px', marginBottom: 22,
          background: 'var(--ps-cloud-gray)', borderRadius: 14, border: '1px solid var(--ps-line)' }}>
          <Stat n={counts.total} l="in library" />
          <Stat n={counts.reviewed} l="reviewed" />
          <Stat n={counts.reviewed ? Math.round((counts.aligned / counts.reviewed) * 100) + '%' : '—'} l="AI aligned with you" />
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
            <Btn icon="download" onClick={exportData}>Back up</Btn>
            <Btn icon="save" onClick={() => importRef.current && importRef.current.click()}>Restore</Btn>
            <Btn icon="shuffle" onClick={shuffle}>Reshuffle</Btn>
            <Btn kind="danger" icon="trash" onClick={clearAll}>Clear all</Btn>
          </div>
        </div>
      )}

      {/* dropzone / empty */}
      {counts.total === 0 ? (
        <Dropzone drag={drag} setDrag={setDrag} onFiles={handleFiles} busy={busy}
          onPick={() => fileRef.current && fileRef.current.click()}
          onRestore={() => importRef.current && importRef.current.click()} />
      ) : (
        <div
          onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
          onDragLeave={() => setDrag(false)}
          onDrop={(e) => { e.preventDefault(); setDrag(false); handleFiles(e.dataTransfer.files); }}
          style={{ outline: drag ? '2px dashed var(--ps-primary-blue)' : 'none', outlineOffset: 8, borderRadius: 14 }}
        >
          {/* filters */}
          <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 18 }}>
            {filters.map(([k, lab, n]) => (
              <button key={k} onClick={() => setFilter(k)} style={{
                fontFamily: 'var(--font-sans)', fontSize: 13, fontWeight: 600, cursor: 'pointer',
                padding: '7px 13px', borderRadius: 60, border: '1px solid var(--ps-line)',
                background: filter === k ? 'var(--ps-navy)' : 'var(--ps-white)',
                color: filter === k ? '#fff' : 'var(--fg-2)',
              }}>{lab} <span style={{ opacity: .6 }}>{n}</span></button>
            ))}
          </div>

          {busy && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 16, color: 'var(--fg-2)', fontSize: 14 }}>
              <Spinner /> Importing {busy.done}/{busy.total}…
            </div>
          )}

          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(212px,1fr))', gap: 18 }}>
            {shown.map((r) => <LibCard key={r.id} rec={r} onRemove={() => removeOne(r.id)} onReset={() => resetOne(r.id)} />)}
          </div>
          {shown.length === 0 && (
            <p style={{ color: 'var(--fg-3)', fontSize: 15, padding: '30px 0' }}>Nothing in this filter yet.</p>
          )}
        </div>
      )}
    </div>
  );
}

function Stat({ n, l }) {
  return (
    <div>
      <div style={{ fontSize: 26, fontWeight: 700, color: 'var(--ps-navy)', lineHeight: 1 }}>{n}</div>
      <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 5, letterSpacing: '.02em' }}>{l}</div>
    </div>
  );
}

function LibCard({ rec, onRemove, onReset }) {
  const [hover, setHover] = useState(false);
  return (
    <figure
      onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
      style={{ margin: 0, background: 'var(--ps-white)', border: '1px solid var(--ps-line)',
        borderRadius: 14, overflow: 'hidden', boxShadow: hover ? 'var(--sh-2)' : 'var(--sh-1)',
        transform: hover ? 'translateY(-2px)' : 'none', transition: 'all .18s var(--ease-standard)' }}>
      <div style={{ position: 'relative', aspectRatio: '4/3', background: 'var(--ps-cloud-gray)' }}>
        <img src={rec.dataURL} alt={rec.name} loading="lazy" decoding="async" style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }} />
        {(rec.ai || (rec.category && rec.category !== 'auto')) && (
          <div style={{ position: 'absolute', top: 8, left: 8 }}>
            <CategoryBadge category={(rec.ai && rec.ai.category) || rec.category} small />
          </div>
        )}
        {hover && (
          <div style={{ position: 'absolute', top: 8, right: 8, display: 'flex', gap: 6 }}>
            {rec.user && (
              <IconBtn title="Re-review (clears feedback)" onClick={onReset} name="refresh" />
            )}
            <IconBtn title="Remove image + feedback" onClick={onRemove} name="trash" danger />
          </div>
        )}
      </div>
      <figcaption style={{ padding: '11px 12px 13px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8 }}>
          <StatusChip rec={rec} />
          {rec.user && <span style={{ color: rec.user.like ? 'var(--st-success)' : 'var(--ps-flag)' }}>
            <Icon name={rec.user.like ? 'heart' : 'x'} size={15} stroke={2.5} /></span>}
        </div>
        <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 8, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{rec.name}</div>
      </figcaption>
    </figure>
  );
}

function IconBtn({ name, onClick, title, danger }) {
  return (
    <button title={title} onClick={onClick} style={{
      width: 32, height: 32, display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      borderRadius: 8, cursor: 'pointer', border: 'none',
      background: 'rgba(12,14,22,.62)', color: danger ? '#ffb4ab' : '#fff', backdropFilter: 'blur(4px)' }}>
      <Icon name={name} size={16} />
    </button>
  );
}

function Dropzone({ drag, setDrag, onFiles, onPick, busy, onRestore }) {
  return (
    <div
      onDragOver={(e) => { e.preventDefault(); setDrag(true); }}
      onDragLeave={() => setDrag(false)}
      onDrop={(e) => { e.preventDefault(); setDrag(false); onFiles(e.dataTransfer.files); }}
      onClick={onPick}
      style={{ cursor: 'pointer', textAlign: 'center', padding: '72px 30px',
        border: `2px dashed ${drag ? 'var(--ps-primary-blue)' : 'var(--ps-line-strong)'}`,
        borderRadius: 20, background: drag ? 'var(--ps-dark-blue-100)' : 'var(--ps-cloud-gray)',
        transition: 'all .18s var(--ease-standard)' }}>
      <div style={{ color: 'var(--ps-primary-blue)', display: 'flex', justifyContent: 'center', marginBottom: 14 }}>
        {busy ? <Spinner size={34} /> : <Icon name="upload" size={40} stroke={1.6} />}
      </div>
      <div style={{ fontSize: 20, fontWeight: 500, color: 'var(--ps-navy)' }}>
        {busy ? `Importing ${busy.done}/${busy.total}…` : 'Drop images here'}
      </div>
      <div style={{ fontSize: 14.5, color: 'var(--fg-2)', marginTop: 8 }}>
        or click to browse — photos, stock, clip-art. They're resized and stored right in your browser.
      </div>
      {!busy && onRestore && (
        <div style={{ fontSize: 13.5, color: 'var(--fg-3)', marginTop: 16 }}>
          Returning?{' '}
          <button onClick={(e) => { e.stopPropagation(); onRestore(); }} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--ps-primary-blue)', fontWeight: 600, fontFamily: 'var(--font-sans)', fontSize: 13.5, padding: 0 }}>Restore a backup file</button>
        </div>
      )}
    </div>
  );
}

window.Library = Library;
