// Spreadsheet-style INVENTORY bulk editor (Inventory → BULK EDIT). Edits stock only:
// On-hand, Staged, Par, Bin. (Part-definition fields like name/manufacturer/price are edited
// in the BOM editor's bulk mode.) Inline edit, row-select + set, Excel-style drag-fill, Save all.
const { useState: useStateBE, useEffect: useEffectBE, useRef: useRefBE } = React;

const BE_COLS = [
  { key: "qty", label: "On-hand", w: 90, type: "number" },
  { key: "qty_packaged", label: "Staged", w: 90, type: "number" },
  { key: "par", label: "Par", w: 80, type: "number" },
  { key: "bin", label: "Bin", w: 120 },
];

function BulkEditGrid() {
  const live = window.useGpsData ? window.useGpsData() : 0;
  const [edits, setEdits] = useStateBE({});           // { sku: { field: value } }
  const [query, setQuery] = useStateBE("");
  const [sel, setSel] = useStateBE({ r: -1, c: null });
  const [fill, setFill] = useStateBE(null);           // { c, startR, endR }
  const [picked, setPicked] = useStateBE(() => new Set());
  const [bulkCol, setBulkCol] = useStateBE("bin");
  const [bulkVal, setBulkVal] = useStateBE("");
  const [saving, setSaving] = useStateBE(false);

  const editsRef = useRefBE(edits); editsRef.current = edits;
  const fillRef = useRefBE(fill); fillRef.current = fill;
  const rowsRef = useRefBE([]);

  const all = (window.INVENTORY || []);
  const parts = React.useMemo(() => all.map(i => ({ sku: i.sku, name: i.name || i.sku, qty: i.qty || 0, qty_packaged: i.qty_packaged || 0, par: i.par || 0, bin: i.bin || "" })), [live, all.length]);

  const rows = parts.filter(p => { const q = query.toLowerCase().trim(); return !q || (`${p.name} ${p.sku}`.toLowerCase().includes(q)); });
  rowsRef.current = rows;

  const orig = (sku) => parts.find(p => p.sku === sku) || {};
  const val = (p, key) => { const e = edits[p.sku]; return e && key in e ? e[key] : (p[key] != null ? p[key] : ""); };
  const setVal = (sku, key, value) => setEdits(e => ({ ...e, [sku]: { ...e[sku], [key]: value } }));
  const dirty = (p, key) => { const e = edits[p.sku]; return e && key in e && String(e[key]) !== String(p[key] != null ? p[key] : ""); };

  useEffectBE(() => {
    const up = () => {
      const f = fillRef.current;
      if (f) {
        const rr = rowsRef.current; const src = rr[f.startR]; const key = f.c;
        if (src) {
          const v = (editsRef.current[src.sku] && key in editsRef.current[src.sku]) ? editsRef.current[src.sku][key] : (src[key] != null ? src[key] : "");
          const a = Math.min(f.startR, f.endR), b = Math.max(f.startR, f.endR);
          setEdits(e => { const n = { ...e }; for (let r = a; r <= b; r++) { const s = rr[r]; if (s) n[s.sku] = { ...n[s.sku], [key]: v }; } return n; });
        }
        setFill(null);
      }
    };
    window.addEventListener("mouseup", up);
    return () => window.removeEventListener("mouseup", up);
  }, []);
  const inFill = (r, c) => fill && fill.c === c && r >= Math.min(fill.startR, fill.endR) && r <= Math.max(fill.startR, fill.endR);

  function applyBulk() { if (!picked.size || !bulkCol) return; setEdits(e => { const n = { ...e }; picked.forEach(sku => { n[sku] = { ...n[sku], [bulkCol]: bulkVal }; }); return n; }); }
  function togglePick(sku) { setPicked(s => { const n = new Set(s); n.has(sku) ? n.delete(sku) : n.add(sku); return n; }); }
  function pickAll() { setPicked(s => s.size === rows.length ? new Set() : new Set(rows.map(p => p.sku))); }

  const changeCount = Object.keys(edits).reduce((n, sku) => { const p = orig(sku), e = edits[sku] || {}; return n + (Object.keys(e).some(k => String(e[k]) !== String(p[k] != null ? p[k] : "")) ? 1 : 0); }, 0);

  async function save() {
    const changes = [];
    for (const sku in edits) {
      const p = orig(sku), e = edits[sku], ch = { sku }; let any = false;
      for (const k in e) { let v = e[k]; if (k !== "bin") v = Number(v) || 0; if (String(v) !== String(p[k] != null ? p[k] : "")) { ch[k] = v; any = true; } }
      if (any) changes.push(ch);
    }
    if (!changes.length) { window.gpsToast && window.gpsToast({ message: "No changes to save", tone: "warn" }); return; }
    setSaving(true);
    try {
      const r = await fetch("/api/inventory/bulk-update", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ changes }) });
      const d = await r.json().catch(() => ({}));
      if (!r.ok) { window.gpsToast && window.gpsToast({ message: d.error || "Save failed", tone: "warn" }); return; }
      window.gpsToast && window.gpsToast({ message: `Saved ${d.updated} item(s)`, tone: "ok" });
      setEdits({}); setPicked(new Set());
      if (window.gpsRefreshData) window.gpsRefreshData();
    } catch { window.gpsToast && window.gpsToast({ message: "Save failed", tone: "warn" }); }
    finally { setSaving(false); }
  }

  return (
    <div className="flex-1 flex flex-col overflow-hidden">
      <div className="px-4 sm:px-8 py-3 border-b border-zinc-800 flex flex-wrap items-center gap-2">
        <input value={query} onChange={e => setQuery(e.target.value)} placeholder="Filter items…"
          className="bg-zinc-900 border border-zinc-700 rounded-lg px-3 py-1.5 text-[13px] text-zinc-100 placeholder-zinc-500 outline-none w-48" />
        <div className="flex items-center gap-1.5 text-[12px] text-zinc-400">
          <span>{picked.size} selected →</span>
          <select value={bulkCol} onChange={e => setBulkCol(e.target.value)} className="bg-zinc-900 border border-zinc-700 rounded px-2 py-1 text-zinc-200">
            {BE_COLS.map(c => <option key={c.key} value={c.key}>{c.label}</option>)}
          </select>
          <span>=</span>
          <input value={bulkVal} onChange={e => setBulkVal(e.target.value)} placeholder="value" className="bg-zinc-900 border border-zinc-700 rounded px-2 py-1 text-zinc-100 w-24 outline-none" />
          <button onClick={applyBulk} disabled={!picked.size} className="px-2.5 py-1 rounded bg-zinc-800 border border-zinc-700 hover:bg-zinc-700 disabled:opacity-40">Set selected</button>
        </div>
        <div className="flex-1" />
        <span className="text-[12px] text-zinc-500">{changeCount} edited</span>
        <button onClick={save} disabled={saving || !changeCount} className="px-4 py-1.5 rounded-lg text-white font-semibold text-[13px] disabled:opacity-40" style={{ background: window.GPS_RED }}>
          {saving ? "Saving…" : `Save all (${changeCount})`}
        </button>
      </div>
      <div className="flex-1 overflow-auto">
        <table className="text-[12px] border-collapse select-none">
          <thead className="sticky top-0 bg-zinc-900 z-10">
            <tr>
              <th className="border border-zinc-800 px-2 py-1.5"><input type="checkbox" checked={rows.length > 0 && picked.size === rows.length} onChange={pickAll} /></th>
              <th className="border border-zinc-800 px-2 py-1.5 text-left text-zinc-400 font-medium">SKU</th>
              <th className="border border-zinc-800 px-2 py-1.5 text-left text-zinc-400 font-medium">Name</th>
              {BE_COLS.map(c => <th key={c.key} className="border border-zinc-800 px-2 py-1.5 text-left text-zinc-400 font-medium" style={{ minWidth: c.w }}>{c.label}</th>)}
            </tr>
          </thead>
          <tbody>
            {rows.map((p, r) => (
              <tr key={p.sku} className={picked.has(p.sku) ? "bg-zinc-900/40" : ""}>
                <td className="border border-zinc-800 px-2 text-center"><input type="checkbox" checked={picked.has(p.sku)} onChange={() => togglePick(p.sku)} /></td>
                <td className="border border-zinc-800 px-2 py-1 font-mono text-zinc-500 whitespace-nowrap">{p.sku}</td>
                <td className="border border-zinc-800 px-2 py-1 text-zinc-300 whitespace-nowrap max-w-[220px] truncate">{p.name}</td>
                {BE_COLS.map(c => (
                  <td key={c.key} onMouseEnter={() => fill && fill.c === c.key && setFill(f => ({ ...f, endR: r }))}
                    className={`border border-zinc-800 p-0 relative ${inFill(r, c.key) ? "bg-blue-500/20" : ""} ${dirty(p, c.key) ? "bg-amber-500/10" : ""}`}>
                    <input type={c.type === "number" ? "number" : "text"} value={val(p, c.key)}
                      onFocus={() => setSel({ r, c: c.key })} onChange={e => setVal(p.sku, c.key, e.target.value)}
                      className="w-full bg-transparent text-zinc-100 px-2 py-1 outline-none focus:bg-zinc-800" />
                    {sel.r === r && sel.c === c.key && (
                      <div title="Drag to fill down" onMouseDown={e => { e.preventDefault(); setFill({ c: c.key, startR: r, endR: r }); }}
                        className="absolute -bottom-[3px] -right-[3px] h-2 w-2 bg-blue-500 border border-white cursor-crosshair z-20" />
                    )}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
        {rows.length === 0 && <div className="text-zinc-600 text-[13px] p-8 text-center">No items.</div>}
      </div>
    </div>
  );
}

window.BulkEditGrid = BulkEditGrid;
