/* NGIPL PLM — Master price list view */
const { useState, useEffect, useMemo, useRef } = React;

function MasterView({ nav, toast }) {
  const state = PLM.useStore();
  const [search, setSearch] = useState("");
  const [catFilter, setCatFilter] = useState("all");
  const [bulkOpen, setBulkOpen] = useState(false);
  const [editProduct, setEditProduct] = useState(null); // product object or "new"
  const [partiesFor, setPartiesFor] = useState(null); // product
  const grouped = PLM.groupedProducts();
  const nums = PLM.numberMap();
  const q = search.trim().toLowerCase();

  const bands = grouped
    .filter((b) => catFilter === "all" || b.cat.id === catFilter)
    .map((b) => ({
      cat: b.cat,
      groups: b.groups
        .map((g) => ({
          sub: g.sub,
          items: g.items.filter((p) => !q || p.name.toLowerCase().includes(q) || (p.note || "").toLowerCase().includes(q)),
        }))
        .filter((g) => g.items.length),
    }))
    .filter((b) => b.groups.length);
  const visibleCount = bands.reduce((a, b) => a + b.groups.reduce((x, g) => x + g.items.length, 0), 0);

  function commitRate(p, rate) {
    PLM.updateProduct(p.id, { rate });
    const linked = PLM.productParties(p.id);
    const special = linked.filter((x) => Math.abs(x.item.rate - rate) > 0.0001);
    if (special.length) {
      toast(p.name + ": ₹" + PLM.fmtRate(rate) + " — " + special.length + " part" + (special.length === 1 ? "y has" : "ies have") + " special rates to review");
    } else {
      toast(p.name + " updated to ₹" + PLM.fmtRate(rate));
    }
  }

  return (
    <div data-screen-label="Master Price List">
      <div className="toolbar">
        <div className="search-box">
          <ISearch size={15}></ISearch>
          <input className="f-input" placeholder="Search items…" value={search} onChange={(e) => setSearch(e.target.value)} />
        </div>
        <select className="f-select" style={{ width: 210 }} value={catFilter} onChange={(e) => setCatFilter(e.target.value)}>
          <option value="all">All categories</option>
          {state.categories.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
        </select>
        <span className="caption">{visibleCount} of {state.products.length} items</span>
        <div className="spacer"></div>
        <WefChip state={state}></WefChip>
        <Btn variant="secondary" size="sm" onClick={() => setBulkOpen(true)}><IPercent size={13}></IPercent> Update prices</Btn>
        <Btn size="sm" onClick={() => setEditProduct("new")}><IPlus size={13}></IPlus> Add item</Btn>
      </div>

      <div className="panel panel--strong plm-table-wrap" style={{ maxHeight: "calc(100vh - 220px)" }}>
        <table className="plm-table">
          <thead>
            <tr>
              <th className="col-no">#</th>
              <th>Item</th>
              <th className="num" style={{ width: 90 }}>Rate ₹</th>
              <th style={{ width: 80 }}>Unit</th>
              <th className="num" style={{ width: 90 }}>Pack size</th>
              <th className="num" style={{ width: 64 }}>GST</th>
              <th style={{ width: 130 }}>Special rates</th>
              <th style={{ width: 56 }}></th>
            </tr>
          </thead>
          <tbody>
            {bands.map((band) => (
              <React.Fragment key={band.cat.id}>
                <tr className="cat-band"><td colSpan={8}><span className="band-cell"><CatIcon catId={band.cat.id} size={18}></CatIcon><span>{band.cat.name}</span></span></td></tr>
                {band.groups.map((g, gi) => (
                  <React.Fragment key={g.sub ? g.sub.id : "loose" + gi}>
                    {g.sub ? <tr className="sub-band"><td colSpan={8}>{g.sub.name}</td></tr> : null}
                    {g.items.map((p) => (
                      <ProductRow key={p.id} p={p} no={nums[p.id]}
                        onRate={(r) => commitRate(p, r)}
                        onEdit={() => setEditProduct(p)}
                        onParties={() => setPartiesFor(p)}></ProductRow>
                    ))}
                  </React.Fragment>
                ))}
              </React.Fragment>
            ))}
          </tbody>
        </table>
        {visibleCount === 0 ? <div style={{ padding: 32, textAlign: "center" }} className="caption">No items match.</div> : null}
      </div>

      {bulkOpen ? <BulkDialog onClose={() => setBulkOpen(false)} toast={toast}></BulkDialog> : null}
      {editProduct ? (
        <ProductDialog product={editProduct === "new" ? null : editProduct}
          onClose={() => setEditProduct(null)} toast={toast}></ProductDialog>
      ) : null}
      {partiesFor ? <PartiesForProductDialog product={partiesFor} nav={nav} onClose={() => setPartiesFor(null)}></PartiesForProductDialog> : null}
    </div>
  );
}

function ProductRow({ p, no, onRate, onEdit, onParties }) {
  const linked = PLM.productParties(p.id);
  const special = linked.filter((x) => Math.abs(x.item.rate - p.rate) > 0.0001);
  const stale = linked.filter((x) => PLM.itemStale(x.item));
  return (
    <tr className="item-row">
      <td className="col-no">{no}</td>
      <td>
        <div>{p.name}</div>
        {p.note ? <div className="item-note">{p.note}</div> : null}
      </td>
      <td className="num rate"><RateCell value={p.rate} onCommit={onRate}></RateCell></td>
      <td>{p.unit}</td>
      <td className="num">{PLM.fmtPack(p.packSize)}</td>
      <td className="num">{PLM.fmtGst(p.gst)}</td>
      <td>
        {special.length ? (
          <span className={"chip chip--click" + (stale.length ? " chip--warn" : "")} onClick={onParties}
            title="Parties with a special rate on this item">
            {stale.length ? <IAlert size={11}></IAlert> : null}
            {special.length} {special.length === 1 ? "party" : "parties"}
          </span>
        ) : (
          <span className="chip chip--ghost">—</span>
        )}
      </td>
      <td>
        <span className="row-actions">
          <IconBtn title="Edit item" onClick={onEdit}><IPencil size={14}></IPencil></IconBtn>
        </span>
      </td>
    </tr>
  );
}

function WefChip({ state }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useOutsideClose(ref, () => setOpen(false));
  return (
    <span ref={ref} style={{ position: "relative", display: "inline-flex" }}>
      <span className="chip chip--click" onClick={() => setOpen((o) => !o)} title="Effective date — click to pick from calendar">
        <ICalendar size={12}></ICalendar> W.E.F. {state.settings.wef}
      </span>
      {open ? <WefCalendar value={state.settings.wef} align="right" onPick={(d) => { PLM.setWef(fmtWefDate(d)); setOpen(false); }}></WefCalendar> : null}
    </span>
  );
}

/* ---------- Bulk price update ---------- */
function BulkDialog({ onClose, toast }) {
  const state = PLM.useStore();
  const [scope, setScope] = useState("all");
  const [mode, setMode] = useState("pct");
  const [value, setValue] = useState("");
  const [round, setRound] = useState("0.05");
  const [note, setNote] = useState("");

  const scopeOptions = [{ value: "all", label: "All items" }];
  state.categories.forEach((c) => {
    scopeOptions.push({ value: "cat:" + c.id, label: c.name });
    c.subs.forEach((s) => scopeOptions.push({ value: "sub:" + c.id + ":" + s.id, label: "— " + c.name + " · " + s.name }));
  });

  function inScope(p) {
    if (scope === "all") return true;
    const parts = scope.split(":");
    if (parts[0] === "cat") return p.categoryId === parts[1];
    return p.categoryId === parts[1] && p.subId === parts[2];
  }
  const v = parseFloat(value);
  const valid = !isNaN(v) && v !== 0;
  function computeNew(rate) {
    if (!valid) return null;
    let nv = mode === "pct" ? rate * (1 + v / 100) : rate + v;
    const step = parseFloat(round);
    if (step) nv = Math.round(nv / step) * step;
    nv = Math.round(nv * 100) / 100;
    return nv < 0 ? 0 : nv;
  }
  const affected = state.products.filter(inScope);
  const preview = valid
    ? affected.map((p) => ({ p, nv: computeNew(p.rate) })).filter((x) => Math.abs(x.nv - x.p.rate) > 0.0001)
    : [];

  function apply() {
    const scopeLabel = scopeOptions.find((o) => o.value === scope).label.replace(/^— /, "");
    const desc = (mode === "pct" ? (v > 0 ? "+" : "") + v + "%" : (v > 0 ? "+₹" : "−₹") + Math.abs(v)) + " on " + scopeLabel;
    const n = PLM.bulkUpdate(preview.map((x) => x.p.id), computeNew, "Bulk update: " + desc, note);
    const staleAfter = PLM.totalStale();
    toast("Updated " + n + " rates (" + desc + ")" + (staleAfter ? " — " + staleAfter + " party rates flagged for review" : ""));
    onClose();
  }

  return (
    <Dialog title="Update prices" onClose={onClose} width={640}
      footer={
        <React.Fragment>
          <Btn variant="ghost" size="sm" onClick={onClose}>Cancel</Btn>
          <Btn size="sm" disabled={!preview.length} onClick={apply}>Apply to {preview.length} items</Btn>
        </React.Fragment>
      }>
      <div className="f-stack">
        <div className="f-row">
          <Field label="Scope">
            <select className="f-select" value={scope} onChange={(e) => setScope(e.target.value)}>
              {scopeOptions.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
            </select>
          </Field>
          <Field label="Adjustment">
            <div style={{ display: "flex", gap: 8 }}>
              <Seg options={[{ value: "pct", label: "%" }, { value: "abs", label: "₹" }]} value={mode} onChange={setMode}></Seg>
              <input className="f-input" style={{ width: 100 }} placeholder={mode === "pct" ? "e.g. 5" : "e.g. 0.10"}
                value={value} onChange={(e) => setValue(e.target.value)} />
            </div>
          </Field>
          <Field label="Round to">
            <select className="f-select" value={round} onChange={(e) => setRound(e.target.value)}>
              <option value="0">No rounding</option>
              <option value="0.05">₹0.05</option>
              <option value="0.10">₹0.10</option>
              <option value="0.5">₹0.50</option>
              <option value="1">₹1</option>
            </select>
          </Field>
        </div>
        <Field label="Note (shown in history)">
          <input className="f-input" placeholder="e.g. Raw material cost increase, FY 26-27" value={note} onChange={(e) => setNote(e.target.value)} />
        </Field>
        <div>
          <div className="f-label">Preview {valid ? "— " + preview.length + " of " + affected.length + " rates change" : ""}</div>
          <div className="panel" style={{ maxHeight: 240, overflow: "auto" }}>
            {!valid ? (
              <div className="caption" style={{ padding: 16 }}>Enter an adjustment to preview changes.</div>
            ) : (
              <table className="plm-table">
                <tbody>
                  {preview.slice(0, 200).map(({ p, nv }) => (
                    <tr key={p.id}>
                      <td>{p.name}</td>
                      <td className="num tnum" style={{ width: 90, color: "var(--text-faint)" }}>₹{PLM.fmtRate(p.rate)}</td>
                      <td style={{ width: 30, color: "var(--text-faint)" }}><IArrowR size={12}></IArrowR></td>
                      <td className="num tnum rate" style={{ width: 90 }}>₹{PLM.fmtRate(nv)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            )}
          </div>
        </div>
        <div className="caption">
          Party special rates are not changed. Any party with a special rate on an updated item is flagged for review under Party Rates.
        </div>
      </div>
    </Dialog>
  );
}

/* ---------- Add / edit product ---------- */
function ProductDialog({ product, onClose, toast }) {
  const state = PLM.useStore();
  const isNew = !product;
  const [f, setF] = useState(() => ({
    name: product ? product.name : "",
    note: product ? product.note || "" : "",
    categoryId: product ? product.categoryId : state.categories[0].id,
    subId: product ? product.subId || "" : "",
    rate: product ? String(product.rate) : "",
    unit: product ? product.unit : "Pcs",
    packSize: product ? (product.packSize === null || product.packSize === undefined ? "" : String(product.packSize)) : "",
    gst: product ? String(product.gst) : "18",
  }));
  const [confirmDel, setConfirmDel] = useState(false);
  const cat = PLM.catById(f.categoryId);
  const set = (k) => (e) => setF({ ...f, [k]: e.target.value });
  const rateN = parseFloat(f.rate);
  const canSave = f.name.trim() && !isNaN(rateN) && rateN >= 0;

  function save() {
    const packRaw = f.packSize.trim();
    const packN = parseFloat(packRaw);
    const fields = {
      name: f.name.trim(), note: f.note.trim(),
      categoryId: f.categoryId, subId: f.subId || null,
      rate: Math.round(rateN * 100) / 100,
      unit: f.unit.trim() || "Pcs",
      packSize: packRaw === "" ? null : (!isNaN(packN) && /^[\d.]+$/.test(packRaw) ? packN : packRaw),
      gst: parseFloat(f.gst) || 0,
    };
    if (isNew) {
      PLM.addProduct(fields);
      toast("Added " + fields.name);
    } else {
      PLM.updateProduct(product.id, fields);
      toast("Saved " + fields.name);
    }
    onClose();
  }
  const linkedCount = product ? PLM.productParties(product.id).length : 0;

  return (
    <Dialog title={isNew ? "Add item" : "Edit item"} onClose={onClose} width={620}
      footer={
        <React.Fragment>
          {!isNew ? (
            confirmDel ? (
              <span style={{ marginRight: "auto", display: "inline-flex", alignItems: "center", gap: 8 }}>
                <span className="caption">Delete this item{linkedCount ? " — " + linkedCount + " party line(s) become custom" : ""}?</span>
                <Btn variant="danger" size="sm" onClick={() => { PLM.deleteProduct(product.id); toast("Deleted " + product.name); onClose(); }}>Delete</Btn>
              </span>
            ) : (
              <Btn variant="ghost" size="sm" style={{ marginRight: "auto", color: "var(--red-700)" }} onClick={() => setConfirmDel(true)}>
                <ITrash size={13}></ITrash> Delete
              </Btn>
            )
          ) : null}
          <Btn variant="ghost" size="sm" onClick={onClose}>Cancel</Btn>
          <Btn size="sm" disabled={!canSave} onClick={save}>{isNew ? "Add item" : "Save"}</Btn>
        </React.Fragment>
      }>
      <div className="f-stack">
        <Field label="Item name">
          <input className="f-input" value={f.name} onChange={set("name")} placeholder="e.g. White Sugar (5gms)" />
        </Field>
        <Field label="Note (optional — prints under the name)">
          <input className="f-input" value={f.note} onChange={set("note")} placeholder="e.g. For date printing ₹0.10 extra, MOQ applies" />
        </Field>
        <div className="f-row">
          <Field label="Category">
            <select className="f-select" value={f.categoryId} onChange={(e) => setF({ ...f, categoryId: e.target.value, subId: "" })}>
              {state.categories.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
            </select>
          </Field>
          {cat && cat.subs.length ? (
            <Field label="Sub-category">
              <select className="f-select" value={f.subId} onChange={set("subId")}>
                <option value="">— None —</option>
                {cat.subs.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}
              </select>
            </Field>
          ) : null}
        </div>
        <div className="f-row">
          <Field label="Rate ₹ (ex-GST)">
            <input className="f-input" value={f.rate} onChange={set("rate")} placeholder="0.00" />
          </Field>
          <Field label="Unit">
            <input className="f-input" value={f.unit} onChange={set("unit")} placeholder="Pcs / Sachets / Can" />
          </Field>
          <Field label="Pack size (per carton)">
            <input className="f-input" value={f.packSize} onChange={set("packSize")} placeholder="e.g. 200 or 5 Ltr" />
          </Field>
          <Field label="GST %">
            <select className="f-select" value={f.gst} onChange={set("gst")}>
              {["0", "5", "12", "18", "28"].map((g) => <option key={g} value={g}>{g}%</option>)}
            </select>
          </Field>
        </div>
      </div>
    </Dialog>
  );
}

/* ---------- Parties with special rates on a product ---------- */
function PartiesForProductDialog({ product, nav, onClose }) {
  const linked = PLM.productParties(product.id);
  return (
    <Dialog title="Special rates — " onClose={onClose} width={620}>
      <div style={{ marginTop: -8, marginBottom: 14 }}>
        <div style={{ fontWeight: 600, fontSize: 15 }}>{product.name}</div>
        <div className="caption">Master rate ₹{PLM.fmtRate(product.rate)} · {product.unit} · GST {PLM.fmtGst(product.gst)}</div>
      </div>
      <div className="panel">
        <table className="plm-table">
          <thead>
            <tr><th>Party</th><th className="num">Party ₹</th><th className="num">vs master</th><th style={{ width: 110 }}></th><th style={{ width: 44 }}></th></tr>
          </thead>
          <tbody>
            {linked.map(({ party, item }) => {
              const stale = PLM.itemStale(item);
              const d = PLM.deltaPct(item.rate, product.rate);
              return (
                <tr key={party.id + item.id}>
                  <td>{party.name}</td>
                  <td className="num rate tnum">₹{PLM.fmtRate(item.rate)}</td>
                  <td className="num tnum">{d || "same"}</td>
                  <td>{stale ? <span className="chip chip--warn"><IAlert size={11}></IAlert> Review</span> : null}</td>
                  <td>
                    <IconBtn title={"Open " + party.name} onClick={() => { onClose(); nav.goParty(party.id); }}><IJump size={14}></IJump></IconBtn>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        {!linked.length ? <div className="caption" style={{ padding: 16 }}>No party lists include this item.</div> : null}
      </div>
    </Dialog>
  );
}

Object.assign(window, { MasterView });
