/* === Inventario — gestiona artículos y entradas/salidas por área ===
   El stock actual se calcula sumando entradas y restando salidas de los
   movimientos del item. Para una primera versión simple sin foto. */

const INVENTORY_CATEGORIES = {
  amallaves: ["Ama de llaves", "Items Máximo"],
  bar:       ["Vinos", "Licores", "Dr. Casas Premium", "Casa de Casas items"],
};

// Subcategorias opcionales por (area, categoria). Cuando existe la lista, el
// editor muestra un select adicional. El display tambien la usa para
// distinguir dentro del grupo.
const INVENTORY_SUBCATEGORIES = {
  "bar|Vinos": ["Blanco", "Tinto", "Rosado", "Espumoso"],
};
const subcatsFor = (area, cat) => INVENTORY_SUBCATEGORIES[`${area}|${cat}`] || [];

// Stock del item = sum(entradas) - sum(salidas)
const __stockOf = (itemId, movements) => {
  let s = 0;
  for (const m of (movements || [])) {
    if (m.itemId !== itemId) continue;
    if (m.type === "entrada") s += Number(m.qty) || 0;
    else if (m.type === "salida") s -= Number(m.qty) || 0;
  }
  return s;
};

const InventoryPanel = ({ areaId, areaLabel, items, movements, user, role, canEdit, upsertInventoryItem, removeInventoryItem, addInventoryMovement, removeInventoryMovement }) => {
  const [editingItem, setEditingItem] = React.useState(null); // null | "new" | item
  const [activeItem, setActiveItem] = React.useState(null);   // item activo abierto en drawer
  const [filter, setFilter] = React.useState("todos");        // "todos" | nombre de categoría
  const [search, setSearch] = React.useState("");
  const [reportOpen, setReportOpen] = React.useState(false);

  const areaItems = items.filter(i => i.area === areaId);
  const categories = INVENTORY_CATEGORIES[areaId] || [];
  // Si un item tiene una categoria que ya no existe en el diccionario actual
  // (p.ej. "Cristalería" del bar viejo), la mostramos como "Sin categoría"
  // para que los headers viejos no aparezcan. Al editar el item se puede
  // reasignar a una de las nuevas.
  const catOf = (i) => {
    if (i.category && categories.includes(i.category)) return i.category;
    return "Sin categoría";
  };

  const filtered = areaItems.filter(i => {
    if (filter !== "todos" && catOf(i) !== filter) return false;
    if (search && !(i.name || "").toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  // Agrupa por categoría (respetando el orden del diccionario)
  const grouped = {};
  filtered.forEach(i => {
    const cat = catOf(i);
    if (!grouped[cat]) grouped[cat] = [];
    grouped[cat].push(i);
  });

  return (
    <div className="cdc-card" style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, marginTop: -18 }}>
      <div className="cdc-card__head">
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <I.Box size={18} />
          <div className="cdc-card__title">Inventario — {areaLabel}</div>
          <span style={{ fontSize: 12, color: "var(--cdc-ink-3)" }}>{areaItems.length} artículo{areaItems.length === 1 ? "" : "s"}</span>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          {(items || []).filter(i => i.area === areaId).length > 0 && (
            <button className="cdc-pill" onClick={() => setReportOpen(true)} title="Reporte PDF de movimientos por periodo">
              <I.Send size={14} /> Reporte PDF
            </button>
          )}
          {canEdit && (
            <button className="cdc-btn cdc-btn--coral" onClick={() => setEditingItem("new")}>
              <I.Plus size={14} /> Nuevo artículo
            </button>
          )}
        </div>
      </div>

      {areaItems.length > 0 && (
        <div style={{ padding: "10px 18px 4px", display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 6, background: "white", border: "1px solid var(--cdc-border)", borderRadius: 999, padding: "4px 10px" }}>
            <I.Search size={13} style={{ color: "var(--cdc-ink-3)" }} />
            <input
              className="cdc-input"
              placeholder="Buscar artículo…"
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              style={{ border: 0, padding: 0, width: 180, background: "transparent", fontSize: 13 }}
            />
          </div>
          <button className="cdc-chip" aria-pressed={filter === "todos"} onClick={() => setFilter("todos")}>Todas</button>
          {categories.map(c => (
            <button key={c} className="cdc-chip" aria-pressed={filter === c} onClick={() => setFilter(c)}>{c}</button>
          ))}
        </div>
      )}

      {areaItems.length === 0 ? (
        <div className="cdc-empty">
          <I.Box size={42} />
          <div className="cdc-empty__title">Sin artículos en el inventario</div>
          {canEdit && (
            <button className="cdc-btn cdc-btn--coral" onClick={() => setEditingItem("new")}>
              <I.Plus size={14} /> Registrar primer artículo
            </button>
          )}
        </div>
      ) : filtered.length === 0 ? (
        <div className="cdc-empty">
          <I.Box size={42} />
          <div className="cdc-empty__title">Sin resultados</div>
          <div style={{ fontSize: 13, color: "var(--cdc-ink-3)" }}>Ajusta el filtro o la búsqueda.</div>
        </div>
      ) : (
        <div style={{ padding: "10px 18px 18px", display: "flex", flexDirection: "column", gap: 14 }}>
          {Object.keys(grouped).map(cat => {
            // Dentro de la categoria, si hay subcategorias definidas para
            // ella, agrupamos por subcategoria — respetando el orden del
            // diccionario y dejando "Sin especificar" al final.
            const subs = subcatsFor(areaId, cat);
            const renderItem = (it) => {
              const stock = __stockOf(it.id, movements);
              return (
                <button
                  key={it.id}
                  onClick={() => setActiveItem(it)}
                  style={{
                    background: "white", border: "1px solid var(--cdc-border)", borderRadius: 12,
                    padding: 14, textAlign: "left", display: "grid", gridTemplateColumns: it.photo ? "56px 1fr" : "1fr", gap: 12, alignItems: "center",
                    cursor: "pointer",
                  }}
                >
                  {it.photo && (
                    <img src={it.photo} alt="" style={{ width: 56, height: 56, objectFit: "cover", borderRadius: 8, border: "1px solid var(--cdc-border-soft)" }} />
                  )}
                  <div style={{ minWidth: 0, display: "flex", flexDirection: "column", gap: 4 }}>
                    <div style={{ display: "flex", justifyContent: "space-between", gap: 8, alignItems: "flex-start" }}>
                      <span style={{ fontWeight: 700, fontSize: 14, color: "var(--cdc-ink)" }}>{it.name}</span>
                      <span style={{ fontFamily: "var(--cdc-display)", fontSize: 22, fontWeight: 600, color: stock < 0 ? "var(--cdc-overdue)" : "var(--cdc-ink)" }}>{stock}</span>
                    </div>
                    <div style={{ fontSize: 11.5, color: "var(--cdc-ink-3)" }}>
                      {it.unit ? `Unidad: ${it.unit}` : "Sin unidad"}
                    </div>
                    {it.notes && <div style={{ fontSize: 12, color: "var(--cdc-ink-3)", lineHeight: 1.4 }}>{it.notes}</div>}
                  </div>
                </button>
              );
            };
            const gridProps = { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: 10 };
            if (subs.length === 0) {
              return (
                <div key={cat}>
                  <div style={{ fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", fontWeight: 700, color: "var(--cdc-ink-3)", marginBottom: 8 }}>{cat}</div>
                  <div style={gridProps}>{grouped[cat].map(renderItem)}</div>
                </div>
              );
            }
            // Con subcategorias: buckets por subcategoria y bucket final para
            // items sin subcategoria definida.
            const bySub = {};
            grouped[cat].forEach(it => {
              const s = it.subcategory && subs.includes(it.subcategory) ? it.subcategory : "Sin especificar";
              if (!bySub[s]) bySub[s] = [];
              bySub[s].push(it);
            });
            const subOrder = [...subs, "Sin especificar"].filter(s => bySub[s] && bySub[s].length > 0);
            return (
              <div key={cat}>
                <div style={{ fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", fontWeight: 700, color: "var(--cdc-ink-3)", marginBottom: 8 }}>{cat}</div>
                <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                  {subOrder.map(s => (
                    <div key={s}>
                      <div style={{ fontSize: 12, color: "var(--cdc-ink-2)", fontWeight: 600, marginBottom: 6, paddingLeft: 4, borderLeft: "3px solid var(--cdc-coral)" }}>
                        <span style={{ marginLeft: 6 }}>{s}</span>
                        <span style={{ marginLeft: 6, color: "var(--cdc-ink-4)", fontWeight: 500, fontSize: 11 }}>{bySub[s].length}</span>
                      </div>
                      <div style={gridProps}>{bySub[s].map(renderItem)}</div>
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      )}

      {editingItem && (
        <InventoryItemDrawer
          item={editingItem === "new" ? null : editingItem}
          areaId={areaId}
          categories={categories}
          user={user}
          onClose={() => setEditingItem(null)}
          onSave={(data) => {
            const id = data.id || `inv-${areaId}-${Date.now()}`;
            const payload = { ...data, id, area: areaId, createdAt: data.createdAt || TODAY_ISO, createdBy: data.createdBy || user.id };
            if (upsertInventoryItem) upsertInventoryItem(payload);
            setEditingItem(null);
          }}
          onRemove={() => {
            if (!window.confirm(`¿Eliminar "${editingItem.name}"?\nSe borrarán también todos sus movimientos.`)) return;
            if (removeInventoryItem) removeInventoryItem(editingItem.id);
            setEditingItem(null);
          }}
        />
      )}

      {reportOpen && (
        <InventoryReportDialog
          areaId={areaId}
          areaLabel={areaLabel}
          items={items}
          movements={movements}
          requestedBy={user.name}
          onClose={() => setReportOpen(false)}
        />
      )}

      {activeItem && (
        <InventoryDetailDrawer
          item={activeItem}
          movements={movements.filter(m => m.itemId === activeItem.id)}
          user={user}
          canEdit={canEdit}
          stock={__stockOf(activeItem.id, movements)}
          onClose={() => setActiveItem(null)}
          onEdit={() => { setEditingItem(activeItem); setActiveItem(null); }}
          onAddMovement={(mov) => {
            const id = mov.id || `mov-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
            if (addInventoryMovement) addInventoryMovement({ ...mov, id, itemId: activeItem.id });
          }}
          onRemoveMovement={(id) => {
            if (!window.confirm("¿Eliminar este movimiento?")) return;
            if (removeInventoryMovement) removeInventoryMovement(id);
          }}
        />
      )}
    </div>
  );
};

const InventoryItemDrawer = ({ item, areaId, categories, user, onClose, onSave, onRemove }) => {
  const [f, setF] = React.useState(item || {
    name: "", category: categories[0] || "", unit: "pza", notes: "", photo: null,
  });
  const u = (k, v) => setF(x => ({ ...x, [k]: v }));

  // Comprime y guarda la foto de la etiqueta como data URL (JPEG ~70%, max
  // 900px) — mismo patron que las compras del yate, evita subir imagenes de
  // varios megas y las mantiene visibles offline.
  const handlePhotoFile = (file) => {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (ev) => {
      const img = new Image();
      img.onload = () => {
        const maxSize = 900;
        let w = img.width, h = img.height;
        if (w > h && w > maxSize) { h = h * (maxSize / w); w = maxSize; }
        else if (h > maxSize) { w = w * (maxSize / h); h = maxSize; }
        const canvas = document.createElement("canvas");
        canvas.width = w; canvas.height = h;
        canvas.getContext("2d").drawImage(img, 0, 0, w, h);
        u("photo", canvas.toDataURL("image/jpeg", 0.7));
      };
      img.src = ev.target.result;
    };
    reader.readAsDataURL(file);
  };

  return (
    <div className="cdc-overlay" onClick={onClose}>
      <div className="cdc-drawer" onClick={(e) => e.stopPropagation()}>
        <div className="cdc-drawer__head">
          <div className="cdc-drawer__title">{item ? "Editar artículo" : "Nuevo artículo"}</div>
          <button className="cdc-iconbtn" onClick={onClose}><I.X size={18} /></button>
        </div>
        <div className="cdc-drawer__body">
          <div className="cdc-field">
            <label>Nombre</label>
            <input className="cdc-input" placeholder="Ej: Toalla blanca grande" value={f.name || ""} onChange={(e) => u("name", e.target.value)} />
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 12 }}>
            <div className="cdc-field">
              <label>Categoría</label>
              <select className="cdc-select" value={f.category || ""} onChange={(e) => setF(x => ({ ...x, category: e.target.value, subcategory: "" }))}>
                <option value="">(Sin categoría)</option>
                {categories.map(c => <option key={c} value={c}>{c}</option>)}
              </select>
            </div>
            <div className="cdc-field">
              <label>Unidad</label>
              <input className="cdc-input" placeholder="pza, kg, set…" value={f.unit || ""} onChange={(e) => u("unit", e.target.value)} />
            </div>
          </div>
          {subcatsFor(areaId, f.category).length > 0 && (
            <div className="cdc-field">
              <label>Tipo de {(f.category || "").toLowerCase()}</label>
              <select className="cdc-select" value={f.subcategory || ""} onChange={(e) => u("subcategory", e.target.value)}>
                <option value="">— Elegir —</option>
                {subcatsFor(areaId, f.category).map(s => <option key={s} value={s}>{s}</option>)}
              </select>
            </div>
          )}
          <div className="cdc-field">
            <label>Foto de la etiqueta (opcional)</label>
            {f.photo ? (
              <div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
                <img src={f.photo} alt="" style={{ width: 120, height: 120, objectFit: "cover", borderRadius: 10, border: "1px solid var(--cdc-border)" }} />
                <button type="button" className="cdc-btn" onClick={() => u("photo", null)} style={{ color: "var(--cdc-overdue)" }}>
                  <I.Trash size={13} /> Quitar foto
                </button>
              </div>
            ) : (
              <label style={{ display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 6, padding: "10px 12px", border: "1px dashed var(--cdc-border)", borderRadius: 10, fontSize: 13, color: "var(--cdc-ink-2)", cursor: "pointer", background: "var(--cdc-cream-50)", alignSelf: "flex-start" }}>
                <I.Camera size={16} />
                Tomar o subir foto
                <input type="file" accept="image/*" onChange={(e) => handlePhotoFile(e.target.files && e.target.files[0])} style={{ display: "none" }} />
              </label>
            )}
          </div>
          <div className="cdc-field">
            <label>Notas (opcional)</label>
            <textarea className="cdc-input" rows={3} placeholder="Marca, color, proveedor habitual, etc." value={f.notes || ""} onChange={(e) => u("notes", e.target.value)} />
          </div>
        </div>
        <div className="cdc-panel__actions" style={{ position: "static", borderTop: "1px solid var(--cdc-border-soft)" }}>
          {item && onRemove && (
            <button className="cdc-btn" style={{ color: "var(--cdc-overdue)" }} onClick={onRemove}>
              <I.Trash size={14} /> Eliminar
            </button>
          )}
          <button className="cdc-btn" onClick={onClose}>Cancelar</button>
          <button className="cdc-btn cdc-btn--coral" disabled={!(f.name && f.name.trim())} onClick={() => onSave({ ...f, name: (f.name || "").trim() })}>
            <I.Check size={14} /> {item ? "Guardar cambios" : "Crear artículo"}
          </button>
        </div>
      </div>
    </div>
  );
};

const InventoryDetailDrawer = ({ item, movements, user, canEdit, stock, onClose, onEdit, onAddMovement, onRemoveMovement }) => {
  const [movType, setMovType] = React.useState(null); // null | "entrada" | "salida"
  const [movQty, setMovQty] = React.useState(1);
  const [movReason, setMovReason] = React.useState("");
  const [movNotes, setMovNotes] = React.useState("");
  const [movDate, setMovDate] = React.useState(TODAY_ISO);

  const sortedMovs = [...movements].sort((a, b) => (b.date || "").localeCompare(a.date || ""));

  const openMov = (kind) => {
    setMovType(kind);
    setMovDate(TODAY_ISO);
    setMovQty(1);
    setMovReason("");
    setMovNotes("");
  };
  const submitMov = () => {
    const qty = parseFloat(movQty);
    if (!qty || qty <= 0) { window.alert("La cantidad debe ser mayor a 0."); return; }
    if (!movDate) { window.alert("Pon la fecha del movimiento."); return; }
    onAddMovement({
      type: movType, qty,
      date: movDate, by: user.id,
      reason: movReason.trim(), notes: movNotes.trim(),
    });
    setMovType(null); setMovQty(1); setMovReason(""); setMovNotes(""); setMovDate(TODAY_ISO);
  };

  return (
    <div className="cdc-overlay" onClick={onClose}>
      <div className="cdc-drawer" onClick={(e) => e.stopPropagation()} style={{ maxWidth: 540 }}>
        <div className="cdc-drawer__head">
          <div className="cdc-drawer__title">{item.name}</div>
          <div style={{ display: "flex", gap: 4 }}>
            {canEdit && (
              <button className="cdc-iconbtn" onClick={onEdit} title="Editar artículo"><I.Edit size={15} /></button>
            )}
            <button className="cdc-iconbtn" onClick={onClose}><I.X size={18} /></button>
          </div>
        </div>
        <div className="cdc-drawer__body">
          {(item.category || item.unit) && (
            <div style={{ fontSize: 12.5, color: "var(--cdc-ink-3)", marginBottom: 8 }}>
              {item.category || "Sin categoría"}{item.subcategory ? ` · ${item.subcategory}` : ""}{item.unit ? ` · Unidad: ${item.unit}` : ""}
            </div>
          )}
          {item.photo && (
            <img src={item.photo} alt={item.name} style={{ width: "100%", maxHeight: 260, objectFit: "cover", borderRadius: 10, border: "1px solid var(--cdc-border)", marginBottom: 12 }} />
          )}
          {item.notes && (
            <div style={{ background: "var(--cdc-cream-50)", border: "1px solid var(--cdc-cream-300)", borderRadius: 10, padding: "10px 12px", marginBottom: 14, fontSize: 13, color: "var(--cdc-ink-2)", lineHeight: 1.5, whiteSpace: "pre-wrap" }}>
              <div style={{ fontSize: 10.5, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--cdc-ink-3)", fontWeight: 700, marginBottom: 4 }}>Notas</div>
              {item.notes}
            </div>
          )}
          <div style={{ background: "var(--cdc-bg-soft)", border: "1px solid var(--cdc-border-soft)", borderRadius: 10, padding: 14, marginBottom: 14, display: "flex", alignItems: "center", justifyContent: "space-between" }}>
            <div>
              <div style={{ fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--cdc-ink-3)", fontWeight: 700 }}>Stock actual</div>
              <div style={{ fontFamily: "var(--cdc-display)", fontSize: 36, fontWeight: 600, color: stock < 0 ? "var(--cdc-overdue)" : "var(--cdc-ink)" }}>
                {stock} <span style={{ fontSize: 14, color: "var(--cdc-ink-3)" }}>{item.unit || ""}</span>
              </div>
            </div>
            {canEdit && (
              <div style={{ display: "flex", gap: 6 }}>
                <button className="cdc-btn cdc-btn--coral" onClick={() => openMov("entrada")}>
                  <I.Plus size={14} /> Entrada
                </button>
                <button className="cdc-btn" onClick={() => openMov("salida")}>
                  <I.Minus size={14} /> Salida
                </button>
              </div>
            )}
          </div>

          {movType && (
            <div style={{ background: movType === "entrada" ? "var(--cdc-done-bg)" : "var(--cdc-cream-50)", border: `1px solid ${movType === "entrada" ? "var(--cdc-done)" : "var(--cdc-coral)"}`, borderRadius: 10, padding: 14, marginBottom: 14 }}>
              <div style={{ fontWeight: 700, marginBottom: 10, color: movType === "entrada" ? "var(--cdc-done)" : "var(--cdc-coral-deep)" }}>
                Nueva {movType === "entrada" ? "entrada" : "salida"}
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                <div className="cdc-field">
                  <label>Fecha</label>
                  <input className="cdc-input" type="date" value={movDate} onChange={(e) => setMovDate(e.target.value)} />
                </div>
                <div className="cdc-field">
                  <label>Cantidad</label>
                  <input className="cdc-input" type="number" min="0" step="0.5" value={movQty} onChange={(e) => setMovQty(e.target.value)} />
                </div>
              </div>
              <div className="cdc-field" style={{ marginTop: 10 }}>
                <label>Motivo (opcional)</label>
                <input className="cdc-input" placeholder={movType === "entrada" ? "Compra, devolución…" : "Entrega a suite, lavandería…"} value={movReason} onChange={(e) => setMovReason(e.target.value)} />
              </div>
              <div className="cdc-field" style={{ marginTop: 10 }}>
                <label>Notas (opcional)</label>
                <textarea className="cdc-input" rows={2} value={movNotes} onChange={(e) => setMovNotes(e.target.value)} />
              </div>
              <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 10 }}>
                <button className="cdc-btn" onClick={() => setMovType(null)}>Cancelar</button>
                <button className="cdc-btn cdc-btn--coral" onClick={submitMov}>
                  <I.Check size={14} /> Registrar
                </button>
              </div>
            </div>
          )}

          <div style={{ fontSize: 11, letterSpacing: "0.12em", textTransform: "uppercase", color: "var(--cdc-ink-3)", fontWeight: 700, marginBottom: 8 }}>
            Historial de movimientos
          </div>
          {sortedMovs.length === 0 ? (
            <div style={{ fontSize: 13, color: "var(--cdc-ink-3)", padding: "10px 0" }}>Aún no hay movimientos registrados.</div>
          ) : (
            <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
              {sortedMovs.map(m => (
                <div key={m.id} style={{ display: "flex", gap: 10, padding: "8px 10px", background: "white", border: "1px solid var(--cdc-border-soft)", borderRadius: 8 }}>
                  <div style={{ width: 60, textAlign: "center" }}>
                    <span style={{ fontSize: 14, fontWeight: 700, color: m.type === "entrada" ? "var(--cdc-done)" : "var(--cdc-overdue)" }}>
                      {m.type === "entrada" ? "+" : "−"}{m.qty}
                    </span>
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, color: "var(--cdc-ink)" }}>
                      <strong>{(STAFF_BY_ID[m.by] && STAFF_BY_ID[m.by].name) || m.by || "—"}</strong>
                      <span style={{ color: "var(--cdc-ink-3)" }}> · {fmtShortDate(m.date)}</span>
                    </div>
                    {m.reason && <div style={{ fontSize: 12, color: "var(--cdc-ink-2)" }}>{m.reason}</div>}
                    {m.notes && <div style={{ fontSize: 11.5, color: "var(--cdc-ink-3)" }}>{m.notes}</div>}
                  </div>
                  {canEdit && (
                    <button className="cdc-iconbtn" onClick={() => onRemoveMovement(m.id)} title="Eliminar movimiento" style={{ color: "var(--cdc-overdue)" }}>
                      <I.Trash size={12} />
                    </button>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

const InventoryReportDialog = ({ areaId, areaLabel, items, movements, requestedBy, onClose }) => {
  const PAD2 = (n) => String(n).padStart(2, "0");
  const fmtLocal = (d) => `${d.getFullYear()}-${PAD2(d.getMonth() + 1)}-${PAD2(d.getDate())}`;
  const monthRange = () => {
    const n = new Date();
    return [fmtLocal(new Date(n.getFullYear(), n.getMonth(), 1)), fmtLocal(new Date(n.getFullYear(), n.getMonth() + 1, 0))];
  };
  const [m0, m1] = monthRange();
  const [from, setFrom] = React.useState(m0);
  const [to, setTo] = React.useState(m1);
  const [includeAll, setIncludeAll] = React.useState(false);

  const setPreset = (preset) => {
    setIncludeAll(false);
    const n = new Date();
    if (preset === "hoy") {
      const t = fmtLocal(n); setFrom(t); setTo(t);
    } else if (preset === "semana") {
      const dow = n.getDay();
      const offM = dow === 0 ? -6 : 1 - dow;
      const ws = new Date(n); ws.setDate(n.getDate() + offM);
      const we = new Date(ws); we.setDate(ws.getDate() + 6);
      setFrom(fmtLocal(ws)); setTo(fmtLocal(we));
    } else if (preset === "mes") {
      const [a, b] = monthRange(); setFrom(a); setTo(b);
    } else if (preset === "anterior") {
      const ms = new Date(n.getFullYear(), n.getMonth() - 1, 1);
      const me = new Date(n.getFullYear(), n.getMonth(), 0);
      setFrom(fmtLocal(ms)); setTo(fmtLocal(me));
    }
  };

  const isValid = includeAll || from <= to;
  const areaItems = (items || []).filter(i => i.area === areaId);
  const ids = new Set(areaItems.map(i => i.id));
  const inRange = (movements || []).filter(m => {
    if (!ids.has(m.itemId)) return false;
    if (includeAll) return true;
    if (!m.date) return false;
    return m.date >= from && m.date <= to;
  });

  // Existencias actuales = stock acumulado de TODOS los movimientos del item
  // (no solo los del rango). Y el orden de clasificacion para agrupar en el PDF.
  const stockByItem = {};
  areaItems.forEach(it => { stockByItem[it.id] = __stockOf(it.id, movements); });
  const categoriesOrder = INVENTORY_CATEGORIES[areaId] || [];
  const subcategoriesOrder = {};
  categoriesOrder.forEach(c => { const s = subcatsFor(areaId, c); if (s.length) subcategoriesOrder[c] = s; });

  const generate = () => {
    if (!isValid) return;
    if (window.exportInventoryMovementsPDF) {
      window.exportInventoryMovementsPDF({
        areaLabel,
        items: areaItems,
        movements: inRange,
        stockByItem,
        categoriesOrder,
        subcategoriesOrder,
        dateFrom: includeAll ? "" : from,
        dateTo: includeAll ? "" : to,
        requestedBy,
      });
    }
    onClose();
  };

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,.4)", zIndex: 600, display: "flex", alignItems: "center", justifyContent: "center", padding: 20 }}>
      <div onClick={(e) => e.stopPropagation()} style={{ background: "white", borderRadius: 14, padding: 22, width: "100%", maxWidth: 460, boxShadow: "var(--cdc-shadow-lg, 0 20px 50px rgba(0,0,0,.12))" }}>
        <h2 style={{ fontFamily: "var(--cdc-display)", fontSize: 22, fontWeight: 500, margin: 0 }}>Reporte de movimientos</h2>
        <p style={{ fontSize: 13, color: "var(--cdc-ink-3)", margin: "4px 0 14px" }}>Existencias actuales por clasificación + entradas y salidas de {areaLabel} en el periodo seleccionado.</p>
        <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 14 }}>
          <button className="cdc-chip" onClick={() => setPreset("hoy")}>Hoy</button>
          <button className="cdc-chip" onClick={() => setPreset("semana")}>Esta semana</button>
          <button className="cdc-chip" onClick={() => setPreset("mes")}>Este mes</button>
          <button className="cdc-chip" onClick={() => setPreset("anterior")}>Mes anterior</button>
          <button className="cdc-chip" aria-pressed={includeAll} onClick={() => setIncludeAll(v => !v)}>Todo</button>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, opacity: includeAll ? 0.5 : 1 }}>
          <div>
            <label style={{ display: "block", fontSize: 12, color: "var(--cdc-ink-3)", marginBottom: 4 }}>Desde</label>
            <input type="date" value={from} disabled={includeAll}
              onChange={(e) => { setIncludeAll(false); setFrom(e.target.value); }}
              style={{ width: "100%", padding: "9px 10px", border: "1px solid var(--cdc-border)", borderRadius: 9, background: "var(--cdc-bg-soft)", boxSizing: "border-box" }} />
          </div>
          <div>
            <label style={{ display: "block", fontSize: 12, color: "var(--cdc-ink-3)", marginBottom: 4 }}>Hasta</label>
            <input type="date" value={to} disabled={includeAll}
              onChange={(e) => { setIncludeAll(false); setTo(e.target.value); }}
              style={{ width: "100%", padding: "9px 10px", border: "1px solid var(--cdc-border)", borderRadius: 9, background: "var(--cdc-bg-soft)", boxSizing: "border-box" }} />
          </div>
        </div>
        <div style={{ marginTop: 14, fontSize: 13, color: "var(--cdc-ink-2)" }}>
          {isValid
            ? <><strong>{inRange.length}</strong> movimiento{inRange.length === 1 ? "" : "s"} en el rango ({inRange.filter(m => m.type === "entrada").length} entradas, {inRange.filter(m => m.type === "salida").length} salidas).</>
            : <span style={{ color: "var(--cdc-overdue)" }}>La fecha "Desde" debe ser anterior o igual a "Hasta".</span>}
        </div>
        <div style={{ display: "flex", gap: 8, marginTop: 18, justifyContent: "flex-end" }}>
          <button className="cdc-btn" onClick={onClose}>Cancelar</button>
          <button className="cdc-btn cdc-btn--coral" disabled={!isValid || areaItems.length === 0} onClick={generate} style={{ opacity: (!isValid || areaItems.length === 0) ? 0.5 : 1 }}>
            <I.Send size={14} /> Generar PDF
          </button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { InventoryPanel, INVENTORY_CATEGORIES, InventoryReportDialog });
