// ── INVENTARIO REAL v3 — Persistencia localStorage + Export/Import + Etiquetas 55×12mm ──

// Claves de almacenamiento
const INV_KEY   = 'inventario_prods';   // array completo (sin fotos)
const FOTOS_KEY = 'inventario_fotos';   // {id: foto_url}

// ── Persistencia ─────────────────────────────────────────────────────────────
function guardarInventarioLS(productos) {
  // Guardar sin foto_url para no saturar localStorage (fotos van aparte)
  const sinFotos = productos.map(({ foto_url, ...rest }) => rest);
  lsSet(INV_KEY, sinFotos);
}

function guardarFotosLS(fotos) {
  lsSet(FOTOS_KEY, fotos);
}

function merge(jsonProds, lsProds, fotos) {
  // Si hay datos en LS, usarlos; si no, sembrar desde JSON
  const base = (lsProds && lsProds.length > 0) ? lsProds : jsonProds;
  // Inyectar fotos
  return base.map(p => ({ ...p, foto_url: fotos[p.id] || null }));
}

// ── Export ───────────────────────────────────────────────────────────────────
function exportarJSON(productos) {
  const blob = new Blob([JSON.stringify(productos, null, 2)], { type: 'application/json' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = `navarro_inventario_${new Date().toISOString().slice(0,10)}.json`;
  a.click();
}

// ── Mapa campo interno → etiqueta amigable en español ────────────────────────
const CSV_COLS = [
  { key: 'sku',            label: 'SKU'              },
  { key: 'nombre',         label: 'Nombre'           },
  { key: 'categoria',      label: 'Categoría'        },
  { key: 'metal',          label: 'Metal'            },
  { key: 'pureza',         label: 'Pureza'           },
  { key: 'piedra',         label: 'Piedra/Gema'      },
  { key: 'talla',          label: 'Talla'            },
  { key: 'peso',           label: 'Peso (g)'         },
  { key: 'largo_cm',       label: 'Largo (cm)'       },
  { key: 'costo',          label: 'Costo ($)'        },
  { key: 'precio',         label: 'Precio ($)'       },
  { key: 'stock',          label: 'Stock'            },
  { key: 'estado',         label: 'Estado'           },
  { key: 'ubicacion',      label: 'Ubicación'        },
  { key: 'tienda',         label: 'Tienda'           },
  { key: 'notas',          label: 'Notas'            },
  { key: 'proveedor',      label: 'Proveedor'        },
  { key: 'venta_online',   label: 'Venta Online'     },
  { key: 'insumo_asociado',label: 'Insumo Asociado'  },
];

// Valores válidos de referencia para cada campo (van como comentario en la plantilla)
const CSV_HINTS = {
  categoria: 'Anillo / Collar / Argolla / Pulsera / Arete / Colgante / Otro',
  metal:     'Oro / Plata / Acero / Platino / Otro',
  pureza:    '750 / 925 / 585 / 950 / —',
  estado:    'activo / inactivo / encargo',
  tienda:    'Casa Matriz / Sucursal 1 / Online',
  venta_online: 'sí / no',
};

// ── Escapar valor para CSV con separador `;` ──────────────────────────────────
function escCSV(v, sep = ';') {
  const s = v == null ? '' : String(v);
  return s.includes(sep) || s.includes('"') || s.includes('\n')
    ? '"' + s.replace(/"/g, '""') + '"'
    : s;
}

// ── Exportar CSV con separador ; (compatible Excel/Numbers en español) ────────
function exportarCSV(productos) {
  const SEP = ';';
  const header = CSV_COLS.map(c => escCSV(c.label, SEP)).join(SEP);
  const rows   = productos.map(p =>
    CSV_COLS.map(c => escCSV(p[c.key], SEP)).join(SEP)
  );
  const blob = new Blob(['﻿' + [header, ...rows].join('\r\n')], { type: 'text/csv;charset=utf-8' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = `navarro_inventario_${new Date().toISOString().slice(0,10)}.csv`;
  a.click();
}

// ── Descargar plantilla vacía con encabezados + 5 filas ejemplo ───────────────
function descargarPlantillaCSV() {
  const SEP = ';';
  // Fila de referencia (valores posibles) — va como primera fila de datos en gris
  const hintsRow = CSV_COLS.map(c => escCSV(c.key === 'sku' ? '← Obligatorio' : (CSV_HINTS[c.key] || ''), SEP)).join(SEP);
  const exampleRow = CSV_COLS.map(c => {
    const eg = {
      sku:'ANI-001', nombre:'Anillo Solitario', categoria:'Anillo', metal:'Oro',
      pureza:'750', piedra:'Diamante', talla:'17', peso:'3.2', largo_cm:'',
      costo:'85000', precio:'190000', stock:'2', estado:'activo',
      ubicacion:'Vitrina A', tienda:'Casa Matriz', notas:'',
      proveedor:'Proveedor XYZ', venta_online:'sí', insumo_asociado:''
    };
    return escCSV(eg[c.key] ?? '', SEP);
  }).join(SEP);
  // 4 filas vacías para rellenar
  const emptyRow = CSV_COLS.map(() => '').join(SEP);
  const header   = CSV_COLS.map(c => escCSV(c.label, SEP)).join(SEP);
  const lines    = [header, hintsRow, exampleRow, emptyRow, emptyRow, emptyRow, emptyRow];
  const blob = new Blob(['﻿' + lines.join('\r\n')], { type: 'text/csv;charset=utf-8' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = `navarro_plantilla_inventario.csv`;
  a.click();
}

function importarJSON(file, onDone) {
  const reader = new FileReader();
  reader.onload = e => {
    try {
      const data = JSON.parse(e.target.result);
      if (!Array.isArray(data)) { alert('El archivo JSON debe contener un array de productos.'); return; }
      onDone(data);
    } catch { alert('Error al leer el archivo JSON.'); }
  };
  reader.readAsText(file);
}

function importarCSV(file, onDone) {
  const reader = new FileReader();
  reader.onload = e => {
    try {
      const raw   = e.target.result.replace(/^﻿/, '');
      const lines = raw.split(/\r?\n/).filter(l => l.trim());
      if (lines.length < 2) { alert('CSV vacío o inválido.'); return; }

      // ── Detectar separador automáticamente (;  o  ,) ────────────────────────
      const firstLine = lines[0];
      const SEP = (firstLine.split(';').length >= firstLine.split(',').length) ? ';' : ',';

      // ── Parser CSV robusto que respeta comillas ────────────────────────────
      function parseCsvRow(row) {
        const vals = []; let cur = '', inQ = false;
        for (let i = 0; i < row.length; i++) {
          const ch = row[i];
          if (ch === '"' && !inQ) { inQ = true; continue; }
          if (ch === '"' && inQ)  {
            if (row[i+1] === '"') { cur += '"'; i++; } else inQ = false;
            continue;
          }
          if (ch === SEP && !inQ) { vals.push(cur.trim()); cur = ''; continue; }
          cur += ch;
        }
        vals.push(cur.trim());
        return vals;
      }

      // ── Mapear encabezados (acepta etiquetas en español O claves internas) ──
      const rawHeaders = parseCsvRow(lines[0]);
      const labelToKey = {};
      CSV_COLS.forEach(c => {
        labelToKey[c.label.toLowerCase()]           = c.key;
        labelToKey[c.label.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g,'')] = c.key;
        labelToKey[c.key.toLowerCase()]             = c.key;
      });
      const headers = rawHeaders.map(h => labelToKey[h.toLowerCase().trim()] || h.toLowerCase().trim());

      const NUMS = new Set(['costo','precio','stock','peso','largo_cm']);
      const data = lines.slice(1).map((line, li) => {
        // Ignorar la fila de hints ("← Obligatorio" / referencias)
        if (line.includes('← Obligatorio') || line.includes('Anillo / Collar')) return null;
        const vals = parseCsvRow(line);
        const obj  = {};
        headers.forEach((h, i) => {
          const v = vals[i] ?? '';
          obj[h] = NUMS.has(h) ? (parseFloat(v.replace(',','.')) || 0) : v;
        });
        if (!obj.id) obj.id = 'imp-' + Date.now() + li + '-' + Math.random().toString(36).slice(2,8);
        return obj;
      }).filter(p => p && (p.sku || p.nombre));

      if (!data.length) { alert('No se encontraron productos válidos en el archivo.'); return; }
      onDone(data);
    } catch(err) { alert('Error al leer el CSV: ' + err.message); }
  };
  reader.readAsText(file, 'utf-8');
}

// ── FOTO MANAGER ──────────────────────────────────────────────────────────────
function FotoManager({ prod, isEdit, onFoto }) {
  const { useState, useRef } = React;
  const [menu, setMenu]       = useState(false);
  const [urlInput, setUrlInput]= useState(false);
  const [url, setUrl]          = useState('');
  const fileRef = useRef();
  const foto = prod?.foto_url;

  function handleFile(e) {
    const f = e.target.files[0];
    if (!f) return;
    const reader = new FileReader();
    reader.onload = ev => { onFoto && onFoto(ev.target.result); setMenu(false); };
    reader.readAsDataURL(f);
  }

  function aplicarUrl() {
    if (url.trim()) { onFoto && onFoto(url.trim()); setUrl(''); setUrlInput(false); setMenu(false); }
  }

  return (
    <div style={{ position:'relative', flexShrink:0 }}>
      <div onClick={() => isEdit && setMenu(m => !m)}
        style={{
          width:'72px', height:'72px', borderRadius:'8px', overflow:'hidden',
          border: foto ? '2px solid var(--gold)' : '1px solid var(--border)',
          background:'var(--surface)', cursor: isEdit ? 'pointer' : 'default',
          display:'flex', alignItems:'center', justifyContent:'center', flexDirection:'column',
        }}>
        {foto
          ? <img src={foto} alt="" style={{ width:'100%', height:'100%', objectFit:'cover' }}
              onError={e => e.target.style.display='none'}/>
          : <>
              <span style={{ fontSize:'22px' }}>📷</span>
              <span style={{ fontSize:'7px', color:'var(--cream-3)', marginTop:'2px' }}>
                {isEdit ? 'Agregar foto' : 'Sin foto'}
              </span>
            </>
        }
        {isEdit && foto && (
          <div style={{ position:'absolute', bottom:'2px', right:'2px', background:'rgba(0,0,0,0.7)', borderRadius:'3px', padding:'1px 3px', fontSize:'8px', color:'var(--cream)' }}>✏</div>
        )}
      </div>

      {menu && isEdit && (
        <div style={{
          position:'absolute', top:'76px', left:0, zIndex:50,
          background:'var(--bg-card)', border:'1px solid var(--border)',
          borderRadius:'10px', padding:'6px', width:'190px',
          boxShadow:'0 8px 24px rgba(0,0,0,0.6)',
        }}>
          <div style={{ fontSize:'9px', color:'var(--gold)', fontWeight:600, padding:'3px 6px 5px', letterSpacing:'0.5px' }}>AGREGAR FOTO</div>

          <button onClick={() => fileRef.current.click()}
            style={{ display:'flex', alignItems:'center', gap:'8px', width:'100%', padding:'7px 8px', background:'none', border:'none', color:'var(--cream)', cursor:'pointer', borderRadius:'6px', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
            <span>🖥</span> Subir desde computador
          </button>
          <input ref={fileRef} type="file" accept="image/*" style={{ display:'none' }} onChange={handleFile}/>

          <button onClick={() => { const inp = document.createElement('input'); inp.type='file'; inp.accept='image/*'; inp.capture='environment'; inp.onchange=handleFile; inp.click(); setMenu(false); }}
            style={{ display:'flex', alignItems:'center', gap:'8px', width:'100%', padding:'7px 8px', background:'none', border:'none', color:'var(--cream)', cursor:'pointer', borderRadius:'6px', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
            <span>📷</span> Tomar foto (cámara)
          </button>

          <button onClick={() => setUrlInput(u => !u)}
            style={{ display:'flex', alignItems:'center', gap:'8px', width:'100%', padding:'7px 8px', background:'none', border:'none', color:'var(--cream)', cursor:'pointer', borderRadius:'6px', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
            <span>🌐</span> Pegar URL de web
          </button>
          {urlInput && (
            <div style={{ padding:'4px 8px 6px' }}>
              <input value={url} onChange={e => setUrl(e.target.value)}
                placeholder="https://…" autoFocus
                style={{ ...calcStyles.input, fontSize:'10px', padding:'5px 8px', marginBottom:'4px' }}/>
              <button onClick={aplicarUrl}
                style={{ ...inv2Styles.btnGold, width:'100%', fontSize:'10px', padding:'4px' }}>
                Aplicar
              </button>
            </div>
          )}

          {foto && (
            <button onClick={() => { onFoto && onFoto(null); setMenu(false); }}
              style={{ display:'flex', alignItems:'center', gap:'8px', width:'100%', padding:'7px 8px', background:'none', border:'none', color:'#c0392b', cursor:'pointer', borderRadius:'6px', fontSize:'11px', fontFamily:'Inter,sans-serif', marginTop:'2px' }}>
              <span>🗑</span> Quitar foto
            </button>
          )}

          <button onClick={() => setMenu(false)}
            style={{ display:'block', width:'100%', marginTop:'4px', padding:'4px', background:'none', border:'none', color:'var(--cream-3)', cursor:'pointer', fontSize:'10px', fontFamily:'Inter,sans-serif', textAlign:'center' }}>
            Cerrar
          </button>
        </div>
      )}
    </div>
  );
}

// ── MODAL AJUSTE STOCK ────────────────────────────────────────────────────────
function ModalAjusteStock({ prod, onClose, onGuardar }) {
  const { useState } = React;
  const [modo,   setModo]   = useState('set');   // 'set' | 'add' | 'sub'
  const [valor,  setValor]  = useState(0);
  const [motivo, setMotivo] = useState('');

  const stockFinal = () => {
    const v = parseInt(valor) || 0;
    if (modo === 'set') return Math.max(0, v);
    if (modo === 'add') return Math.max(0, (prod.stock || 0) + v);
    return Math.max(0, (prod.stock || 0) - v);
  };

  return (
    <div style={posStyles.overlay} onClick={e => e.target === e.currentTarget && onClose()}>
      <div style={{ ...posStyles.modalBox, maxWidth:'380px' }}>
        <div style={posStyles.modalHeader}>
          <span style={{ fontFamily:'Cormorant Garamond,serif', fontSize:'20px', fontWeight:600 }}>
            📦 Ajustar Stock
          </span>
          <button onClick={onClose} style={posStyles.clearBtn}>✕</button>
        </div>
        <div style={{ background:'var(--surface)', borderRadius:'8px', padding:'10px', marginBottom:'14px' }}>
          <div style={{ fontFamily:'monospace', color:'var(--gold)', fontWeight:700 }}>{prod.sku}</div>
          <div style={{ color:'var(--cream)', fontSize:'12px', marginTop:'2px' }}>{prod.nombre}</div>
          <div style={{ color:'var(--cream-3)', fontSize:'11px', marginTop:'4px' }}>Stock actual: <strong style={{ color:'var(--cream)' }}>{prod.stock || 0}</strong></div>
        </div>

        <div style={{ display:'flex', gap:'6px', marginBottom:'12px' }}>
          {[['set','= Fijar'], ['add','+ Agregar'], ['sub','− Restar']].map(([m, l]) => (
            <button key={m} onClick={() => setModo(m)}
              style={{ flex:1, padding:'7px', borderRadius:'6px', border:'1px solid var(--border)',
                background: modo === m ? 'var(--gold-dim)' : 'var(--surface)',
                color: modo === m ? 'var(--gold)' : 'var(--cream-3)',
                fontWeight: modo === m ? 700 : 400, cursor:'pointer', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
              {l}
            </button>
          ))}
        </div>

        <div style={{ marginBottom:'10px' }}>
          <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'4px' }}>
            {modo === 'set' ? 'Stock nuevo' : modo === 'add' ? 'Unidades a agregar' : 'Unidades a restar'}
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:'8px' }}>
            <button onClick={() => setValor(v => Math.max(0, parseInt(v)||0 - 1))}
              style={{ ...inv2Styles.btnSec, width:'32px', padding:'4px', fontSize:'16px', textAlign:'center' }}>−</button>
            <input type="number" min="0" value={valor}
              onChange={e => setValor(Math.max(0, parseInt(e.target.value) || 0))}
              style={{ ...calcStyles.input, width:'80px', textAlign:'center', fontWeight:700, fontSize:'16px' }}/>
            <button onClick={() => setValor(v => (parseInt(v)||0) + 1)}
              style={{ ...inv2Styles.btnSec, width:'32px', padding:'4px', fontSize:'16px', textAlign:'center' }}>+</button>
            <div style={{ flex:1, textAlign:'right', color:'var(--cream-3)', fontSize:'11px' }}>
              → <strong style={{ color:'var(--gold)', fontSize:'14px' }}>{stockFinal()}</strong> unidades
            </div>
          </div>
        </div>

        <div style={{ marginBottom:'14px' }}>
          <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'4px' }}>Motivo (opcional)</div>
          <input style={calcStyles.input} placeholder="Ej: Venta directa, Corrección inventario…"
            value={motivo} onChange={e => setMotivo(e.target.value)}/>
        </div>

        <button onClick={() => onGuardar(stockFinal(), motivo)} style={{ ...posStyles.cobrarBtn, width:'100%' }}>
          ✓ Confirmar ajuste de stock
        </button>
      </div>
    </div>
  );
}

// ── COMPONENTE INVENTARIO REAL ────────────────────────────────────────────────
function InventarioReal({ tiendaId }) {
  const { useState, useEffect, useRef, useCallback } = React;

  const [productos,    setProductos]    = useState([]);
  const [fotos,        setFotos]        = useState({});
  const [cargando,     setCargando]     = useState(true);
  const [busqueda,     setBusqueda]     = useState('');
  const [catFiltro,    setCatFiltro]    = useState('Todos');
  const [metalFiltro,  setMetalFiltro]  = useState('Todos');
  const [estadoFiltro, setEstadoFiltro] = useState('Todos');
  const [selId,        setSel]          = useState(null);
  const [editando,     setEditando]     = useState(null);
  const [modalNuevo,   setModalNuevo]   = useState(false);
  const [modalStock,   setModalStock]   = useState(null); // product para ajustar stock
  const [vistaEtiq,    setVistaEtiq]    = useState(false);
  const [selEtiq,      setSelEtiq]      = useState(new Set());
  const [pagina,       setPagina]       = useState(0);
  const [toast,        setToast]        = useState('');
  const [confirmDel,   setConfirmDel]   = useState(null); // id a eliminar
  const [modalImport,  setModalImport]  = useState(null); // {nuevos, conflictos, data}
  const importRef = useRef();
  const POR_PAGINA = 60;

  const [nuevo, setNuevo] = useState({
    nombre:'', nombre_corto:'', categoria:'ANILLO', metal_code:'AG',
    metal:'Plata', piedra:'', pureza:'', talla:'', largo_cm:'', peso:'',
    costo:0, precio:0, stock:1, estado:'En vitrina', ubicacion:'',
    notas:'', tienda: tiendaId||'navarro',
    venta_online:'No', insumo_asociado:'Sin empaque', observaciones:'',
    sku:'', skuManual:false,
  });

  // ── Validación de SKU único — coherente para crear y editar ───────────────
  // Devuelve el producto que ya usa ese SKU (si existe), excluyendo `excludeId`
  function buscarSkuDuplicado(sku, excludeId) {
    const s = (sku||'').trim().toLowerCase();
    if (!s) return null;
    return productos.find(p => p.id !== excludeId && (p.sku||'').trim().toLowerCase() === s) || null;
  }

  // ── TOAST ─────────────────────────────────────────────────────────────────
  const showToast = msg => {
    setToast(msg);
    setTimeout(() => setToast(''), 2800);
  };

  // ── CARGA INICIAL ────────────────────────────────────────────────────────
  useEffect(() => {
    const fotosLS = lsGet(FOTOS_KEY, {});
    setFotos(fotosLS);

    const prodsLS = lsGet(INV_KEY, null);
    if (prodsLS && prodsLS.length > 0) {
      // Inyectar fotos y listo
      setProductos(prodsLS.map(p => ({ ...p, foto_url: fotosLS[p.id] || null })));
      setCargando(false);
    } else {
      // Primera vez: sembrar desde JSON
      fetch('data/inventario_real.json')
        .then(r => r.json())
        .then(data => {
          const conFotos = data.map(p => ({ ...p, foto_url: fotosLS[p.id] || null }));
          setProductos(conFotos);
          guardarInventarioLS(conFotos);
          setCargando(false);
        })
        .catch(() => { setProductos([]); setCargando(false); });
    }
  }, []);

  // ── PERSISTIR cuando cambia productos ────────────────────────────────────
  // (Solo después de la carga inicial)
  const firstRender = useRef(true);
  useEffect(() => {
    if (firstRender.current) { firstRender.current = false; return; }
    if (!cargando) guardarInventarioLS(productos);
  }, [productos, cargando]);

  const misProd = productos.filter(p => p.tienda === (tiendaId||'navarro'));

  // Filtrado
  const filtrados = misProd.filter(p => {
    const q = busqueda.toLowerCase();
    const matchQ = !q || p.nombre?.toLowerCase().includes(q) || p.sku?.toLowerCase().includes(q)
      || p.piedra?.toLowerCase().includes(q) || p.metal?.toLowerCase().includes(q)
      || p.notas?.toLowerCase().includes(q);
    const matchCat   = catFiltro==='Todos'   || p.categoria===catFiltro;
    const matchMetal = metalFiltro==='Todos' || p.metal===metalFiltro;
    const matchEst   = estadoFiltro==='Todos'|| p.estado===estadoFiltro;
    return matchQ && matchCat && matchMetal && matchEst;
  });

  const totalPags = Math.ceil(filtrados.length / POR_PAGINA);
  const pagina_items = filtrados.slice(pagina*POR_PAGINA, (pagina+1)*POR_PAGINA);

  useEffect(() => setPagina(0), [busqueda, catFiltro, metalFiltro, estadoFiltro]);

  const selProd = productos.find(p => p.id === selId);

  const catCounts = {};
  misProd.forEach(p => { catCounts[p.categoria] = (catCounts[p.categoria]||0)+1; });
  const cats = ['Todos', ...Object.keys(catCounts).sort()];

  const metalCounts = {};
  misProd.forEach(p => { metalCounts[p.metal] = (metalCounts[p.metal]||0)+1; });
  const metales = ['Todos', ...Object.keys(metalCounts).sort()];

  const valorInventario = misProd.reduce((s,p) => s+(p.precio||0)*(p.stock||0), 0);
  const sinFoto         = misProd.filter(p => !p.foto_url).length;
  const stockTotal      = misProd.reduce((s,p) => s+(p.stock||0), 0);

  // ── GUARDAR EDICIÓN ───────────────────────────────────────────────────────
  function guardarEdit() {
    // Validación: no permitir códigos duplicados al editar
    const skuLimpio = (editando.sku||'').trim().toUpperCase();
    if (!skuLimpio) { alert('El código SKU no puede quedar vacío.'); return; }
    const dup = buscarSkuDuplicado(skuLimpio, editando.id);
    if (dup) { alert(`⚠ El código "${skuLimpio}" ya está en uso por:\n${dup.sku} — ${dup.nombre}\n\nElige un código diferente.`); return; }
    const editFinal = { ...editando, sku: skuLimpio };
    setProductos(prev => prev.map(p => p.id === editFinal.id ? { ...editFinal } : p));
    setSel(editando.id);
    // Foto aparte
    if (editando.foto_url !== undefined) {
      const newFotos = { ...fotos, [editando.id]: editando.foto_url || null };
      setFotos(newFotos);
      guardarFotosLS(newFotos);
    }
    setEditando(null);
    showToast('✓ Producto actualizado y guardado');
  }

  // ── AJUSTAR STOCK ──────────────────────────────────────────────────────────
  function confirmarAjusteStock(nuevoStock, motivo) {
    const prod = modalStock;
    setProductos(prev => prev.map(p =>
      p.id === prod.id
        ? { ...p, stock: nuevoStock,
            historialStock: [...(p.historialStock||[]), {
              fecha: new Date().toISOString(), anterior: p.stock,
              nuevo: nuevoStock, motivo: motivo||'Ajuste manual'
            }]}
        : p
    ));
    setModalStock(null);
    showToast(`✓ Stock de ${prod.sku} ajustado a ${nuevoStock}`);
  }

  // ── AGREGAR PRODUCTO ──────────────────────────────────────────────────────
  function agregarProducto() {
    if (!nuevo.nombre.trim()) { alert('El nombre es obligatorio.'); return; }
    // SKU: si el usuario lo editó se respeta su valor; si no, se usa el propuesto automáticamente
    const propuesto = generarSKU(nuevo.metal_code, nuevo.categoria, nuevo.piedra, productos);
    const sku = (nuevo.sku||'').trim().toUpperCase() || propuesto;
    // Validación: no permitir códigos duplicados en toda la app
    const dup = buscarSkuDuplicado(sku, null);
    if (dup) { alert(`⚠ El código "${sku}" ya está en uso por:\n${dup.sku} — ${dup.nombre}\n\nElige un código diferente.`); return; }
    const id  = 'prod-' + Date.now();
    const prod = {
      ...nuevo, id, sku,
      imagen_status: 'sin_foto',
      speech: '', is_active: true,
      tienda: tiendaId||'navarro',
      fechaIngreso: hoy(),
      diasEnStock: 0,
    };
    setProductos(prev => [prod, ...prev]);
    setModalNuevo(false);
    setSel(id);
    setNuevo(n => ({ ...n, nombre:'', nombre_corto:'', costo:0, precio:0, stock:1, sku:'', skuManual:false }));
    showToast('✓ Producto creado: ' + sku);
  }

  // ── ELIMINAR PRODUCTO ─────────────────────────────────────────────────────
  function eliminarProducto(id) {
    setProductos(prev => prev.filter(p => p.id !== id));
    if (selId === id) setSel(null);
    setConfirmDel(null);
    showToast('Producto eliminado del inventario');
  }

  // ── FOTO ─────────────────────────────────────────────────────────────────
  function actualizarFoto(id, url) {
    // Mostrar de inmediato en pantalla con el base64 local (respuesta instantánea)
    const newFotos = { ...fotos, [id]: url };
    setFotos(newFotos);
    guardarFotosLS(newFotos);
    if (editando && editando.id === id) {
      setEditando(prev => ({ ...prev, foto_url: url, imagen_status: url ? 'con_foto' : 'sin_foto' }));
    }
    setProductos(prev => prev.map(p =>
      p.id === id ? { ...p, foto_url: url, imagen_status: url ? 'con_foto' : 'sin_foto' } : p
    ));
    // Subir a la nube (Supabase Storage) en segundo plano y reemplazar por la URL pública
    // (así la foto queda visible desde cualquier dispositivo, no solo este navegador)
    if (url && url.startsWith('data:')) {
      sbSubirFoto(id, url).then(publicUrl => {
        if (!publicUrl || publicUrl === url) return; // subida falló: se queda con el local
        const fotosNube = { ...fotos, [id]: publicUrl };
        setFotos(fotosNube);
        guardarFotosLS(fotosNube);
        setEditando(prev => (prev && prev.id === id) ? { ...prev, foto_url: publicUrl } : prev);
        setProductos(prev => prev.map(p => p.id === id ? { ...p, foto_url: publicUrl } : p));
      }).catch(()=>{});
    }
  }

  // ── IMPORTAR ─────────────────────────────────────────────────────────────
  function handleImportar(file) {
    if (!file) return;
    const ext = file.name.split('.').pop().toLowerCase();
    const done = data => {
      // Indexar existentes por SKU y por ID
      const bySku = {}, byId = {};
      productos.forEach(p => {
        if (p.sku)  bySku[p.sku.toLowerCase().trim()]  = p;
        if (p.id)   byId[p.id]  = p;
      });
      const nuevos     = data.filter(p => !bySku[(p.sku||'').toLowerCase().trim()] && !byId[p.id]);
      const conflictos = data.filter(p =>  bySku[(p.sku||'').toLowerCase().trim()] ||  byId[p.id]);
      setModalImport({ nuevos, conflictos, data });
    };
    if (ext === 'json') importarJSON(file, done);
    else if (ext === 'csv') importarCSV(file, done);
    else alert('Solo se admiten archivos .json o .csv');
    importRef.current.value = '';
  }

  // ── Aplicar importación según opción elegida ──────────────────────────────
  function aplicarImport(modo) {
    if (!modalImport) return;
    const { nuevos, conflictos, data } = modalImport;
    const bySku = {};
    productos.forEach(p => { if (p.sku) bySku[p.sku.toLowerCase().trim()] = p; });

    let resultado;
    if (modo === 'solo_nuevos') {
      // Agrega los nuevos, deja intactos los existentes
      resultado = [...productos, ...nuevos];
      showToast(`✓ ${nuevos.length} productos nuevos agregados`);
    } else if (modo === 'actualizar_todo') {
      // Nuevos se agregan; existentes se sobreescriben completamente
      const bySkuUpd = {};
      conflictos.forEach(p => { bySkuUpd[(p.sku||'').toLowerCase().trim()] = p; });
      resultado = productos.map(p => bySkuUpd[(p.sku||'').toLowerCase().trim()] || p);
      resultado = [...resultado, ...nuevos];
      showToast(`✓ ${conflictos.length} actualizados · ${nuevos.length} nuevos`);
    } else if (modo === 'solo_stock') {
      // Solo actualiza el campo stock de los existentes
      const bySkuUpd = {};
      conflictos.forEach(p => { bySkuUpd[(p.sku||'').toLowerCase().trim()] = p; });
      resultado = productos.map(p => {
        const imp = bySkuUpd[(p.sku||'').toLowerCase().trim()];
        return imp ? { ...p, stock: imp.stock } : p;
      });
      resultado = [...resultado, ...nuevos];
      showToast(`✓ Stock actualizado en ${conflictos.length} prod · ${nuevos.length} nuevos`);
    } else if (modo === 'reemplazar') {
      // Reemplaza TODO el inventario
      resultado = data;
      showToast(`✓ Inventario reemplazado (${data.length} productos)`);
    } else {
      setModalImport(null); return;
    }
    setProductos(resultado);
    guardarInventarioLS(resultado);
    setModalImport(null);
  }

  // ── ETIQUETA (usa la de data.jsx — 55×12mm hueso) ────────────────────────
  function imprimirEtiq(lista) {
    window.imprimirEtiquetaGodex(lista, {});
  }

  // Toggle etiqueta
  function toggleEtiq(id) {
    setSelEtiq(prev => { const s = new Set(prev); s.has(id) ? s.delete(id) : s.add(id); return s; });
  }

  const S = inv2Styles;

  if (cargando) return (
    <div style={{ display:'flex', alignItems:'center', justifyContent:'center', height:'100%',
      flexDirection:'column', gap:'12px', color:'var(--cream-3)' }}>
      <div style={{ fontSize:'32px', animation:'pulse 1.5s infinite' }}>✦</div>
      <div>Cargando inventario…</div>
    </div>
  );

  return (
    <div style={{ display:'flex', height:'100%', overflow:'hidden' }}>

      {/* ── TOAST ── */}
      {toast && (
        <div style={{ position:'fixed', bottom:'20px', left:'50%', transform:'translateX(-50%)',
          background:'#1a3a2a', color:'#c9a84c', padding:'9px 20px', borderRadius:'8px',
          fontSize:'12px', fontWeight:600, zIndex:300, boxShadow:'0 4px 20px rgba(0,0,0,0.5)',
          border:'1px solid rgba(201,168,76,0.3)', pointerEvents:'none' }}>
          {toast}
        </div>
      )}

      {/* ── Sidebar filtros ── */}
      <div style={{ ...S.sidebar, width:'185px' }}>
        <div style={{ padding:'10px 12px', borderBottom:'1px solid var(--border)' }}>
          <input style={{ ...S.searchInput, width:'100%' }} placeholder="🔍 SKU, nombre, piedra…"
            value={busqueda} onChange={e => setBusqueda(e.target.value)} autoFocus/>
        </div>

        {/* Stats */}
        <div style={{ padding:'8px 12px', borderBottom:'1px solid var(--border)',
          display:'grid', gridTemplateColumns:'1fr 1fr', gap:'4px' }}>
          {[
            { l:'Productos', v:misProd.length },
            { l:'Unidades',  v:stockTotal },
            { l:'Valor',     v:'$'+Math.round(valorInventario/1_000_000).toFixed(1)+'M' },
            { l:'Sin foto',  v:sinFoto, alert:true },
          ].map(s => (
            <div key={s.l} style={{ background:'var(--surface)', borderRadius:'5px', padding:'5px 7px', textAlign:'center' }}>
              <div style={{ color:s.alert&&s.v>0?'#f39c12':'var(--gold)', fontWeight:700, fontSize:'13px' }}>{s.v}</div>
              <div style={{ color:'var(--cream-3)', fontSize:'9px' }}>{s.l}</div>
            </div>
          ))}
        </div>

        {/* Filtros */}
        {[
          { title:'CATEGORÍA', items:cats, val:catFiltro, set:setCatFiltro, counts:catCounts },
          { title:'METAL',     items:metales, val:metalFiltro, set:setMetalFiltro, counts:metalCounts },
        ].map(({ title, items, val, set, counts }) => (
          <div key={title} style={{ padding:'8px 10px', borderBottom:'1px solid var(--border)', flex:'0 0 auto' }}>
            <div style={{ fontSize:'9px', color:'var(--cream-3)', fontWeight:600, letterSpacing:'0.5px', marginBottom:'5px' }}>{title}</div>
            <div style={{ maxHeight:'130px', overflowY:'auto', display:'flex', flexDirection:'column', gap:'2px' }}>
              {items.map(c => (
                <button key={c} onClick={() => set(c)}
                  style={{ ...S.filterBtn, ...(val===c ? S.filterBtnAct : {}) }}>
                  <span style={{ flex:1, textAlign:'left' }}>{c}</span>
                  {c !== 'Todos' && <span style={{ color:'var(--cream-3)', fontSize:'9px' }}>{counts[c]||0}</span>}
                </button>
              ))}
            </div>
          </div>
        ))}

        <div style={{ padding:'8px 10px' }}>
          <div style={{ fontSize:'9px', color:'var(--cream-3)', fontWeight:600, letterSpacing:'0.5px', marginBottom:'5px' }}>ESTADO</div>
          <div style={{ display:'flex', flexDirection:'column', gap:'2px' }}>
            {['Todos', ...ESTADOS_PROD].map(e => (
              <button key={e} onClick={() => setEstadoFiltro(e)}
                style={{ ...S.filterBtn, ...(estadoFiltro===e ? S.filterBtnAct : {}) }}>
                {e}
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* ── Lista productos ── */}
      <div style={{ flex:1, display:'flex', flexDirection:'column', overflow:'hidden',
        borderRight:'1px solid var(--border)' }}>

        {/* Toolbar */}
        <div style={{ ...S.toolbar, gap:'6px', flexWrap:'wrap' }}>
          <div style={{ display:'flex', alignItems:'center', gap:'8px' }}>
            <span style={{ color:'var(--cream-3)', fontSize:'12px' }}>
              {filtrados.length.toLocaleString()} productos
              {(busqueda || catFiltro!=='Todos' || metalFiltro!=='Todos' || estadoFiltro!=='Todos') ? ' (filtrado)' : ''}
            </span>
          </div>
          <div style={{ display:'flex', gap:'5px', flexWrap:'wrap' }}>
            {/* Etiquetas */}
            <button onClick={() => setVistaEtiq(!vistaEtiq)}
              style={{ ...S.btnSec, ...(vistaEtiq ? { background:'var(--gold-dim)', color:'var(--gold)' } : {}) }}>
              🏷 {vistaEtiq ? `${selEtiq.size} sel.` : 'Etiquetas'}
            </button>
            {vistaEtiq && selEtiq.size > 0 && (
              <button onClick={() => imprimirEtiq([...selEtiq].map(id => productos.find(p => p.id===id)).filter(Boolean))}
                style={S.btnGold}>
                🖨 Imprimir {selEtiq.size}
              </button>
            )}

            {/* Export */}
            <div style={{ position:'relative' }} className="export-wrap">
              <button style={S.btnSec} onClick={() => {
                const m = document.getElementById('export-menu');
                m.style.display = m.style.display === 'none' ? 'block' : 'none';
              }}>⬇ Exportar</button>
              <div id="export-menu" style={{ display:'none', position:'absolute', top:'34px', right:0,
                background:'var(--bg-card)', border:'1px solid var(--border)', borderRadius:'8px',
                padding:'4px', zIndex:50, minWidth:'140px', boxShadow:'0 8px 24px rgba(0,0,0,0.5)' }}>
                <button onClick={() => { exportarJSON(productos); document.getElementById('export-menu').style.display='none'; }}
                  style={{ display:'block', width:'100%', padding:'7px 12px', background:'none', border:'none',
                    color:'var(--cream)', cursor:'pointer', fontSize:'11px', textAlign:'left', fontFamily:'Inter,sans-serif', borderRadius:'5px' }}>
                  📄 JSON completo
                </button>
                <button onClick={() => { exportarCSV(misProd); document.getElementById('export-menu').style.display='none'; }}
                  style={{ display:'block', width:'100%', padding:'7px 12px', background:'none', border:'none',
                    color:'var(--cream)', cursor:'pointer', fontSize:'11px', textAlign:'left', fontFamily:'Inter,sans-serif', borderRadius:'5px' }}>
                  📊 CSV — esta tienda
                </button>
                <button onClick={() => { exportarCSV(filtrados); document.getElementById('export-menu').style.display='none'; }}
                  style={{ display:'block', width:'100%', padding:'7px 12px', background:'none', border:'none',
                    color:'var(--cream)', cursor:'pointer', fontSize:'11px', textAlign:'left', fontFamily:'Inter,sans-serif', borderRadius:'5px' }}>
                  🔍 CSV — filtrado actual
                </button>
                <div style={{ height:'1px', background:'var(--border)', margin:'4px 0' }}/>
                <button onClick={() => { descargarPlantillaCSV(); document.getElementById('export-menu').style.display='none'; }}
                  style={{ display:'block', width:'100%', padding:'7px 12px', background:'none', border:'none',
                    color:'var(--gold)', cursor:'pointer', fontSize:'11px', textAlign:'left', fontFamily:'Inter,sans-serif', borderRadius:'5px' }}>
                  📋 Plantilla para rellenar
                </button>
              </div>
            </div>

            {/* Import */}
            <button style={S.btnSec} onClick={() => importRef.current.click()}>⬆ Importar</button>
            <input ref={importRef} type="file" accept=".json,.csv" style={{ display:'none' }}
              onChange={e => handleImportar(e.target.files[0])}/>

            <button onClick={() => setModalNuevo(true)} style={S.btnGold}>+ Nuevo</button>
          </div>
        </div>

        {/* Tabla */}
        <div style={{ flex:1, overflowY:'auto' }}>
          <table style={{ width:'100%', borderCollapse:'collapse' }}>
            <thead>
              <tr style={{ position:'sticky', top:0, background:'var(--bg-card)', zIndex:5 }}>
                {vistaEtiq && (
                  <th style={S.th}>
                    <input type="checkbox" style={{ accentColor:'var(--gold)' }}
                      onChange={e => { if (e.target.checked) setSelEtiq(new Set(pagina_items.map(p => p.id))); else setSelEtiq(new Set()); }}/>
                  </th>
                )}
                {['SKU','','Producto','Cat.','Metal','Piedra','Precio','Stock','Estado','','Días'].map((h,i) => (
                  <th key={i} style={{ ...S.th }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {pagina_items.map(p => (
                <tr key={p.id} onClick={() => setSel(p.id === selId ? null : p.id)}
                  style={{ ...S.tr,
                    ...(selId === p.id ? { background:'rgba(201,168,76,0.07)', borderLeft:'2px solid var(--gold)' } : {}),
                    cursor:'pointer' }}>
                  {vistaEtiq && (
                    <td style={S.td} onClick={e => e.stopPropagation()}>
                      <input type="checkbox" checked={selEtiq.has(p.id)}
                        onChange={() => toggleEtiq(p.id)} style={{ accentColor:'var(--gold)' }}/>
                    </td>
                  )}
                  <td style={S.td}>
                    <span style={{ fontFamily:'monospace', fontSize:'10px', color:'var(--cream-3)' }}>{p.sku}</span>
                  </td>
                  <td style={{ ...S.td, width:'32px', padding:'4px' }}>
                    {p.foto_url
                      ? <img src={p.foto_url} alt="" style={{ width:'28px', height:'28px', objectFit:'cover', borderRadius:'4px', border:'1px solid var(--border)', display:'block' }} onError={e => e.target.style.display='none'}/>
                      : <div style={{ width:'28px', height:'28px', borderRadius:'4px', border:'1px solid var(--border)', background:'var(--surface)', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'10px', color:'var(--border)' }}>📷</div>
                    }
                  </td>
                  <td style={{ ...S.td, maxWidth:'180px' }}>
                    <div style={{ color:'var(--cream)', fontSize:'11px', fontWeight:500, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{p.nombre}</div>
                    {p.notas && <div style={{ color:'var(--cream-3)', fontSize:'9px', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{p.notas}</div>}
                  </td>
                  <td style={S.td}><span style={{ fontSize:'10px', color:'var(--cream-2)', padding:'1px 5px', background:'var(--surface)', borderRadius:'4px' }}>{p.categoria}</span></td>
                  <td style={S.td}><span style={{ fontSize:'10px', color:'var(--cream-3)' }}>{p.metal}</span></td>
                  <td style={S.td}><span style={{ fontSize:'10px', color:'var(--cream-3)' }}>{p.piedra||'—'}</span></td>
                  <td style={S.td}><span style={{ color:'var(--gold)', fontWeight:600, fontSize:'11px' }}>{clp(p.precio||0)}</span></td>
                  <td style={S.td} onClick={e => { e.stopPropagation(); setModalStock(p); }}>
                    <span style={{ ...invStyles.stockBadge,
                      ...(p.stock<=0 ? invStyles.stockCero : p.stock<=2 ? invStyles.stockBajo : {}),
                      cursor:'pointer' }} title="Click para ajustar stock">
                      {p.stock||0}
                    </span>
                  </td>
                  <td style={S.td}>
                    <span style={{ fontSize:'9px', padding:'2px 6px', borderRadius:'10px',
                      background: p.estado==='En vitrina' ? 'rgba(39,174,96,0.12)' : 'rgba(100,100,100,0.12)',
                      color: p.estado==='En vitrina' ? '#27ae60' : 'var(--cream-3)' }}>
                      {p.estado}
                    </span>
                  </td>
                  <td style={S.td} onClick={e => e.stopPropagation()}>
                    <button onClick={() => { setEditando({...p}); setSel(p.id); }}
                      style={invStyles.btnEdit}>✏</button>
                  </td>
                  <td style={S.td}>
                    {p.fechaIngreso && (() => {
                      const dias = Math.floor((Date.now() - new Date(p.fechaIngreso).getTime()) / 86400000);
                      return <span style={{ fontSize:'9px', padding:'1px 5px', borderRadius:'10px',
                        background: dias>180 ? 'rgba(192,57,43,0.12)' : dias>90 ? 'rgba(243,156,18,0.12)' : 'rgba(39,174,96,0.1)',
                        color: dias>180 ? '#c0392b' : dias>90 ? '#f39c12' : '#27ae60' }}>
                        {dias}d
                      </span>;
                    })()}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Paginación */}
        <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center',
          padding:'8px 12px', borderTop:'1px solid var(--border)', background:'var(--bg-card)', flexShrink:0 }}>
          <button onClick={() => setPagina(p => Math.max(0, p-1))} disabled={pagina===0}
            style={{ ...S.btnSec, opacity:pagina===0?0.3:1 }}>← Anterior</button>
          <span style={{ color:'var(--cream-3)', fontSize:'11px' }}>
            Página {pagina+1} de {totalPags||1} · {filtrados.length} resultados
          </span>
          <button onClick={() => setPagina(p => Math.min(totalPags-1, p+1))} disabled={pagina>=totalPags-1}
            style={{ ...S.btnSec, opacity:pagina>=totalPags-1?0.3:1 }}>Siguiente →</button>
        </div>
      </div>

      {/* ── Panel Detalle / Edición ── */}
      {(selProd || editando) && (() => {
        const p = editando || selProd;
        const isEdit = !!editando;

        function F({ l, v, k, type, opts, readOnly, area }) {
          return (
            <div style={{ marginBottom:'8px' }}>
              <div style={{ fontSize:'10px', color:'var(--cream-3)', marginBottom:'3px' }}>{l}</div>
              {isEdit
                ? readOnly
                  ? <div style={{ color:'var(--cream-3)', fontSize:'11px', padding:'5px 8px', background:'var(--bg)', borderRadius:'6px', border:'1px solid var(--border)' }}>{editando[k]||'—'}</div>
                  : area
                  ? <textarea style={{ ...calcStyles.input, padding:'5px 8px', fontSize:'11px', width:'100%', height:'60px', resize:'vertical' }}
                      value={editando[k]||''} onChange={e => setEditando(prev => ({...prev, [k]:e.target.value}))}/>
                  : opts
                  ? <select style={{ ...invStyles.select, width:'100%', fontSize:'11px' }}
                      value={editando[k]||''} onChange={e => setEditando(prev => ({...prev, [k]:e.target.value}))}>
                      {opts.map(o => <option key={o}>{o}</option>)}
                    </select>
                  : <input type={type||'text'} style={{ ...calcStyles.input, padding:'5px 8px', fontSize:'11px' }}
                      value={editando[k]??''} onChange={e => setEditando(prev => ({...prev, [k]:type==='number'?parseFloat(e.target.value)||0:e.target.value}))}/>
                : <div style={{ color:'var(--cream)', fontSize:'11px', whiteSpace:'pre-wrap' }}>{v||'—'}</div>
              }
            </div>
          );
        }

        return (
          <div style={{ ...S.detalle, width:'290px' }}>
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:'12px', flexShrink:0 }}>
              <div style={{ fontFamily:'Cormorant Garamond,serif', fontSize:'16px', fontWeight:600, color:'var(--cream)' }}>
                {isEdit ? 'Editando' : 'Detalle'}
              </div>
              <div style={{ display:'flex', gap:'4px' }}>
                {!isEdit && <button onClick={() => setEditando({...p})} style={S.btnSec}>✏ Editar</button>}
                {isEdit  && <button onClick={guardarEdit} style={S.btnGold}>✓ Guardar</button>}
                {isEdit  && <button onClick={() => setEditando(null)} style={S.btnSec}>✕</button>}
                {!isEdit && <button onClick={() => setSel(null)} style={S.btnSec}>✕</button>}
              </div>
            </div>

            <div style={{ overflowY:'auto', flex:1 }}>
              {/* SKU + foto */}
              <div style={{ display:'flex', gap:'10px', marginBottom:'12px' }}>
                <FotoManager
                  prod={isEdit ? editando : p}
                  isEdit={isEdit}
                  onFoto={url => actualizarFoto(p.id, url)}
                />
                <div style={{ flex:1 }}>
                  {isEdit ? (() => {
                    const dupEdit = buscarSkuDuplicado(editando.sku, editando.id);
                    return (
                      <div style={{ marginBottom:'4px' }}>
                        <input
                          style={{ ...calcStyles.input, padding:'4px 7px', fontFamily:'monospace', fontWeight:700, color:'var(--gold)', fontSize:'13px', borderColor: dupEdit ? '#c0392b' : undefined }}
                          value={editando.sku||''}
                          onChange={e => setEditando(prev => ({ ...prev, sku: e.target.value.toUpperCase() }))}
                        />
                        {dupEdit && (
                          <div style={{ marginTop:'3px', fontSize:'10px', color:'#c0392b' }}>
                            ⚠ Ya existe: {dupEdit.sku} — {dupEdit.nombre}
                          </div>
                        )}
                      </div>
                    );
                  })() : (
                    <div style={{ fontFamily:'monospace', fontSize:'13px', fontWeight:700, color:'var(--gold)', marginBottom:'3px' }}>{p.sku}</div>
                  )}
                  <div style={{ color:'var(--cream)', fontSize:'11px', fontWeight:500, lineHeight:'1.3' }}>{p.nombre}</div>
                  <div style={{ color:'var(--cream-3)', fontSize:'10px', marginTop:'2px' }}>{p.categoria} · {p.metal}</div>
                </div>
              </div>

              {/* Campos */}
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'2px' }}>
                <F l="Categoría"    k="categoria"  v={p.categoria}   opts={CATS_MAESTRAS}/>
                <F l="Metal"        k="metal"       v={p.metal}       opts={METALES_MAESTROS.map(m=>m.name)}/>
                <F l="Piedra"       k="piedra"      v={p.piedra}      opts={PIEDRAS_MAESTRAS}/>
                <F l="Talla/Medida" k="talla"       v={p.talla}/>
                <F l="Peso (g)"     k="peso"        v={p.peso}        type="number"/>
                <F l="Largo (cm)"   k="largo_cm"    v={p.largo_cm}    type="number"/>
                <F l="Costo CLP"    k="costo"       v={clp(p.costo)}  type="number"/>
                <F l="Precio CLP"   k="precio"      v={clp(p.precio)} type="number"/>
                <F l="Stock"        k="stock"       v={p.stock}       type="number"/>
                <F l="Estado"       k="estado"      v={p.estado}      opts={ESTADOS_PROD}/>
              </div>

              <F l="Ubicación (vitrina/bodega)" k="ubicacion" v={p.ubicacion||'Sin asignar'}/>
              <F l="Insumo/Empaque" k="insumo_asociado" v={p.insumo_asociado}
                opts={['Sin empaque','Caja anillo terciopelo negro','Caja collar rígida blanca','Bolsa organza dorada','Bolsa papel kraft','Estuche cuero','Otro']}/>
              <F l="Venta online" k="venta_online" v={p.venta_online}
                opts={['No','Sí — tienda web','Sí — marketplace']}/>
              <F l="Proveedor" k="proveedor" v={p.proveedor}/>
              <F l="Notas internas" k="notas" v={p.notas}/>
              <F l="Observaciones" k="observaciones" v={p.observaciones} area/>

              {/* Speech */}
              <div style={{ marginTop:'10px', borderTop:'1px solid var(--border)', paddingTop:'10px', marginBottom:'8px' }}>
                <div style={{ fontSize:'11px', color:'var(--gold)', fontWeight:600, marginBottom:'5px' }}>✦ Speech de Venta</div>
                {isEdit
                  ? <textarea style={{ ...calcStyles.input, width:'100%', height:'70px', fontSize:'11px', lineHeight:'1.5' }}
                      value={editando.speech||''} onChange={e => setEditando(prev => ({...prev, speech:e.target.value}))}
                      placeholder="Argumento de venta…"/>
                  : <div style={{ background:'var(--surface)', borderRadius:'8px', padding:'10px', fontSize:'11px',
                      color:'var(--cream-2)', lineHeight:'1.6', borderLeft:'2px solid var(--gold)', minHeight:'40px' }}>
                      {p.speech || <em style={{ color:'var(--cream-3)' }}>Sin speech.</em>}
                    </div>
                }
              </div>

              {/* Acciones rápidas */}
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'5px', marginTop:'8px' }}>
                <button onClick={() => imprimirEtiq([p])}
                  style={{ ...S.btnSec, padding:'8px', textAlign:'center' }}>
                  🏷 Etiqueta 55×12
                </button>
                <button onClick={() => setModalStock(p)}
                  style={{ ...S.btnSec, padding:'8px', textAlign:'center' }}>
                  📦 Ajustar stock
                </button>
              </div>

              {/* Eliminar */}
              {!isEdit && (
                <button onClick={() => setConfirmDel(p.id)}
                  style={{ ...S.btnSec, width:'100%', marginTop:'6px', color:'#c0392b',
                    border:'1px solid rgba(192,57,43,0.3)', padding:'7px' }}>
                  🗑 Eliminar producto
                </button>
              )}
            </div>
          </div>
        );
      })()}

      {/* ── Modal Nuevo Producto ── */}
      {modalNuevo && (
        <div style={posStyles.overlay} onClick={e => e.target===e.currentTarget && setModalNuevo(false)}>
          <div style={{ ...posStyles.modalBox, maxWidth:'540px' }}>
            <div style={{ ...posStyles.modalHeader, marginBottom:'14px' }}>
              <span style={{ fontFamily:'Cormorant Garamond,serif', fontSize:'22px', fontWeight:600 }}>
                Nuevo Producto
              </span>
              <button onClick={() => setModalNuevo(false)} style={posStyles.clearBtn}>✕</button>
            </div>

            {/* SKU — propuesto automáticamente, editable por el usuario */}
            {(() => {
              const propuesto = generarSKU(nuevo.metal_code, nuevo.categoria, nuevo.piedra, productos);
              const valorActual = nuevo.skuManual ? nuevo.sku : propuesto;
              const dupActual = nuevo.skuManual ? buscarSkuDuplicado(valorActual, null) : null;
              return (
                <div style={{ background:'var(--surface)', borderRadius:'8px', padding:'10px', marginBottom:'14px' }}>
                  <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:'6px' }}>
                    <span style={{ color:'var(--cream-3)', fontSize:'11px' }}>Código SKU {nuevo.skuManual?'(editado por ti)':'(propuesto automáticamente — puedes cambiarlo)'}:</span>
                    {nuevo.skuManual && (
                      <button onClick={() => setNuevo(n => ({ ...n, sku:'', skuManual:false }))}
                        style={{ background:'none', border:'none', color:'var(--gold)', fontSize:'10px', cursor:'pointer', textDecoration:'underline' }}>
                        usar propuesto
                      </button>
                    )}
                  </div>
                  <input
                    style={{ ...calcStyles.input, fontFamily:'monospace', fontWeight:700, color:'var(--gold)', fontSize:'16px', borderColor: dupActual ? '#c0392b' : undefined }}
                    value={valorActual}
                    onChange={e => setNuevo(n => ({ ...n, sku: e.target.value.toUpperCase(), skuManual:true }))}
                  />
                  {dupActual && (
                    <div style={{ marginTop:'6px', fontSize:'11px', color:'#c0392b' }}>
                      ⚠ Este código ya existe: {dupActual.sku} — {dupActual.nombre}. Debes elegir uno diferente.
                    </div>
                  )}
                </div>
              );
            })()}

            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'8px' }}>
              <div style={{ gridColumn:'1/-1' }}>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Nombre completo *</div>
                <input style={calcStyles.input} placeholder="Ej: Anillo de plata con circón blanco"
                  value={nuevo.nombre} onChange={e => setNuevo(n => ({ ...n, nombre:e.target.value, nombre_corto:e.target.value }))} autoFocus/>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Categoría *</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.categoria}
                  onChange={e => setNuevo(n => ({ ...n, categoria:e.target.value }))}>
                  {CATS_MAESTRAS.map(c => <option key={c}>{c}</option>)}
                </select>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Metal *</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.metal}
                  onChange={e => {
                    const m = METALES_MAESTROS.find(x => x.name===e.target.value) || METALES_MAESTROS[0];
                    setNuevo(n => ({ ...n, metal:e.target.value, metal_code:m.code }));
                  }}>
                  {METALES_MAESTROS.map(m => <option key={m.code}>{m.name}</option>)}
                </select>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Piedra/Material</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.piedra}
                  onChange={e => setNuevo(n => ({ ...n, piedra:e.target.value }))}>
                  <option value="">Sin piedra</option>
                  {PIEDRAS_MAESTRAS.map(p => <option key={p}>{p}</option>)}
                </select>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Talla/Medida</div>
                <input style={calcStyles.input} placeholder="Ej: 16, 45cm, ajustable"
                  value={nuevo.talla} onChange={e => setNuevo(n => ({ ...n, talla:e.target.value }))}/>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Costo CLP</div>
                <input type="number" style={calcStyles.input} value={nuevo.costo}
                  onChange={e => setNuevo(n => ({ ...n, costo:parseInt(e.target.value)||0 }))}/>
              </div>
              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Precio venta CLP *</div>
                <input type="number" style={calcStyles.input} value={nuevo.precio}
                  onChange={e => setNuevo(n => ({ ...n, precio:parseInt(e.target.value)||0 }))}/>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Stock inicial</div>
                <input type="number" style={calcStyles.input} value={nuevo.stock} min="0"
                  onChange={e => setNuevo(n => ({ ...n, stock:parseInt(e.target.value)||0 }))}/>
              </div>
              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Estado</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.estado}
                  onChange={e => setNuevo(n => ({ ...n, estado:e.target.value }))}>
                  {ESTADOS_PROD.map(e => <option key={e}>{e}</option>)}
                </select>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Peso (g)</div>
                <input type="number" style={calcStyles.input} value={nuevo.peso||''} step="0.01"
                  onChange={e => setNuevo(n => ({ ...n, peso:parseFloat(e.target.value)||'' }))}/>
              </div>
              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Proveedor</div>
                <input style={calcStyles.input} placeholder="Nombre proveedor"
                  value={nuevo.proveedor||''} onChange={e => setNuevo(n => ({ ...n, proveedor:e.target.value }))}/>
              </div>

              <div style={{ gridColumn:'1/-1' }}>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Tienda</div>
                <div style={{ display:'flex', gap:'6px' }}>
                  {TIENDAS.map(t => (
                    <button key={t.id} onClick={() => setNuevo(n => ({ ...n, tienda:t.id }))}
                      style={{ ...calcStyles.chip, flex:1, textAlign:'center',
                        ...(nuevo.tienda===t.id ? calcStyles.chipAct : {}) }}>
                      {t.sigla} — {t.nombre.split(' ').slice(0,2).join(' ')}
                    </button>
                  ))}
                </div>
              </div>

              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Empaque</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.insumo_asociado}
                  onChange={e => setNuevo(n => ({ ...n, insumo_asociado:e.target.value }))}>
                  {['Sin empaque','Caja anillo terciopelo negro','Caja collar rígida blanca','Bolsa organza dorada','Bolsa papel kraft','Estuche cuero','Otro'].map(o => <option key={o}>{o}</option>)}
                </select>
              </div>
              <div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Venta online</div>
                <select style={{ ...invStyles.select, width:'100%' }} value={nuevo.venta_online}
                  onChange={e => setNuevo(n => ({ ...n, venta_online:e.target.value }))}>
                  {['No','Sí — tienda web','Sí — marketplace'].map(o => <option key={o}>{o}</option>)}
                </select>
              </div>

              <div style={{ gridColumn:'1/-1' }}>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginBottom:'3px' }}>Notas internas</div>
                <input style={calcStyles.input} placeholder="Proveedor, detalles técnicos…"
                  value={nuevo.notas} onChange={e => setNuevo(n => ({ ...n, notas:e.target.value }))}/>
              </div>
            </div>

            <button onClick={agregarProducto}
              style={{ ...posStyles.cobrarBtn, width:'100%', marginTop:'14px' }}>
              ✦ Crear Producto
            </button>
          </div>
        </div>
      )}

      {/* ── Modal Ajuste Stock ── */}
      {modalStock && (
        <ModalAjusteStock
          prod={modalStock}
          onClose={() => setModalStock(null)}
          onGuardar={confirmarAjusteStock}
        />
      )}

      {/* ── Modal Confirmar Eliminación ── */}
      {confirmDel && (
        <div style={posStyles.overlay} onClick={e => e.target===e.currentTarget && setConfirmDel(null)}>
          <div style={{ ...posStyles.modalBox, maxWidth:'360px', textAlign:'center' }}>
            <div style={{ fontSize:'36px', marginBottom:'12px' }}>⚠️</div>
            <div style={{ fontFamily:'Cormorant Garamond,serif', fontSize:'20px', fontWeight:600, color:'var(--cream)', marginBottom:'8px' }}>
              ¿Eliminar producto?
            </div>
            <div style={{ color:'var(--cream-3)', fontSize:'12px', marginBottom:'20px' }}>
              {(() => { const p = productos.find(x => x.id===confirmDel); return p ? `${p.sku} — ${p.nombre}` : ''; })()}
              <br/>Esta acción no se puede deshacer.
            </div>
            <div style={{ display:'flex', gap:'8px' }}>
              <button onClick={() => setConfirmDel(null)}
                style={{ ...inv2Styles.btnSec, flex:1, padding:'10px' }}>
                Cancelar
              </button>
              <button onClick={() => eliminarProducto(confirmDel)}
                style={{ flex:1, padding:'10px', background:'rgba(192,57,43,0.8)', border:'none',
                  borderRadius:'8px', color:'white', fontWeight:700, cursor:'pointer', fontSize:'12px' }}>
                Sí, eliminar
              </button>
            </div>
          </div>
        </div>
      )}

      {/* ── Modal de importación con detección de conflictos ────────────────── */}
      {modalImport && (
        <div style={posStyles.overlay} onClick={e => e.target===e.currentTarget && setModalImport(null)}>
          <div style={{ ...posStyles.modalBox, maxWidth:'520px', maxHeight:'85vh', display:'flex', flexDirection:'column' }}>

            {/* Header */}
            <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', marginBottom:'16px', flexShrink:0 }}>
              <div>
                <div style={{ fontFamily:'Cormorant Garamond,serif', fontSize:'20px', fontWeight:600, color:'var(--cream)' }}>
                  Importar inventario
                </div>
                <div style={{ fontSize:'11px', color:'var(--cream-3)', marginTop:'2px' }}>
                  Revisá el resumen antes de confirmar
                </div>
              </div>
              <button onClick={() => setModalImport(null)} style={posStyles.clearBtn}>✕</button>
            </div>

            {/* Resumen */}
            <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:'8px', marginBottom:'14px', flexShrink:0 }}>
              <div style={{ background:'rgba(39,174,96,0.1)', border:'1px solid rgba(39,174,96,0.3)', borderRadius:'8px', padding:'12px', textAlign:'center' }}>
                <div style={{ color:'#27ae60', fontSize:'28px', fontWeight:700 }}>{modalImport.nuevos.length}</div>
                <div style={{ color:'var(--cream-2)', fontSize:'11px' }}>productos nuevos</div>
                <div style={{ color:'var(--cream-3)', fontSize:'10px', marginTop:'2px' }}>SKU no existe → se agregarán</div>
              </div>
              <div style={{ background:'rgba(230,126,34,0.1)', border:'1px solid rgba(230,126,34,0.3)', borderRadius:'8px', padding:'12px', textAlign:'center' }}>
                <div style={{ color:'#e67e22', fontSize:'28px', fontWeight:700 }}>{modalImport.conflictos.length}</div>
                <div style={{ color:'var(--cream-2)', fontSize:'11px' }}>conflictos de SKU</div>
                <div style={{ color:'var(--cream-3)', fontSize:'10px', marginTop:'2px' }}>Ya existen — elige qué hacer</div>
              </div>
            </div>

            {/* Lista de conflictos */}
            {modalImport.conflictos.length > 0 && (
              <div style={{ flex:1, overflowY:'auto', marginBottom:'14px', border:'1px solid var(--border)', borderRadius:'8px' }}>
                <div style={{ padding:'8px 12px', background:'var(--surface)', fontSize:'10px', color:'var(--cream-3)',
                  fontWeight:600, letterSpacing:'0.5px', borderBottom:'1px solid var(--border)', position:'sticky', top:0 }}>
                  PRODUCTOS CON CONFLICTO
                </div>
                {modalImport.conflictos.map((p, i) => {
                  const exist = productos.find(x => x.sku && x.sku.toLowerCase() === (p.sku||'').toLowerCase());
                  return (
                    <div key={i} style={{ display:'flex', justifyContent:'space-between', alignItems:'center',
                      padding:'8px 12px', borderBottom:'1px solid var(--border)', background: i%2===0?'var(--bg-card)':'var(--bg)' }}>
                      <div>
                        <span style={{ color:'var(--gold)', fontSize:'11px', fontFamily:'monospace', fontWeight:700 }}>{p.sku}</span>
                        <span style={{ color:'var(--cream-2)', fontSize:'11px', marginLeft:'8px' }}>{p.nombre}</span>
                      </div>
                      {exist && (
                        <div style={{ fontSize:'10px', color:'var(--cream-3)', textAlign:'right' }}>
                          <span style={{ color:'var(--cream-3)' }}>stock: {exist.stock}</span>
                          <span style={{ color:'#e67e22', margin:'0 4px' }}>→</span>
                          <span style={{ color:'#27ae60' }}>{p.stock}</span>
                          {exist.precio !== p.precio && (
                            <span style={{ marginLeft:'6px', color:'var(--cream-3)' }}>
                              · precio: <span style={{ color:'#e67e22' }}>{clp(exist.precio)}</span>→<span style={{ color:'#27ae60' }}>{clp(p.precio)}</span>
                            </span>
                          )}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            )}

            {/* Opciones */}
            <div style={{ display:'flex', flexDirection:'column', gap:'6px', flexShrink:0 }}>
              {modalImport.nuevos.length > 0 && modalImport.conflictos.length === 0 && (
                <button onClick={() => aplicarImport('solo_nuevos')}
                  style={{ padding:'11px', background:'rgba(39,174,96,0.15)', border:'1px solid rgba(39,174,96,0.4)',
                    borderRadius:'8px', color:'#27ae60', fontWeight:700, cursor:'pointer', fontSize:'12px', fontFamily:'Inter,sans-serif' }}>
                  ✓ Agregar {modalImport.nuevos.length} productos nuevos
                </button>
              )}
              {modalImport.conflictos.length > 0 && (
                <>
                  {modalImport.nuevos.length > 0 && (
                    <button onClick={() => aplicarImport('solo_nuevos')}
                      style={{ padding:'10px', background:'rgba(39,174,96,0.12)', border:'1px solid rgba(39,174,96,0.3)',
                        borderRadius:'8px', color:'#27ae60', fontWeight:600, cursor:'pointer', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
                      + Solo agregar {modalImport.nuevos.length} nuevos · ignorar conflictos
                    </button>
                  )}
                  <button onClick={() => aplicarImport('solo_stock')}
                    style={{ padding:'10px', background:'rgba(41,128,185,0.12)', border:'1px solid rgba(41,128,185,0.3)',
                      borderRadius:'8px', color:'#2980b9', fontWeight:600, cursor:'pointer', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
                    📦 Actualizar solo stock de los {modalImport.conflictos.length} existentes (+ agregar nuevos)
                  </button>
                  <button onClick={() => aplicarImport('actualizar_todo')}
                    style={{ padding:'10px', background:'rgba(230,126,34,0.12)', border:'1px solid rgba(230,126,34,0.3)',
                      borderRadius:'8px', color:'#e67e22', fontWeight:600, cursor:'pointer', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
                    🔄 Actualizar TODO de los existentes: precio, stock, datos (+ agregar nuevos)
                  </button>
                  <button onClick={() => { if (confirm(`¿Reemplazar COMPLETAMENTE el inventario con ${modalImport.data.length} productos? Esto elimina lo actual.`)) aplicarImport('reemplazar'); }}
                    style={{ padding:'10px', background:'rgba(192,57,43,0.1)', border:'1px solid rgba(192,57,43,0.3)',
                      borderRadius:'8px', color:'#c0392b', fontWeight:600, cursor:'pointer', fontSize:'11px', fontFamily:'Inter,sans-serif' }}>
                    ⚠ Reemplazar inventario completo ({modalImport.data.length} productos)
                  </button>
                </>
              )}
              <button onClick={() => setModalImport(null)}
                style={{ ...inv2Styles.btnSec, padding:'10px', textAlign:'center' }}>
                Cancelar
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Estilos locales del módulo (complementan inv2Styles de data.jsx) ─────────
// Se asignan a inv2Styles para que el componente los encuentre en S = inv2Styles
Object.assign(inv2Styles, {
  sidebar: {
    display:'flex', flexDirection:'column',
    borderRight:'1px solid var(--border)', overflow:'hidden',
    background:'var(--bg-sidebar)', flexShrink:0,
  },
  searchInput: {
    background:'var(--surface)', border:'1px solid var(--border)',
    borderRadius:'6px', padding:'7px 10px',
    color:'var(--cream)', fontSize:'12px', outline:'none',
  },
  filterBtn: {
    display:'flex', alignItems:'center', gap:'4px',
    padding:'5px 8px', borderRadius:'5px',
    background:'transparent', border:'none',
    color:'var(--cream-2)', cursor:'pointer',
    fontSize:'11px', fontFamily:'Inter,sans-serif',
    textAlign:'left', width:'100%',
  },
  filterBtnAct: {
    background:'var(--gold-dim)', color:'var(--cream)',
    borderLeft:'2px solid var(--gold)',
  },
  toolbar: {
    display:'flex', justifyContent:'space-between', alignItems:'center',
    padding:'8px 12px', borderBottom:'1px solid var(--border)',
    flexShrink:0, background:'var(--bg-card)',
  },
  detalle: {
    width:'290px', display:'flex', flexDirection:'column',
    padding:'14px', overflow:'hidden', flexShrink:0,
    borderLeft:'1px solid var(--border)', background:'var(--bg)',
  },
});

// Exportar al scope global
Object.assign(window, {
  InventarioReal,
  exportarJSON, exportarCSV,
});
