// admin/pages/products.jsx — product CRUD + photo manager + Phase 09 variants/SEO/publish

function commerceCorePresent() {
  if (window.ErpCore && typeof window.ErpCore.migrateLegacyVariants === 'function') return true;
  try {
    const c = window.AmbadyCommerce && window.AmbadyCommerce.get && window.AmbadyCommerce.get();
    return !!(c && typeof c.variantsFor === 'function');
  } catch (_) {
    return false;
  }
}

function resolveStructuredVariants(product) {
  try {
    const c = window.AmbadyCommerce && window.AmbadyCommerce.get && window.AmbadyCommerce.get();
    if (c && typeof c.variantsFor === 'function') return c.variantsFor(product);
  } catch (_) {}
  if (window.ErpCore && typeof window.ErpCore.migrateLegacyVariants === 'function') {
    return window.ErpCore.migrateLegacyVariants(product);
  }
  return null;
}

function isStructuredVariantList(variants) {
  return Array.isArray(variants) && variants.length > 0 && typeof variants[0] === 'object' && variants[0] !== null && !Array.isArray(variants[0]);
}

function ProductsPage() {
  const admin = useAdmin();
  const [q, setQ] = React.useState('');
  const [cat, setCat] = React.useState('all');
  const [editing, setEditing] = React.useState(null); // product or 'new'
  const [selected, setSelected] = React.useState({});
  const products = HAP.PRODUCTS;

  const topCats = HAP.CATEGORIES.map(c => ({ slug: c.slug, name: c.name }));
  let list = products.filter(p =>
    (cat === 'all' || p.categories.includes(cat)) &&
    (!q || p.name.toLowerCase().includes(q.toLowerCase()) || (p.sku || '').toLowerCase().includes(q.toLowerCase()))
  );

  const selectedIds = Object.keys(selected).filter((id) => selected[id]);
  const allSelected = list.length > 0 && list.every((p) => selected[p.id]);

  function toggleAll(checked) {
    if (!checked) {
      setSelected({});
      return;
    }
    const next = {};
    list.forEach((p) => { next[p.id] = true; });
    setSelected(next);
  }

  function bulkSetPublish(status) {
    const label = status === 'published' ? 'publish' : 'unpublish';
    if (!selectedIds.length) {
      alert('Select at least one product.');
      return;
    }
    if (!confirm('Bulk ' + label + ' ' + selectedIds.length + ' product(s)?')) return;
    selectedIds.forEach((id) => {
      const prod = HAP.PRODUCTS.find((p) => p.id === id);
      if (prod) admin.upsertProduct({ ...prod, publishStatus: status });
    });
    setSelected({});
  }

  return (
    <div>
      <div className="toolbar">
        <div className="search-box"><AIcon name="search" /><input className="inp" placeholder="Search products or SKU…" value={q} onChange={e => setQ(e.target.value)} /></div>
        <select className="sel" style={{ width: 'auto' }} value={cat} onChange={e => setCat(e.target.value)}>
          <option value="all">All categories</option>
          {topCats.map(c => <option key={c.slug} value={c.slug}>{c.name}</option>)}
        </select>
        <div style={{ flex: 1 }}></div>
        <span className="muted" style={{ fontSize: '.82rem' }}>{list.length} products</span>
        <button className="btn btn-primary" onClick={() => setEditing('new')}><AIcon name="plus" />Add product</button>
      </div>

      {selectedIds.length > 0 && (
        <div className="toolbar" style={{ marginBottom: 10 }}>
          <span className="muted" style={{ fontSize: '.82rem' }}>{selectedIds.length} selected</span>
          <button className="btn btn-soft btn-sm" type="button" onClick={() => bulkSetPublish('published')}>Bulk publish</button>
          <button className="btn btn-soft btn-sm" type="button" onClick={() => bulkSetPublish('unpublished')}>Bulk unpublish</button>
          <button className="btn btn-ghost btn-sm" type="button" onClick={() => setSelected({})}>Clear</button>
        </div>
      )}

      <div className="card">
        <table className="tbl">
          <thead><tr>
            <th style={{ width: 36 }}>
              <input type="checkbox" checked={allSelected} onChange={(e) => toggleAll(e.target.checked)} aria-label="Select all" />
            </th>
            <th></th><th>Product</th><th>Category</th><th className="num">Price</th><th className="num">Stock</th><th>Status</th><th></th>
          </tr></thead>
          <tbody>
            {list.map(p => (
              <tr key={p.id}>
                <td>
                  <input
                    type="checkbox"
                    checked={!!selected[p.id]}
                    onChange={(e) => setSelected((prev) => ({ ...prev, [p.id]: e.target.checked }))}
                    aria-label={'Select ' + p.name}
                  />
                </td>
                <td><img className="tbl-thumb" src={p.image} alt="" /></td>
                <td><b>{p.name}</b><br /><span className="muted" style={{ fontSize: '.74rem' }}>{p.sku}</span></td>
                <td><span className="muted" style={{ fontSize: '.82rem' }}>{(p.categories[1] || p.categories[0] || '').replace(/-/g, ' ')}</span></td>
                <td className="num">{money(p.price)}<br /><span className="muted" style={{ fontSize: '.72rem', textDecoration: 'line-through' }}>{money(p.compareAt)}</span></td>
                <td className="num">{p.stock}</td>
                <td>
                  <StockBadge p={p} />
                  {p.publishStatus && p.publishStatus !== 'published' && (
                    <div className="muted" style={{ fontSize: '.7rem', marginTop: 2 }}>{p.publishStatus}</div>
                  )}
                </td>
                <td>
                  <div className="row" style={{ justifyContent: 'flex-end' }}>
                    <button className="btn btn-icon btn-ghost btn-sm" title="Edit" onClick={() => setEditing(p)}><AIcon name="edit" size={15} /></button>
                    <button className="btn btn-icon btn-ghost btn-sm" title="Duplicate" onClick={() => {
                      const copy = { ...p, id: admin.newProductId(), name: p.name + ' (copy)', slug: p.slug + '-copy', sku: 'APG-' + Math.floor(Math.random()*90000+10000) };
                      admin.upsertProduct(copy);
                    }}><AIcon name="copy" size={15} /></button>
                    <button className="btn btn-icon btn-danger btn-sm" title="Delete" onClick={() => { if (confirm('Delete ' + p.name + '?')) admin.deleteProduct(p.id); }}><AIcon name="trash" size={15} /></button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        {list.length === 0 && <Empty icon="box" title="No products found" note="Try a different search or add a new product." />}
      </div>

      {editing && <ProductEditor product={editing === 'new' ? null : editing} onClose={() => setEditing(null)} />}
    </div>
  );
}

function ProductEditor({ product, onClose }) {
  const admin = useAdmin();
  const isNew = !product;
  const useStructured = commerceCorePresent();
  const blank = {
    id: admin.newProductId(), name: '', slug: '', sku: 'APG-' + Math.floor(Math.random()*90000+10000),
    type: 'pebble', color: 'white', colorSwatch: '#eee', categories: ['pebbles'], tags: [],
    price: 149, compareAt: 249, currency: '₹', rating: 4.6, ratingCount: 0,
    variants: ['500 g', '1 kg', '5 kg'], stock: 25, lowStockAt: 5, hsn: '6802',
    isNew: true, isSale: true, vendor: 'Ambady Pebbles Garden', shipPan: true,
    image: '', images: [], media: [], blurb: '', description: '',
    publishStatus: 'published', seoTitle: '', seoDescription: ''
  };

  const [p, setP] = React.useState(() => {
    const base = JSON.parse(JSON.stringify(product || blank));
    if (!base.publishStatus) base.publishStatus = 'published';
    if (base.seoTitle == null) base.seoTitle = '';
    if (base.seoDescription == null) base.seoDescription = '';
    if (useStructured) {
      const structured = resolveStructuredVariants(base);
      if (structured) base.variants = structured;
    }
    return base;
  });
  const set = (patch) => setP(prev => ({ ...prev, ...patch }));
  const fileRef = React.useRef(null);

  // gather images: image + images[]
  const gallery = [p.image, ...(p.images || [])].filter(Boolean);
  const structured = useStructured && isStructuredVariantList(p.variants);

  function addPhotos(files) {
    const arr = Array.from(files);
    let pending = arr.length;
    const out = [];
    arr.forEach(f => {
      const r = new FileReader();
      r.onload = () => {
        out.push(r.result);
        if (--pending === 0) {
          setP(prev => {
            const all = [prev.image, ...(prev.images || [])].filter(Boolean).concat(out);
            return { ...prev, image: all[0], images: all.slice(1) };
          });
        }
      };
      r.readAsDataURL(f);
    });
  }
  function setMain(idx) {
    const all = gallery.slice();
    const [m] = all.splice(idx, 1);
    all.unshift(m);
    set({ image: all[0], images: all.slice(1) });
  }
  function removePhoto(idx) {
    const all = gallery.slice();
    all.splice(idx, 1);
    set({ image: all[0] || '', images: all.slice(1) });
  }

  function updateVariant(index, patch) {
    setP((prev) => {
      const next = (prev.variants || []).map((v, i) => (i === index ? { ...v, ...patch } : v));
      return { ...prev, variants: next };
    });
  }

  function save() {
    if (!p.name.trim()) { alert('Please enter a product name'); return; }
    const slug = (p.slug || p.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '')) + (isNew ? '-' + p.id : '');
    const finalSlug = p.slug || slug;
    let variants = p.variants;
    if (useStructured && isStructuredVariantList(variants)) {
      variants = variants.map((v, i) => ({
        ...v,
        id: v.id || (p.id + ':' + String(v.label || i).toLowerCase().replace(/[^a-z0-9]+/g, '-')),
        productId: p.id,
        label: String(v.label || ''),
        sku: String(v.sku || ''),
        price: Number(v.price) || 0,
        compareAt: v.compareAt != null && v.compareAt !== '' ? Number(v.compareAt) : null,
        stock: v.stock === '' || v.stock == null ? null : Number(v.stock),
        sortOrder: v.sortOrder != null ? v.sortOrder : i,
        status: v.status || 'active',
        priceSource: 'explicit'
      }));
      const commerce = window.AmbadyCommerce && AmbadyCommerce.get && AmbadyCommerce.get();
      if (commerce && commerce.catalogIssues) {
        const draft = { ...p, slug: finalSlug, variants, stock: p.stock };
        const issues = [];
        try {
          // Use exported audit via temporary product shape
          if (commerce.isVariantManagedInventory && commerce.isVariantManagedInventory(variants)) {
            const allocated = variants.reduce((s, v) => s + (v.stock ?? 0), 0);
            if (Number.isFinite(Number(p.stock)) && allocated > Number(p.stock)) {
              alert('Cannot save: VARIANT_ALLOCATION_EXCEEDS_POOL — variant stock totals ' + allocated + ' but product stock is ' + p.stock);
              return;
            }
          }
        } catch (_) {}
        void issues;
        void draft;
      }
    }
    if (!isNew && product && product.slug && product.slug !== finalSlug && window.CommerceRedirects) {
      CommerceRedirects.recordProductSlugChange(p.id, product.slug, finalSlug);
    }
    admin.upsertProduct({
      ...p,
      slug: finalSlug,
      blurb: p.blurb || p.description,
      description: p.description || p.blurb,
      variants,
      publishStatus: p.publishStatus || 'published',
      seoTitle: p.seoTitle || '',
      seoDescription: p.seoDescription || ''
    });
    HAPStore.notify ? null : null;
    onClose();
  }

  const allCats = [];
  HAP.CATEGORIES.forEach(c => { allCats.push([c.slug, c.name]); (c.sub || []).forEach(s => allCats.push([s.slug, '— ' + s.name])); });

  return (
    <Modal wide title={isNew ? 'Add product' : 'Edit product'} onClose={onClose}
      foot={<><button className="btn btn-ghost" onClick={onClose}>Cancel</button><button className="btn btn-primary" onClick={save}><AIcon name="check" size={15} />Save product</button></>}>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1.2fr', gap: 24 }} className="pe-grid">
        {/* Photos / Media */}
        <div>
          <div className="section-title">Media</div>
          <p className="muted" style={{ fontSize: '.74rem', marginBottom: 8 }}>
            Primary image below. Gallery uses <code>media[]</code> when present; single <code>image</code> field kept for back-compat.
          </p>
          <div className="photo-grid">
            {gallery.map((src, i) => (
              <div className="photo-cell" key={i}>
                <img src={src} alt="" />
                {i === 0 && <span style={{ position: 'absolute', top: 4, left: 4, background: 'var(--a-forest)', color: '#fff', fontSize: 9, padding: '2px 6px', borderRadius: 5 }}>MAIN</span>}
                <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, display: 'flex', background: 'rgba(0,0,0,0.55)' }}>
                  {i !== 0 && <button title="Set main" onClick={() => setMain(i)} style={{ flex: 1, color: '#fff', padding: '3px', fontSize: 10 }}><AIcon name="star" size={12} /></button>}
                  <button title="Remove" onClick={() => removePhoto(i)} style={{ flex: 1, color: '#fff', padding: '3px', fontSize: 10 }}><AIcon name="trash" size={12} /></button>
                </div>
              </div>
            ))}
            <div className="photo-add" onClick={() => fileRef.current.click()}>
              <AIcon name="plus" size={18} />Upload
            </div>
          </div>
          <input ref={fileRef} type="file" accept="image/*" multiple hidden onChange={e => addPhotos(e.target.files)} />
          <div className="field" style={{ marginTop: 12 }}>
            <label>Primary image URL (back-compat)</label>
            <input className="inp" value={p.image || ''} onChange={e => set({ image: e.target.value })} placeholder="https://… or data URL" />
          </div>
          <p className="muted" style={{ fontSize: '.74rem', marginTop: 10 }}>Drag the star to set the main photo. Images are stored with the product and shown on the storefront.</p>
        </div>

        {/* Details */}
        <div className="form-grid">
          <div className="field span2"><label>Product name</label><input className="inp" value={p.name} onChange={e => set({ name: e.target.value })} /></div>
          <div className="field"><label>Price (₹)</label><input className="inp" type="number" value={p.price} onChange={e => set({ price: +e.target.value })} /></div>
          <div className="field"><label>Compare-at (₹)</label><input className="inp" type="number" value={p.compareAt} onChange={e => set({ compareAt: +e.target.value })} /></div>
          <div className="field"><label>Stock</label><input className="inp" type="number" value={p.stock} onChange={e => set({ stock: +e.target.value })} /></div>
          <div className="field"><label>Low-stock alert at</label><input className="inp" type="number" value={p.lowStockAt} onChange={e => set({ lowStockAt: +e.target.value })} /></div>
          <div className="field"><label>SKU</label><input className="inp" value={p.sku} onChange={e => set({ sku: e.target.value })} /></div>
          <div className="field"><label>HSN code</label><input className="inp" value={p.hsn || ''} onChange={e => set({ hsn: e.target.value })} /></div>
          <div className="field"><label>Publish status</label>
            <select className="sel" value={p.publishStatus || 'published'} onChange={e => set({ publishStatus: e.target.value })}>
              <option value="draft">draft</option>
              <option value="published">published</option>
              <option value="unpublished">unpublished</option>
              <option value="archived">archived</option>
            </select>
          </div>
          <div className="field"><label>Tags (comma-separated)</label><input className="inp" value={(p.tags || []).join(', ')} onChange={e => set({ tags: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })} /></div>
          <div className="field span2"><label>Primary category</label>
            <select className="sel" value={p.categories[0]} onChange={e => set({ categories: [e.target.value, ...p.categories.slice(1)] })}>
              {allCats.map(([s, n]) => <option key={s} value={s}>{n}</option>)}
            </select>
          </div>
          <div className="field span2"><label>Also appears in (comma-separated slugs)</label>
            <input className="inp" value={p.categories.slice(1).join(', ')} onChange={e => set({ categories: [p.categories[0], ...e.target.value.split(',').map(s => s.trim()).filter(Boolean)] })} />
          </div>

          {structured ? (
            <div className="field span2">
              <label>Variants</label>
              <p className="muted" style={{ fontSize: '.72rem', marginBottom: 8 }}>
                Structured variants via commerce core. Empty stock = pooled from product stock. Saved as objects, not comma-separated labels.
              </p>
              {(() => {
                const allocated = (p.variants || []).reduce((s, v) => s + (v.stock == null || v.stock === '' ? 0 : Number(v.stock)), 0);
                const anyAllocated = (p.variants || []).some((v) => v.stock != null && v.stock !== '');
                if (anyAllocated && Number.isFinite(Number(p.stock)) && allocated > Number(p.stock)) {
                  return <div className="banner-err" style={{ marginBottom: 8 }}>VARIANT_ALLOCATION_EXCEEDS_POOL: variant totals {allocated} &gt; product stock {p.stock}. Save is blocked until fixed.</div>;
                }
                if (!anyAllocated && (p.variants || []).length > 1) {
                  return <div className="mode-banner" style={{ marginBottom: 8 }}>VARIANT_STOCK_UNALLOCATED: variants share pooled product stock ({p.stock}).</div>;
                }
                return null;
              })()}
              <div className="card table-scroll" style={{ margin: 0 }}>
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>Label</th>
                      <th>SKU</th>
                      <th className="num">Price</th>
                      <th className="num">Stock</th>
                    </tr>
                  </thead>
                  <tbody>
                    {p.variants.map((v, i) => (
                      <tr key={v.id || i}>
                        <td>{v.label}</td>
                        <td><span className="muted" style={{ fontSize: '.74rem' }}>{v.sku}</span></td>
                        <td className="num">
                          <input
                            className="inp"
                            type="number"
                            style={{ width: 88, textAlign: 'right' }}
                            value={v.price}
                            onChange={(e) => updateVariant(i, { price: +e.target.value, priceSource: 'explicit' })}
                          />
                        </td>
                        <td className="num">
                          <input
                            className="inp"
                            type="number"
                            style={{ width: 72, textAlign: 'right' }}
                            value={v.stock == null ? '' : v.stock}
                            placeholder="pool"
                            onChange={(e) => {
                              const raw = e.target.value;
                              updateVariant(i, { stock: raw === '' ? null : +raw });
                            }}
                          />
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>
          ) : (
            <div className="field span2">
              <label>Variants (comma-separated)</label>
              <input
                className="inp"
                value={(Array.isArray(p.variants) ? p.variants : []).map((v) => (typeof v === 'string' ? v : (v && v.label) || '')).filter(Boolean).join(', ')}
                onChange={e => set({ variants: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })}
              />
              <p className="muted" style={{ fontSize: '.72rem', marginTop: 4 }}>Commerce core not loaded — legacy string labels only.</p>
            </div>
          )}

          <div className="field span2"><label>SEO title (optional)</label>
            <input className="inp" value={p.seoTitle || ''} onChange={e => set({ seoTitle: e.target.value })} placeholder="Defaults to product name when empty" />
          </div>
          <div className="field span2"><label>SEO description (optional)</label>
            <textarea className="ta" rows={2} value={p.seoDescription || ''} onChange={e => set({ seoDescription: e.target.value })} placeholder="Short meta description for search listings" />
          </div>
          <div className="field span2"><label>Description</label><textarea className="ta" value={p.description} onChange={e => set({ description: e.target.value, blurb: e.target.value })} /></div>
          <div className="field span2">
            <label>Flags</label>
            <div className="row" style={{ gap: 18 }}>
              <label className="row" style={{ gap: 6, fontSize: '.85rem' }}><input type="checkbox" checked={!!p.isNew} onChange={e => set({ isNew: e.target.checked })} /> New</label>
              <label className="row" style={{ gap: 6, fontSize: '.85rem' }}><input type="checkbox" checked={!!p.isSale} onChange={e => set({ isSale: e.target.checked })} /> On sale</label>
              <label className="row" style={{ gap: 6, fontSize: '.85rem' }}><input type="checkbox" checked={!!p.shipPan} onChange={e => set({ shipPan: e.target.checked })} /> Pan-India</label>
            </div>
          </div>
        </div>
      </div>
      <style>{`@media (max-width: 760px){ .pe-grid { grid-template-columns: 1fr !important; } }`}</style>
    </Modal>
  );
}
window.ProductsPage = ProductsPage;
