// Lists Library — gallery of curated list templates, plus a full-page
// preview that renders any template AS IF it were a real list (using the
// same list2-* visual language as the live list editor). Adoption is a
// separate explicit action: card-level "Add to my lists" button, OR
// "Add to my lists" CTA inside the preview page.

const { useState: _lle, useEffect: _llef, useMemo: _llm } = React;

// ─────────────────────── Template helpers ───────────────────────
function getAllListTemplates() {
  const stageTemplates = Object.values(window.ESSENTIALS_BY_STAGE || {}).map(stage => {
    const items = stage.sections.flatMap(section =>
      section.items.map(it => ({ ...it, category: section.id }))
    );
    return {
      id: `essentials-${stage.key}`,
      name: `${stage.label} essentials`,
      blurb: stage.sub,
      eyebrow: `${stage.label} · essentials`,
      ageBand: stage.key === 'pre' ? 'pre'
             : stage.key === '0-6m' || stage.key === '6-12m' ? '0-1'
             : stage.key === '1-2y' ? '1-3'
             : stage.key === '3-4y' ? '3-5'
             : stage.key === '5+' ? '5-8'
             : 'any',
      type: 'essentials',
      iconKey: '⭐',
      _sourceStage: stage.key,
      _sourceData: stage,
      items,
    };
  });
  return [...stageTemplates, ...(window.LIST_TEMPLATES || [])];
}

// Normalise a template into a single tree we can render. Flat templates
// get the retroactive F treatment (1 product → item, 2+ → shortlist).
function normaliseTemplateToTree(template) {
  if (Array.isArray(template.tree) && template.tree.length > 0) return template.tree;
  return (template.items || [])
    .filter(it => (it.productIds || []).length > 0)
    .map(it => {
      const ids = it.productIds || [];
      return ids.length === 1
        ? { type: 'item',      label: it.label, productIds: ids, necessity: it.necessity, blurb: it.blurb }
        : { type: 'shortlist', label: it.label, productIds: ids, necessity: it.necessity, blurb: it.blurb };
    });
}

// Up to N product objects pulled from a template — used for the hero
// strip on library cards. Prefers shortlist candidates first.
function templatePreviewProducts(t, limit = 5) {
  const map = {};
  (window.PRODUCTS || []).forEach(p => { map[p.id] = p; });
  const seen = new Set();
  const out = [];
  const push = (pid) => {
    if (!pid || seen.has(pid) || out.length >= limit) return;
    const p = map[pid];
    if (!p) return;
    seen.add(pid);
    out.push(p);
  };
  const walk = (nodes) => {
    (nodes || []).forEach(n => {
      if (n.type === 'shortlist') (n.productIds || []).forEach(push);
      else if (n.type === 'item')  push((n.productIds || [])[0]);
      else if (n.type === 'group' && Array.isArray(n.children)) walk(n.children);
    });
  };
  if (Array.isArray(t.tree)) walk(t.tree);
  if (out.length < limit) {
    (t.items || []).forEach(it => (it.productIds || []).forEach(push));
  }
  return out;
}

// Count nodes — handles both shapes. Returns a short summary string.
function templateSummary(t) {
  let items = 0, shortlists = 0, groups = 0;
  const walk = (nodes) => {
    (nodes || []).forEach(n => {
      if (n.type === 'item')      items++;
      else if (n.type === 'shortlist') { shortlists++; items += (n.productIds || []).length; }
      else if (n.type === 'group') { groups++; walk(n.children); }
    });
  };
  if (Array.isArray(t.tree)) walk(t.tree);
  if (Array.isArray(t.items) && (!Array.isArray(t.tree) || t.tree.length === 0)) {
    t.items.forEach(it => {
      const ids = it.productIds || [];
      if (ids.length === 0) return;
      if (ids.length === 1) items++;
      else { shortlists++; items += ids.length; }
    });
  }
  const parts = [];
  if (items > 0)       parts.push(`${items} item${items === 1 ? '' : 's'}`);
  if (shortlists > 0)  parts.push(`${shortlists} shortlist${shortlists === 1 ? '' : 's'}`);
  if (groups > 0)      parts.push(`${groups} group${groups === 1 ? '' : 's'}`);
  return parts.join(' · ') || 'Empty';
}

// ─────────────────────── Library gallery page ───────────────────────
function ListLibraryPage({ audience, stage, userLists, onAdoptOne, onAdoptMany, onOpenProduct, onPreviewTemplate }) {
  const allTemplates = _llm(() => getAllListTemplates(), [audience, stage]);
  const [ageBand, setAgeBand] = _lle('any');
  const [type, setType] = _lle('all');
  const [selected, setSelected] = _lle(() => new Set());

  const adoptedNames = _llm(() => {
    const s = new Set();
    (userLists || []).forEach(l => { if (l.isMine !== false) s.add(l.name); });
    return s;
  }, [userLists]);

  const canonicalName = (t) => t._sourceData ? `${t._sourceData.label} essentials` : t.name;
  const isAdopted = (t) => adoptedNames.has(canonicalName(t));

  const filtered = _llm(() => allTemplates.filter(t => {
    if (ageBand !== 'any' && t.ageBand !== ageBand && t.ageBand !== 'any') return false;
    if (type !== 'all' && t.type !== type) return false;
    return true;
  }), [allTemplates, ageBand, type]);

  const toggle = (id) => setSelected(prev => {
    const next = new Set(prev);
    if (next.has(id)) next.delete(id); else next.add(id);
    return next;
  });

  _llef(() => {
    if (typeof window.resolveTemplateProducts === 'function') {
      window.resolveTemplateProducts();
    }
  }, []);

  const adoptSelected = () => {
    const picks = allTemplates.filter(t => selected.has(t.id) && !isAdopted(t));
    if (picks.length === 0) return;
    onAdoptMany(picks);
    setSelected(new Set());
  };

  return (
    <div className="page list-library-page">
      <div className="page-head">
        <div>
          <div className="page-eyebrow">Lists Library</div>
          <h1 className="page-title">Starter lists, <em><Whimsy text="ready to adopt" />.</em></h1>
          <p className="page-sub">
            Tap a card to <strong>view the list</strong> — you'll see everything inside, just like an
            actual list. Check the box on multiple cards to bulk-add. Or use the per-card
            <strong> Add to my lists</strong> button.
          </p>
        </div>
      </div>

      {/* Filter rail */}
      <div className="library-filter-bar">
        <div className="library-filter-group">
          <span className="library-filter-lbl">Stage</span>
          {(window.LIST_TEMPLATE_AGE_BANDS || []).map(b => (
            <button
              key={b.value}
              type="button"
              className={`library-filter-chip${ageBand === b.value ? ' is-on' : ''}`}
              onClick={() => setAgeBand(b.value)}
            >{b.label}</button>
          ))}
        </div>
        <div className="library-filter-group">
          <span className="library-filter-lbl">Type</span>
          <button
            type="button"
            className={`library-filter-chip${type === 'all' ? ' is-on' : ''}`}
            onClick={() => setType('all')}
          >All</button>
          {(window.LIST_TEMPLATE_TYPES || []).map(t => (
            <button
              key={t.value}
              type="button"
              className={`library-filter-chip${type === t.value ? ' is-on' : ''}`}
              onClick={() => setType(t.value)}
            >{t.label}</button>
          ))}
        </div>
      </div>

      <div className="library-grid library-grid--big">
        {filtered.map(t => {
          const adopted = isAdopted(t);
          const checked = selected.has(t.id);
          const previews = templatePreviewProducts(t, 5);
          return (
            <LibraryCard
              key={t.id}
              template={t}
              adopted={adopted}
              checked={checked}
              previews={previews}
              onToggleSelect={() => toggle(t.id)}
              onPreview={() => onPreviewTemplate(t.id)}
              onAdoptDirect={() => onAdoptOne(t)}
            />
          );
        })}
      </div>

      {filtered.length === 0 && (
        <div className="empty" style={{ marginTop: 24 }}>
          <h3 className="empty-title">Nothing matches that filter</h3>
          <p>Try a different stage or list type.</p>
        </div>
      )}

      {/* Sticky bulk action bar */}
      {(() => {
        const newSelected = filtered.filter(t => selected.has(t.id) && !isAdopted(t));
        if (newSelected.length === 0) return null;
        return (
          <div className="library-stickybar" role="region" aria-label="Bulk add to my lists">
            <div className="library-stickybar-info">
              <span className="library-stickybar-count">{newSelected.length}</span>
              <span className="library-stickybar-label">
                list{newSelected.length === 1 ? '' : 's'} selected
              </span>
            </div>
            <button
              type="button"
              className="btn btn-ghost"
              onClick={() => setSelected(new Set())}
              style={{ width: 'auto', padding: '10px 16px' }}
            >Clear</button>
            <button
              type="button"
              className="btn"
              onClick={adoptSelected}
              style={{ width: 'auto', padding: '12px 22px' }}
            >
              <span>Add {newSelected.length} to my lists</span>
              <span className="arrow">→</span>
            </button>
          </div>
        );
      })()}
    </div>
  );
}

// ─────────────────────── Library card ───────────────────────
function LibraryCard({ template, adopted, checked, previews, onToggleSelect, onPreview, onAdoptDirect }) {
  const t = template;
  const summary = templateSummary(t);
  return (
    <article className={`library-card library-card--big${adopted ? ' is-adopted' : ''}${checked ? ' is-selected' : ''}`}>
      <button
        type="button"
        className={`library-card-check${checked ? ' is-on' : ''}`}
        onClick={(e) => { e.stopPropagation(); onToggleSelect(); }}
        aria-checked={checked}
        role="checkbox"
        aria-label={checked ? 'Deselect this list' : 'Select this list'}
        title={checked ? 'Deselect' : 'Select for bulk add'}
      >
        {checked && (
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 7"/></svg>
        )}
      </button>

      <button
        type="button"
        className="library-card-hero"
        onClick={onPreview}
        aria-label={`View ${t.name}`}
      >
        {previews.length > 0 ? (
          <div className="library-card-imgrow">
            {previews.map((p, i) => (
              <div key={p.id || i} className="library-card-imgrow-thumb">
                <SmartImage src={p.img} alt={p.name} fallbackLabel={p.brand || p.name} />
              </div>
            ))}
          </div>
        ) : (
          <div className="library-card-iconwrap">
            <span className="library-card-iconbig" aria-hidden="true">{t.iconKey || '⭐'}</span>
          </div>
        )}
      </button>

      <button
        type="button"
        className="library-card-body"
        onClick={onPreview}
      >
        <div className="library-card-eyebrow">{t.eyebrow || `${t.ageBand} · ${t.type}`}</div>
        <h3 className="library-card-name">{t.name}</h3>
        <p className="library-card-blurb">{t.blurb}</p>
        <div className="library-card-summary">{summary}</div>
      </button>

      <div className="library-card-foot">
        <button
          type="button"
          className="library-card-preview-cta"
          onClick={onPreview}
        >
          <span>View list</span>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><path d="M9 6l6 6-6 6"/></svg>
        </button>
        {adopted ? (
          <button
            type="button"
            className="library-card-add library-card-add--open"
            onClick={(e) => { e.stopPropagation(); onAdoptDirect(); }}
          >
            <span>Open in My lists</span>
            <span className="arrow">↗</span>
          </button>
        ) : (
          <button
            type="button"
            className="library-card-add"
            onClick={(e) => { e.stopPropagation(); onAdoptDirect(); }}
          >
            <span>Add to my lists</span>
            <span className="arrow">→</span>
          </button>
        )}
      </div>

      {adopted && <span className="library-card-adopted-flag">✓ Already added</span>}
    </article>
  );
}

// ─────────────────────── Template preview page (full route) ───────────────────────
// Renders any template as if it were a real list — same list2-* visual
// language as the live list editor. The user gets the proper list form
// they want to inspect before deciding to adopt. Read-only.
function TemplatePreviewPage({ templateId, userLists, onBack, onAdopt, onOpenProduct }) {
  const allTemplates = _llm(() => getAllListTemplates(), []);
  const template = _llm(() => allTemplates.find(t => t.id === templateId) || null, [allTemplates, templateId]);

  _llef(() => {
    if (typeof window.resolveTemplateProducts === 'function') {
      window.resolveTemplateProducts();
    }
  }, []);

  // Re-derive after the resolver runs so productIds are populated.
  const tree = _llm(() => template ? normaliseTemplateToTree(template) : [], [template]);
  const productMap = _llm(() => {
    const m = {}; (window.PRODUCTS || []).forEach(p => { m[p.id] = p; });
    return m;
  }, []);

  if (!template) {
    return (
      <div className="page list-library-preview-page">
        <div className="empty">
          <h3 className="empty-title">List not found</h3>
          <p>That template isn't available.</p>
          <button className="btn btn-ghost" onClick={onBack} style={{ marginTop: 12, width: 'auto', padding: '10px 18px' }}>
            <span>← Back to Library</span>
          </button>
        </div>
      </div>
    );
  }

  const canonicalName = template._sourceData ? `${template._sourceData.label} essentials` : template.name;
  const existing = (userLists || []).find(l => l.isMine !== false && l.name === canonicalName);
  const isAdopted = !!existing;

  return (
    <div className="page list-library-preview-page list2-page">
      {/* Hero header — mirrors the list2 page header pattern but with a
          clear "preview" eyebrow so the user knows it isn't a real list yet. */}
      <div className="library-preview-head">
        <button type="button" className="library-preview-back" onClick={onBack}>
          <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5M12 19l-7-7 7-7"/></svg>
          <span>Back to Library</span>
        </button>
        <div className="library-preview-eyebrow">Preview · not yet in My lists</div>
        <h1 className="library-preview-title">{template.name}</h1>
        <p className="library-preview-blurb">{template.blurb}</p>
        <div className="library-preview-summary">{templateSummary(template)}</div>
      </div>

      <div className="library-preview-tree">
        {tree.length === 0 ? (
          <div className="empty">
            <h3 className="empty-title">No items match the catalog yet</h3>
            <p>This template's products didn't resolve. Try a different one.</p>
          </div>
        ) : (
          <PreviewTreeAsList nodes={tree} productMap={productMap} depth={0} onOpenProduct={onOpenProduct} />
        )}
      </div>

      {/* Sticky bottom CTA — single primary action: adopt (or open if
          already in My lists). Same visual weight as the list-library
          stickybar so the user has a consistent mental model. */}
      <div className="library-stickybar" role="region" aria-label="Add this list">
        <div className="library-stickybar-info">
          <span className="library-stickybar-label">
            {isAdopted ? 'Already in your lists' : 'Like what you see?'}
          </span>
        </div>
        <button type="button" className="btn btn-ghost" onClick={onBack} style={{ width: 'auto', padding: '10px 16px' }}>
          Close
        </button>
        <button
          type="button"
          className="btn"
          onClick={() => onAdopt(template)}
          style={{ width: 'auto', padding: '12px 22px' }}
        >
          <span>{isAdopted ? 'Open in My lists' : 'Add to my lists'}</span>
          <span className="arrow">{isAdopted ? '↗' : '→'}</span>
        </button>
      </div>
    </div>
  );
}

// Renders the template tree using the SAME list2-* classes as the live
// list editor so the preview matches what the user gets after adopt.
function PreviewTreeAsList({ nodes, productMap, depth, onOpenProduct }) {
  const openable = typeof onOpenProduct === 'function';
  return (
    <ul className={`list2-children list2-children--d${Math.min(depth, 3)}`}>
      {nodes.map((n, i) => {
        if (n.type === 'group') {
          return (
            <li key={i}>
              <div className="list2-slot list2-slot--group is-expanded">
                <div className="list2-slot-head">
                  <div className="list2-slot-titlewrap">
                    <h3 className="list2-slot-title">
                      {n.label}
                      <span className="list2-slot-kindbadge list2-slot-kindbadge--group">Group</span>
                    </h3>
                    {n.blurb && <p className="list2-slot-blurb">{n.blurb}</p>}
                  </div>
                </div>
                {Array.isArray(n.children) && n.children.length > 0 && (
                  <PreviewTreeAsList nodes={n.children} productMap={productMap} depth={depth + 1} onOpenProduct={onOpenProduct} />
                )}
              </div>
            </li>
          );
        }
        if (n.type === 'shortlist') {
          const products = (n.productIds || []).map(id => productMap[id]).filter(Boolean);
          return (
            <li key={i}>
              <div className="list2-slot list2-slot--shortlist is-expanded">
                <div className="list2-slot-head">
                  <div className="list2-slot-titlewrap">
                    <h3 className="list2-slot-title">
                      {n.label}
                      <span className="list2-slot-kindbadge list2-slot-kindbadge--shortlist">
                        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12l5 5L20 7"/></svg>
                        Picking one
                      </span>
                      {n.necessity === 'must' && <span className="list2-slot-must">Must-have</span>}
                    </h3>
                    {n.blurb && <p className="list2-slot-blurb">{n.blurb}</p>}
                  </div>
                </div>
                <ul className="list2-children list2-children--d1">
                  {products.map(p => (
                    <li key={p.id}>
                      <PreviewItemRow product={p} openable={openable} onOpenProduct={onOpenProduct} />
                    </li>
                  ))}
                </ul>
              </div>
            </li>
          );
        }
        // type: 'item'
        const product = productMap[(n.productIds || [])[0]];
        if (!product) return null;
        return (
          <li key={i}>
            <PreviewItemRow
              product={product}
              label={n.label}
              necessity={n.necessity}
              openable={openable}
              onOpenProduct={onOpenProduct}
            />
          </li>
        );
      })}
    </ul>
  );
}

// One product row — same shape as list2-item but read-only and clickable
// to open the full DetailPanel.
function PreviewItemRow({ product, label, necessity, openable, onOpenProduct }) {
  const handle = (e) => {
    if (!openable) return;
    e.stopPropagation();
    onOpenProduct(product);
  };
  const price = product.price;
  const currency = product.currency || 'AUD';
  return (
    <div
      className={`list2-item${openable ? ' is-clickable' : ''}`}
      role={openable ? 'button' : undefined}
      tabIndex={openable ? 0 : undefined}
      onClick={handle}
      onKeyDown={(e) => { if (openable && (e.key === 'Enter' || e.key === ' ')) { e.preventDefault(); handle(e); } }}
    >
      <div className="list2-item-thumb">
        <SmartImage src={product.img} alt={product.name} fallbackLabel={product.brand || product.name} />
      </div>
      <div className="list2-item-body">
        {product.brand && <div className="list2-item-brand">{product.brand}</div>}
        <div className="list2-item-name">{label || product.name}</div>
        <div className="list2-item-meta">
          {price != null && (
            <span className="list2-item-price">{currency === 'AUD' ? 'A$' : '$'}{Number(price).toLocaleString()}</span>
          )}
          {necessity === 'must' && <span className="list2-slot-must">Must-have</span>}
        </div>
      </div>
    </div>
  );
}

window.ListLibraryPage = ListLibraryPage;
window.TemplatePreviewPage = TemplatePreviewPage;
