// ============================================================================
// StyleKro — WARDROBE module (split from app.jsx on 2026-06-26).
// WardrobePage + MyLooksPage (+ CatIcon, categorizeWardrobeItem, WARDROBE_*).
// Depends on symbols from common.jsx (loaded first).
// ============================================================================
// ===== My Looks page =====
function MyLooksPage() {
  const { apiCall, t } = useAuth();
  const confirmAction = useConfirmDialog();
  const [looks, setLooks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [zoom, setZoom] = useState(null);
  const [sheet360LookId, setSheet360LookId] = useState(null);
  const fetchLookSheet360 = useCallback(
    () => fetchSheet360(`/merges/${sheet360LookId}/sheet360`),
    [sheet360LookId],
  );
  const [shareOpen, setShareOpen] = useState(null); // look.id with open share menu (now: 'bulk' for top-bar share)
  const [copied, setCopied] = useState(null);
  const [selected, setSelected] = useState(() => new Set()); // selected look ids
  const [compareOpen, setCompareOpen] = useState(false);
  const [search, setSearch] = useState('');
  const [filter, setFilter] = useState('all'); // all | shop | chat
  const [filterShop, setFilterShop] = useState(''); // shop name filter
  const [sort, setSort] = useState('new'); // new | old
  const [view, setView] = useState('grid'); // grid | list
  const [filtersOpen, setFiltersOpen] = useState(false);
  useEffect(() => {
    document.body.classList.toggle('filters-open', filtersOpen);
    return () => document.body.classList.remove('filters-open');
  }, [filtersOpen]);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const data = await apiCall('/merges');
      setLooks(data || []);
    } catch (e) {
      setError(e.message);
    } finally {
      setLoading(false);
    }
  }, [apiCall]);

  useEffect(() => { load(); }, [load]);

  async function remove(id) {
    if (!(await confirmAction(t('looks.deleteOne'), { confirmLabel: t('common.delete'), tone: 'danger' }))) return;
    try {
      await apiCall(`/merges/${id}`, { method: 'DELETE' });
      setLooks((cur) => cur.filter((l) => l.id !== id));
      setSelected((cur) => {
        if (!cur.has(id)) return cur;
        const next = new Set(cur);
        next.delete(id);
        return next;
      });
      if (zoom?.id === id) setZoom(null);
    } catch (e) {
      setError(e.message);
    }
  }

  function toggleSelect(id) {
    setSelected((cur) => {
      const next = new Set(cur);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  }
  function clearSelection() { setSelected(new Set()); }

  async function removeSelected() {
    const ids = Array.from(selected);
    if (ids.length === 0) return;
    if (!(await confirmAction(t('looks.deleteMany').replace('{count}', ids.length).replace('{plural}', ids.length === 1 ? '' : 's'), { confirmLabel: t('common.delete'), tone: 'danger' }))) return;
    const results = await Promise.allSettled(
      ids.map((id) => apiCall(`/merges/${id}`, { method: 'DELETE' }))
    );
    const failed = new Set();
    results.forEach((r, i) => { if (r.status === 'rejected') failed.add(ids[i]); });
    setLooks((cur) => cur.filter((l) => !ids.includes(l.id) || failed.has(l.id)));
    setSelected(failed);
    if (zoom && ids.includes(zoom.id) && !failed.has(zoom.id)) setZoom(null);
    if (failed.size > 0) setError(t('looks.couldNotDelete').replace('{count}', failed.size).replace('{plural}', failed.size === 1 ? '' : 's'));
  }

  function fmtDate(s) {
    if (!s) return '';
    const d = new Date(s.replace(' ', 'T') + (s.endsWith('Z') ? '' : 'Z'));
    if (isNaN(d.getTime())) return s;
    return d.toLocaleString();
  }

  async function copyLink(url, id) {
    try {
      await navigator.clipboard.writeText(url);
      setCopied(id);
      setTimeout(() => setCopied((c) => (c === id ? null : c)), 1800);
    } catch {
      window.prompt('Copy this link:', url);
    }
  }

  async function nativeShare(l, url) {
    const text = `My latest look, styled with AI on StyleKro${l.title ? `: ${l.title}` : ''}`;
    if (navigator.share) {
      try {
        await navigator.share({ title: 'My StyleKro look', text, url });
        return true;
      } catch { /* user cancelled */ }
    }
    return false;
  }

  return (
    <section className="screen">
      <NavBar active="looks" />
      <main className="page-wrap looks-page">
        {(() => {
          const total = looks.length;
          const shopCount = looks.filter((l) => l.source === 'shop').length;
          const chatCount = total - shopCount;
          const q = search.trim().toLowerCase();
          let filtered = looks.filter((l) => {
            if (filter === 'shop' && l.source !== 'shop') return false;
            if (filter === 'chat' && l.source === 'shop') return false;
            if (filterShop && (l.shop_name || '') !== filterShop) return false;
            if (!q) return true;
            return (
              (l.title || '').toLowerCase().includes(q) ||
              (l.shop_name || '').toLowerCase().includes(q)
            );
          });
          filtered = [...filtered].sort((a, b) => {
            const ta = new Date((a.created_at || '').replace(' ', 'T')).getTime() || 0;
            const tb = new Date((b.created_at || '').replace(' ', 'T')).getTime() || 0;
            return sort === 'new' ? tb - ta : ta - tb;
          });
          // Counts for the left-rail filters
          const shopNameCounts = makeCountMap(
            looks.filter((l) => l.source === 'shop' && l.shop_name),
            'shop_name'
          );
          const anyFilter = filter !== 'all' || !!filterShop || !!q;

          return (
            <>
              {error && <p className="error">{error}</p>}

              {loading ? (
                <p className="muted">{t('boot.loading')}</p>
              ) : total === 0 ? (
                <div className="looks-empty">
                  <div className="looks-empty-icon">👗</div>
                  <h3>{t('looks.empty')}</h3>
                  <p className="muted">{t('looks.emptyHint')}</p>
                  <div className="looks-empty-actions">
                    <Link to="/shops" className="btn btn-primary">{t('looks.browseShops')}</Link>
                    <Link to="/chat" className="btn btn-ghost">{t('looks.chatStylist')}</Link>
                  </div>
                </div>
              ) : (
                <div className="inv-layout">
                  <aside className={`inv-rail${filtersOpen ? ' open' : ''}`}>
                    <div className="rail-head">
                      <span className="rail-title">{t('looks.filters')}</span>
                      {anyFilter && (
                        <button type="button" className="rail-clear" onClick={() => { setFilter('all'); setFilterShop(''); setSearch(''); }}>{t('looks.clearAll')}</button>
                      )}
                    </div>

                    <details className="rail-section" open>
                      <summary className="rail-section-title">{t('looks.source')}</summary>
                      <label className="rail-opt">
                        <input type="radio" name="lf-src" checked={filter === 'all'} onChange={() => setFilter('all')} />
                        <span>{t('looks.all')} <span className="rail-count">({total})</span></span>
                      </label>
                      <label className="rail-opt">
                        <input type="radio" name="lf-src" checked={filter === 'shop'} onChange={() => setFilter('shop')} />
                        <span>{t('looks.shops')} <span className="rail-count">({shopCount})</span></span>
                      </label>
                      <label className="rail-opt">
                        <input type="radio" name="lf-src" checked={filter === 'chat'} onChange={() => { setFilter('chat'); setFilterShop(''); }} />
                        <span>{t('looks.chat')} <span className="rail-count">({chatCount})</span></span>
                      </label>
                    </details>

                    {Object.keys(shopNameCounts).length > 0 && filter !== 'chat' && (
                      <details className="rail-section" open>
                        <summary className="rail-section-title">{t('looks.shopsHeader')}</summary>
                        {Object.keys(shopNameCounts).sort().map((name) => (
                          <label key={name} className="rail-opt">
                            <input type="checkbox" checked={filterShop === name} onChange={() => setFilterShop(filterShop === name ? '' : name)} />
                            <span>{name} <span className="rail-count">({shopNameCounts[name]})</span></span>
                          </label>
                        ))}
                      </details>
                    )}

                    <details className="rail-section" open>
                      <summary className="rail-section-title">{t('looks.sort')}</summary>
                      <label className="rail-opt">
                        <input type="radio" name="lf-sort" checked={sort === 'new'} onChange={() => setSort('new')} />
                        <span>{t('looks.newestFirst')}</span>
                      </label>
                      <label className="rail-opt">
                        <input type="radio" name="lf-sort" checked={sort === 'old'} onChange={() => setSort('old')} />
                        <span>{t('looks.oldestFirst')}</span>
                      </label>
                    </details>
                    <div className="rail-footer">
                      <button type="button" className="btn-primary rail-apply-btn" onClick={() => setFiltersOpen(false)}>{t('looks.apply')}</button>
                    </div>
                  </aside>
                  {filtersOpen && <div className="filters-backdrop show" onClick={() => setFiltersOpen(false)} />}

                  <div className="inv-content">
                    <div className="inv-toolbar looks-toolbar-v3">
                      <div className="looks-toolbar-row looks-search-row">
                        <div className="looks-search">
                          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
                          <input
                            type="search"
                            placeholder={t('looks.searchPlaceholder')}
                            value={search}
                            onChange={(e) => setSearch(e.target.value)}
                          />
                        </div>
                        <button
                          type="button"
                          className={`looks-filter-iconbtn${anyFilter ? ' has-active' : ''}`}
                          onClick={() => setFiltersOpen(true)}
                          aria-label="Open filters"
                          title="Filters"
                        >
                          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><line x1="4" y1="6" x2="20" y2="6"/><line x1="7" y1="12" x2="17" y2="12"/><line x1="10" y1="18" x2="14" y2="18"/></svg>
                          {anyFilter && <span className="looks-filter-dot" />}
                        </button>
                      </div>
                    </div>

                    {selected.size > 0 && (() => {
                      const selectedLooks = filtered.filter((l) => selected.has(l.id));
                      const first = selectedLooks[0];
                      const firstUrl = first ? imgUrl(first.image_url) : '';
                      const titles = selectedLooks
                        .map((l) => l.title)
                        .filter(Boolean)
                        .slice(0, 3)
                        .join(', ');
                      const shareText = encodeURIComponent(
                        `My latest looks, styled with AI on StyleKro${titles ? `: ${titles}` : ''}`
                      );
                      const u = encodeURIComponent(firstUrl);
                      const isOpen = shareOpen === 'bulk';
                      return (
                        <div className="select-bar" role="toolbar" aria-label="Selection actions">
                          <div className="select-bar-info">
                            <button type="button" className="select-bar-clear" onClick={clearSelection} aria-label="Clear selection">✕</button>
                            <span>{selected.size} {t('looks.selected')}</span>
                          </div>
                          <div className="select-bar-actions">
                            <button
                              type="button"
                              className="sel-btn"
                              title="Share selected"
                              aria-label="Share selected"
                              onClick={async () => {
                                if (!first) return;
                                if (selected.size === 1) {
                                  const ok = await nativeShare(first, firstUrl);
                                  if (!ok) setShareOpen(isOpen ? null : 'bulk');
                                } else {
                                  const urls = selectedLooks.map((l) => imgUrl(l.image_url)).join('\n');
                                  if (navigator.share) {
                                    try {
                                      await navigator.share({ title: 'My StyleKro looks', text: `My latest looks, styled with AI on StyleKro:\n${urls}` });
                                      return;
                                    } catch { /* cancelled */ }
                                  }
                                  setShareOpen(isOpen ? null : 'bulk');
                                }
                              }}
                            >
                              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/><polyline points="16 6 12 2 8 6"/><line x1="12" y1="2" x2="12" y2="15"/></svg>
                              <span className="sel-btn-label">{t('looks.share')}</span>
                            </button>
                            <button type="button" className="sel-btn sel-btn-danger" onClick={removeSelected} title="Delete selected" aria-label="Delete selected">
                              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-2 14a2 2 0 0 1-2 2H9a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/></svg>
                              <span className="sel-btn-label">{t('looks.delete')}</span>
                            </button>
                            {selected.size >= 2 && (
                              <button
                                type="button"
                                className="sel-btn sel-btn-primary compare-btn"
                                onClick={() => setCompareOpen(true)}
                                title="Compare selected looks side by side"
                                aria-label="Compare selected looks"
                              >
                                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
                                <span className="sel-btn-label">{t('looks.compare')}</span>
                              </button>
                            )}
                            {isOpen && first && (
                              <div className="share-menu" onMouseLeave={() => setShareOpen(null)}>
                                <a href={`https://twitter.com/intent/tweet?text=${shareText}&url=${u}`} target="_blank" rel="noreferrer">𝕏 / Twitter</a>
                                <a href={`https://www.facebook.com/sharer/sharer.php?u=${u}`} target="_blank" rel="noreferrer">Facebook</a>
                                <a href={`https://api.whatsapp.com/send?text=${shareText}%20${u}`} target="_blank" rel="noreferrer">WhatsApp</a>
                                <a href={`https://www.linkedin.com/sharing/share-offsite/?url=${u}`} target="_blank" rel="noreferrer">LinkedIn</a>
                                <a href={`https://www.pinterest.com/pin/create/button/?url=${u}&media=${u}&description=${shareText}`} target="_blank" rel="noreferrer">Pinterest</a>
                                <a href={`https://t.me/share/url?url=${u}&text=${shareText}`} target="_blank" rel="noreferrer">Telegram</a>
                                <button type="button" onClick={() => copyLink(firstUrl, 'bulk')}>
                                  {copied === 'bulk' ? t('shop.copied') : t('looks.copyLink')}
                                </button>
                              </div>
                            )}
                          </div>
                        </div>
                      );
                    })()}
                    {filtered.length === 0 ? (
                      <p className="muted" style={{ marginTop: 24 }}>{t('looks.noMatching')}</p>
                    ) : view === 'grid' ? (
                    <div className="looks-grid">
                      {filtered.map((l) => {
                        const shareUrl = imgUrl(l.image_url);
                        const isSelected = selected.has(l.id);
                        const inSelectMode = selected.size > 0;
                        return (
                          <article key={l.id} className={`look-card${isSelected ? ' selected' : ''}`}>
                            <div
                              className="look-photo"
                              onClick={() => {
                                if (inSelectMode) toggleSelect(l.id);
                                else setZoom(l);
                              }}
                            >
                              <img src={shareUrl} alt={l.title || 'Look'} loading="lazy" />
                              <span className={`source-badge ${l.source === 'shop' ? 'shop' : 'chat'}`}>
                                {l.source === 'shop' ? '🛍 Shop' : '💬 Chat'}
                              </span>
                              <button
                                type="button"
                                className={`look-select${isSelected ? ' on' : ''}`}
                                aria-label={isSelected ? 'Deselect look' : 'Select look'}
                                aria-pressed={isSelected}
                                onClick={(e) => { e.stopPropagation(); toggleSelect(l.id); }}
                              >
                                {isSelected ? '✓' : ''}
                              </button>
                              <div className="look-photo-overlay">
                                <span className="look-zoom-hint">{inSelectMode ? (isSelected ? '' : 'Tap to select') : 'Click to view'}</span>
                              </div>
                              <ImageFeedback mergeId={l.id} compact />
                            </div>
                            <div className="look-body">
                              <h4 className="look-title">{l.title || 'Try-on'}</h4>
                              <div className="look-meta">
                                {l.source === 'shop' && l.shop_id ? (
                                  <Link to={`/shops/${l.shop_id}`}>{l.shop_name || 'shop'}</Link>
                                ) : l.source === 'chat' ? (
                                  <Link to="/chat">{t('looks.stylistChat')}</Link>
                                ) : null}
                              </div>
                            </div>
                          </article>
                        );
                      })}
                    </div>
                  ) : (
                    <div className="looks-list">
                      {filtered.map((l) => {
                        const shareUrl = imgUrl(l.image_url);
                        const isSelected = selected.has(l.id);
                        const inSelectMode = selected.size > 0;
                        return (
                          <div key={l.id} className={`look-row${isSelected ? ' selected' : ''}`}>
                            <button
                              type="button"
                              className={`look-select inline${isSelected ? ' on' : ''}`}
                              aria-label={isSelected ? 'Deselect look' : 'Select look'}
                              aria-pressed={isSelected}
                              onClick={() => toggleSelect(l.id)}
                            >
                              {isSelected ? '✓' : ''}
                            </button>
                            <img
                              className="look-row-thumb"
                              src={shareUrl}
                              alt=""
                              loading="lazy"
                              decoding="async"
                              onClick={() => {
                                if (inSelectMode) toggleSelect(l.id);
                                else setZoom(l);
                              }}
                            />
                            <div className="look-row-info">
                              <div className="look-row-title">
                                {l.title || 'Try-on'}
                                <span className={`source-pill ${l.source === 'shop' ? 'shop' : 'chat'}`}>
                                  {l.source === 'shop' ? 'Shop' : 'Chat'}
                                </span>
                              </div>
                              {l.source === 'shop' && l.shop_id ? (
                                <div className="look-meta">
                                  <Link to={`/shops/${l.shop_id}`}>{l.shop_name || 'shop'}</Link>
                                </div>
                              ) : null}
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  )}
                  </div>
                </div>
              )}
            </>
          );
        })()}
        {zoom && (
          <div className="tryon-modal" onClick={() => setZoom(null)}>
            <div className="tryon-card" onClick={(e) => e.stopPropagation()}>
              <button className="tryon-close" onClick={() => setZoom(null)}>✕</button>
              <div className="eyebrow">{t('looks.savedLook')}</div>
              <h3>{zoom.title || 'Try-on'}</h3>
              <img src={imgUrl(zoom.image_url)} alt="" />
              <button
                type="button"
                className="bi-cta-secondary"
                style={{ marginTop: 10 }}
                onClick={() => setSheet360LookId(zoom.id)}
              >
                {t('item.view360')}
              </button>
            </div>
          </div>
        )}
        <Sheet360Modal
          open={!!sheet360LookId}
          fetchSheet={fetchLookSheet360}
          onClose={() => setSheet360LookId(null)}
        />
        {compareOpen && (() => {
          const items = looks.filter((l) => selected.has(l.id)).slice(0, 4);
          if (items.length < 2) return null;
          return (
            <div className="tryon-modal compare-modal" onClick={() => setCompareOpen(false)}>
              <div className="compare-card" onClick={(e) => e.stopPropagation()}>
                <button className="tryon-close" onClick={() => setCompareOpen(false)} aria-label="Close compare">✕</button>
                <div className="eyebrow">{t('compare.sideBySide')}</div>
                <h3>{t('compare.compareLooks')}</h3>
                <div className={`compare-grid cols-${items.length}`}>
                  {items.map((l) => (
                    <figure key={l.id} className="compare-item">
                      <img src={imgUrl(l.image_url)} alt={l.title || 'Look'} />
                      <figcaption>
                        <strong>{l.title || 'Try-on'}</strong>
                        <span className="muted">{fmtDate(l.created_at)}</span>
                      </figcaption>
                    </figure>
                  ))}
                </div>
                {selected.size > 4 && (
                  <p className="muted compare-note">{t('compare.showingPrefix')} {selected.size} {t('compare.showingSuffix')}</p>
                )}
              </div>
            </div>
          );
        })()}
      </main>
    </section>
  );
}

// ===== AI Wardrobe Page =====
const CatIcon = ({ name }) => {
  const common = { width: 26, height: 26, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch (name) {
    case 'all':
      return (<svg {...common}><rect x="3" y="3" width="7" height="7" rx="1.5"/><rect x="14" y="3" width="7" height="7" rx="1.5"/><rect x="3" y="14" width="7" height="7" rx="1.5"/><rect x="14" y="14" width="7" height="7" rx="1.5"/></svg>);
    case 'Topwear':
      return (<svg {...common}><path d="M7 4l-4 3 2 4 2-1v10h10V10l2 1 2-4-4-3-2 2a3 3 0 0 1-6 0z"/></svg>);
    case 'Bottomwear':
      return (<svg {...common}><path d="M6 3h12l1 6-3 12h-3l-2-9h-1l-2 9H5L2 9z"/></svg>);
    case 'Dresses':
      return (<svg {...common}><path d="M9 3h6l1 4-2 2 4 12H6l4-12-2-2z"/></svg>);
    case 'Outerwear':
      return (<svg {...common}><path d="M7 3l5 3 5-3 4 4-3 3v11h-5v-7h-2v7H6V10L3 7z"/><path d="M12 6v15"/></svg>);
    case 'Footwear':
      return (<svg {...common}><path d="M3 14c0-1 1-2 2-2h2l3-5 5 1 2 4 5 2c1 .3 2 1 2 2v2H3z"/><path d="M3 18h18"/></svg>);
    case 'Bags':
      return (<svg {...common}><path d="M5 8h14l-1 12H6z"/><path d="M9 8V6a3 3 0 0 1 6 0v2"/></svg>);
    case 'Accessories':
      return (<svg {...common}><circle cx="8" cy="14" r="4"/><circle cx="16" cy="14" r="4"/><path d="M8 10V6h8v4"/></svg>);
    case 'Others':
      return (<svg {...common}><circle cx="6" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="18" cy="12" r="1.5"/></svg>);
    default:
      return null;
  }
};

const WARDROBE_CATEGORIES = [
  { key: 'Topwear',     label: 'Tops',       match: ['topwear', 't-shirt', 'shirt', 'tops', 'kurti', 'blouse', 'hoodie', 'sweater', 'jacket', 'kurta'] },
  { key: 'Bottomwear',  label: 'Bottoms',    match: ['bottomwear', 'jeans', 'trousers', 'shorts', 'leggings', 'skirts', 'pants', 'palazzo', 'chinos'] },
  { key: 'Dresses',     label: 'Dresses',    match: ['dresses', 'gowns', 'sarees', 'salwar', 'lehenga', 'ethnic'] },
  { key: 'Outerwear',   label: 'Outerwear',  match: ['outerwear', 'jacket', 'coat', 'blazer'] },
  { key: 'Footwear',    label: 'Shoes',      match: ['footwear', 'sneakers', 'shoes', 'heels', 'sandals', 'boots', 'flats'] },
  { key: 'Bags',        label: 'Bags',       match: ['handbag', 'bag', 'backpack', 'wallet'] },
  { key: 'Accessories', label: 'Accessories',match: ['accessories', 'watch', 'belt', 'sunglasses', 'jewellery', 'scarf', 'hat', 'cap', 'tie', 'socks'] },
  { key: 'Others',      label: 'Others',     match: [] },
];

const WARDROBE_RECOMMENDATIONS = [
  { key: 'brunch',  title: 'Brunch Date',    sub: 'Light, airy, photo-ready', emoji: '☕' },
  { key: 'work',    title: 'Work Meeting',   sub: 'Sharp & confident',        emoji: '💼' },
  { key: 'evening', title: 'Evening Out',    sub: 'Polished after dark',      emoji: '🌙' },
  { key: 'weekend', title: 'Weekend Vibes',  sub: 'Effortless casual',        emoji: '✨' },
  { key: 'party',   title: 'Party Night',    sub: 'Bold statement',           emoji: '🎉' },
  { key: 'travel',  title: 'Travel Day',     sub: 'Comfy yet styled',         emoji: '🧳' },
];

function categorizeWardrobeItem(item) {
  const hay = `${item.group || ''} ${item.subcategory || ''} ${item.title || ''}`.toLowerCase();
  for (const cat of WARDROBE_CATEGORIES) {
    if (cat.match.length && cat.match.some((m) => hay.includes(m))) return cat.key;
  }
  return 'Others';
}

function WardrobePage() {
  const { apiCall, token, t } = useAuth();
  const confirmAction = useConfirmDialog();
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(false);
  const [uploadProgress, setUploadProgress] = useState({ current: 0, total: 0 });
  const [error, setError] = useState('');
  const [activeCat, setActiveCat] = useState('all');
  const [selected, setSelected] = useState([]);            // array of item ids
  const [generating, setGenerating] = useState(false);
  const [outfit, setOutfit] = useState(null);              // { image_url, title, match }
  const [occasion, setOccasion] = useState('');
  const [lightbox, setLightbox] = useState(null);          // url string when zoomed
  const fileRef = useRef(null);

  const load = useCallback(async () => {
    try {
      setLoading(true);
      const data = await apiCall('/wardrobe');
      setItems(Array.isArray(data) ? data : []);
    } catch (e) {
      setError(errMsg(e));
    } finally {
      setLoading(false);
    }
  }, [apiCall]);

  useEffect(() => { load(); }, [load]);

  async function onUpload(e) {
    const files = Array.from(e.target.files || []);
    if (!files.length) return;
    setUploading(true);
    setUploadProgress({ current: 0, total: files.length });
    setError('');
    try {
      let done = 0;
      for (const f of files) {
        setUploadProgress({ current: done + 1, total: files.length });
        const fd = new FormData();
        fd.append('photo', f);
        const created = await apiCall('/wardrobe', { method: 'POST', body: fd });
        setItems((prev) => [created, ...prev]);
        done += 1;
      }
    } catch (err) {
      setError(errMsg(err));
    } finally {
      setUploading(false);
      setUploadProgress({ current: 0, total: 0 });
      if (fileRef.current) fileRef.current.value = '';
    }
  }

  function toggleSelect(id) {
    setSelected((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : (prev.length >= 6 ? prev : [...prev, id]));
  }

  async function removeItem(id) {
    if (!(await confirmAction(t('wardrobe.confirmRemove'), { confirmLabel: t('common.delete'), tone: 'danger' }))) return;
    try {
      await apiCall(`/wardrobe/${id}`, { method: 'DELETE' });
      setItems((prev) => prev.filter((x) => x.id !== id));
      setSelected((prev) => prev.filter((x) => x !== id));
    } catch (err) {
      setError(errMsg(err));
    }
  }

  async function generateOutfit(occLabel) {
    if (!selected.length) {
      setError(t('wardrobe.pickOne'));
      return;
    }
    setError('');
    setGenerating(true);
    setOutfit(null);
    const titleLabel = occLabel || occasion || 'Clean & Casual';
    const match = Math.min(99, 78 + selected.length * 3);
    const pickedItems = items.filter((it) => selected.includes(it.id));
    try {
      const body = JSON.stringify({ item_ids: selected, occasion: occLabel || occasion || null });
      let gotFinal = false;
      await streamSSE('/wardrobe/outfit/stream', {
        body,
        token,
        headers: { 'Content-Type': 'application/json' },
        onEvent: (evt, data) => {
          if (evt === 'tryon_fast') {
            setOutfit({
              image_url: imgUrl(data.image_url),
              title: titleLabel,
              match,
              items: pickedItems,
              pending: true,
            });
          } else if (evt === 'tryon_final') {
            gotFinal = true;
            setOutfit({
              image_url: imgUrl(data.image_url),
              title: titleLabel,
              match,
              items: pickedItems,
              pending: false,
            });
          } else if (evt === 'tryon_error') {
            setError(data.detail || 'Try-on failed');
          }
        },
      });
      if (!gotFinal) setGenerating(false);
    } catch (err) {
      setError(errMsg(err));
    } finally {
      setGenerating(false);
    }
  }

  const itemsByCat = {};
  for (const it of items) {
    const k = categorizeWardrobeItem(it);
    (itemsByCat[k] = itemsByCat[k] || []).push(it);
  }
  const filteredItems = activeCat === 'all' ? items : (itemsByCat[activeCat] || []);
  const selectedItems = items.filter((it) => selected.includes(it.id));

  return (
    <section className="screen wardrobe-page">
      <NavBar active="wardrobe" />
      <main className="wardrobe-main">
        {error && <div className="wardrobe-error">{error}</div>}

        {/* === Upload card === */}
        <div className={`wardrobe-upload${uploading ? ' is-uploading' : ''}`} aria-busy={uploading || undefined}>
          <label className={`wardrobe-upload-card${uploading ? ' is-uploading' : ''}`}>
            <input
              ref={fileRef}
              type="file"
              accept="image/*"
              multiple
              hidden
              onChange={onUpload}
              disabled={uploading}
            />
            <div className="wardrobe-upload-icon" aria-hidden>
              {uploading ? (
                <span className="spinner" style={{ width: 24, height: 24, borderWidth: 3, margin: 0 }} />
              ) : (
                <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
              )}
            </div>
            <div className="wardrobe-upload-text">
              <strong>
                {uploading
                  ? (uploadProgress.total > 1
                      ? `${t('wardrobe.uploading')} ${uploadProgress.current}/${uploadProgress.total}`
                      : t('wardrobe.uploading'))
                  : t('wardrobe.addClothing')}
              </strong>
              <span>{t('wardrobe.uploadSubtitle')}</span>
            </div>
          </label>
          <label className={`wardrobe-upload-camera${uploading ? ' is-uploading' : ''}`} title="Use camera">
            <input type="file" accept="image/*" capture="environment" hidden onChange={onUpload} disabled={uploading} />
            {uploading ? (
              <span className="spinner" style={{ margin: 0 }} />
            ) : (
              <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
            )}
          </label>
        </div>

        {/* === Categories === */}
        <section className="wardrobe-cats-card">
          <header className="wardrobe-cats-head">
            <div className="wardrobe-cats-title">
              <span className="wardrobe-cats-spark" aria-hidden>✦</span>
              <div>
                <h2>{t('wardrobe.category')}</h2>
              </div>
            </div>
            <span className="wardrobe-cats-pill">{items.length} {items.length === 1 ? t('wardrobe.items') : t('wardrobe.itemsPlural')}</span>
          </header>
          <div className="wardrobe-cats">
            <button
              type="button"
              className={`wardrobe-cat${activeCat === 'all' ? ' active' : ''}`}
              onClick={() => setActiveCat('all')}
            >
              <div className="wardrobe-cat-icon"><CatIcon name="all" /></div>
              <div className="wardrobe-cat-foot">
                <span className="wardrobe-cat-label">{t('wardrobe.all')}</span>
                <span className="wardrobe-cat-dash" aria-hidden />
                <span className="wardrobe-cat-count">{items.length}</span>
              </div>
            </button>
            {(() => {
              // rank top 3 non-empty cats for badges
              const ranked = [...WARDROBE_CATEGORIES]
                .map((c) => ({ key: c.key, n: (itemsByCat[c.key] || []).length }))
                .filter((c) => c.n > 0)
                .sort((a, b) => b.n - a.n);
              const badgeFor = (key) => {
                const idx = ranked.findIndex((r) => r.key === key);
                if (idx === 0) return 'Most Worn';
                if (idx === 1) return 'Trending';
                if (idx === 2) return 'New';
                return null;
              };
              return WARDROBE_CATEGORIES.map((cat) => {
                const list = itemsByCat[cat.key] || [];
                const badge = badgeFor(cat.key);
                return (
                  <button
                    key={cat.key}
                    type="button"
                    className={`wardrobe-cat${activeCat === cat.key ? ' active' : ''}`}
                    onClick={() => setActiveCat(cat.key)}
                  >
                    {badge && <span className={`wardrobe-cat-badge badge-${badge.toLowerCase().replace(/\s+/g,'-')}`}>{badge}</span>}
                    <div className="wardrobe-cat-icon"><CatIcon name={cat.key} /></div>
                    <div className="wardrobe-cat-foot">
                      <span className="wardrobe-cat-label">{cat.label}</span>
                      <span className="wardrobe-cat-dash" aria-hidden />
                      <span className="wardrobe-cat-count">{list.length}</span>
                    </div>
                  </button>
                );
              });
            })()}
          </div>
        </section>

        {/* === Item grid === */}
        {loading ? (
          <div className="wardrobe-loading">{t('wardrobe.loading')}</div>
        ) : filteredItems.length === 0 ? (
          <div className="wardrobe-empty">
            <div className="wardrobe-empty-icon" aria-hidden>
              <svg width="44" height="44" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M7 4l-4 3 2 4 2-1v10h10V10l2 1 2-4-4-3-2 2a3 3 0 0 1-6 0z"/></svg>
            </div>
            <h3>{activeCat === 'all' ? t('wardrobe.empty') : `No ${activeCat} yet`}</h3>
            <p>{activeCat === 'all' ? t('wardrobe.emptyHint') : 'Upload to start building this category.'}</p>
            <button
              type="button"
              className="wardrobe-empty-btn"
              onClick={() => fileRef.current && fileRef.current.click()}
              disabled={uploading}
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
              {t('wardrobe.uploadNow')}
            </button>
          </div>
        ) : (
          <div className="wardrobe-grid">
            {filteredItems.map((it) => {
              const isSel = selected.includes(it.id);
              return (
                <div key={it.id} className={`wardrobe-item${isSel ? ' selected' : ''}`}>
                  <button type="button" className="wardrobe-item-photo" onClick={() => toggleSelect(it.id)}>
                    <img src={imgUrl(it.photo_url)} alt={it.title || ''} />
                    <span className="wardrobe-item-check" aria-hidden>{isSel ? '✓' : '+'}</span>
                  </button>
                  <div className="wardrobe-item-meta">
                    {(() => {
                      const primary = it.title || it.subcategory || 'Item';
                      const secondary = it.subcategory || it.group || '';
                      const showSecondary = secondary && secondary.toLowerCase() !== primary.toLowerCase();
                      return (
                        <>
                          <strong>{primary}</strong>
                          {showSecondary && <small>{secondary}</small>}
                        </>
                      );
                    })()}
                  </div>
                  <button type="button" className="wardrobe-item-del" onClick={() => removeItem(it.id)} title="Remove">×</button>
                </div>
              );
            })}
          </div>
        )}

        {/* === Floating Try On bar === */}
        {selected.length > 0 && (
          <div className="wardrobe-fab-bar" role="region" aria-label="Stylekro actions">
            <span className="wardrobe-fab-count">{selected.length}</span>
            <StyleKroButton
              busy={generating}
              busyLabel={t('wardrobe.loadingBtn')}
              disabled={generating}
              label={outfit ? 'Style New' : undefined}
              onClick={() => generateOutfit('')}
            />
          </div>
        )}

        {/* === AI Recommendation card === */}
        {(outfit || generating) && (
          <div className="wardrobe-rec-card">
            <div className="wardrobe-rec-photo">
              {generating && !outfit && <div className="wardrobe-rec-loader"><TryonProgress label={t('wardrobe.dressingUp')} /></div>}
              {outfit && (
                <img
                  src={outfit.image_url}
                  alt="Generated outfit"
                  style={{ cursor: 'zoom-in' }}
                  onClick={() => setLightbox(outfit.image_url)}
                  title="Click to zoom"
                />
              )}
              {outfit?.pending && (
                <div className="upgrade-hint upgrade-hint-floating">
                  <span className="upgrade-hint-spinner" aria-hidden="true" />
                  <span className="upgrade-hint-title">{t('chat.refiningLook')}</span>
                </div>
              )}
            </div>
          </div>
        )}
        {lightbox && (
          <div className="lightbox" onClick={() => setLightbox(null)}>
            <button className="lightbox-close" title="Close">×</button>
            <ZoomableImage src={lightbox} />
            <LightboxActions url={lightbox} filename="stylekro-outfit.png" />
          </div>
        )}
      </main>
    </section>
  );
}
