/* =============================================================
   CoreIQ Office — Pricing review (LIVE · this pharmacy)

   The lines that need a price decision, and the working behind each
   recommendation. Ported from the design's Pricing shell + recommendation
   detail, wired to /pricing/queue and /pricing/recommendation/:id.

   ADVISORY ONLY. Nothing on these two screens changes a shelf price. The
   queue is DERIVED on every read from facts already on file — a cost that
   moved on a real invoice, a line received with no price, a competitor
   whose price fell out of its observed range — so there is nothing stored
   to go stale and nothing to "dismiss". Prices are changed in Manage stock.

   Registers window.OFFICE_SCREENS.pricing and .priceDetail
   ============================================================= */
const { useState: prState, useEffect: prEffect, useMemo: prMemo } = React;

const prM = (c) => (c == null ? "—" : "$" + (Number(c) / 100).toLocaleString("en-AU", { minimumFractionDigits: 2, maximumFractionDigits: 2 }));
const prSigned = (c) => (c == null ? "—" : (c > 0 ? "+" : c < 0 ? "−" : "") + prM(Math.abs(c)));
const prPct = (v) => (v == null ? "—" : Number(v).toFixed(1) + "%");
const prDate = (iso) => (iso ? String(iso).slice(0, 10) : "—");

// Why a line is in the queue. Order here is priority order — it matches the API.
const PR_REASONS = {
  new:   { label: "No price",        bg: "var(--void-bg)", fg: "var(--void-text)", bd: "var(--void-border)" },
  cost:  { label: "Cost moved",      bg: "var(--hold-bg)", fg: "var(--hold-text)", bd: "var(--hold)" },
  floor: { label: "Under floor",     bg: "var(--void-bg)", fg: "var(--void-text)", bd: "var(--void-border)" },
  sale:  { label: "Competitor sale", bg: "var(--hold-bg)", fg: "var(--hold-text)", bd: "var(--hold)" },
  kvi:   { label: "Price-sensitive", bg: "var(--navy-100)", fg: "var(--navy-800)", bd: "var(--navy-200)" },
  move:  { label: "Room to move",    bg: "var(--bg-subtle)", fg: "var(--text-subtle)", bd: "var(--line)" },
};

function PrReasonTag({ reason }) {
  const r = PR_REASONS[reason] || PR_REASONS.move;
  return (
    <span style={{ display: "inline-block", fontSize: 10, fontWeight: 700, letterSpacing: ".04em", textTransform: "uppercase",
      padding: "2px 7px", borderRadius: 4, background: r.bg, color: r.fg, border: "1px solid " + r.bd, whiteSpace: "nowrap" }}>
      {r.label}
    </span>
  );
}

function PrAdvisoryNote() {
  return (
    <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "10px 14px", marginBottom: 14, background: "var(--bg-subtle)",
      borderRadius: 8, fontSize: "var(--fs-12)", color: "var(--text-subtle)" }}>
      <window.OIcon name="info" />
      <span>Recommendations only — nothing here changes a shelf price. The queue is worked out fresh from the stock card, the latest invoice cost and observed competitor prices each time you open it. Change a price in <b>Manage stock</b>.</span>
    </div>
  );
}

// =================================================================
// QUEUE
// =================================================================
function PricingReview() {
  const { setScreen, setScreenState } = window.useOffice();
  const Kpi = window.KpiCard;
  const [data, setData] = prState(null);
  const [err, setErr] = prState(null);
  const [loading, setLoading] = prState(true);
  const [filter, setFilter] = prState("all");
  const [search, setSearch] = prState("");
  const [reloadKey, setReloadKey] = prState(0);

  prEffect(() => {
    let alive = true;
    setLoading(true); setErr(null);
    window.OfficeAPI.pricingQueue()
      .then((d) => { if (alive) setData(d); })
      .catch((e) => { if (alive) setErr(e && e.message ? e.message : "Couldn't load the pricing queue."); })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [reloadKey]);

  const rows = prMemo(() => {
    const all = (data && data.rows) || [];
    const q = search.trim().toLowerCase();
    return all.filter((r) => (filter === "all" || r.reason === filter) &&
      (!q || (r.name || "").toLowerCase().includes(q) || (r.sku || "").toLowerCase().includes(q) || (r.brand || "").toLowerCase().includes(q)));
  }, [data, filter, search]);

  const counts = (data && data.counts) || {};
  const total = Object.values(counts).reduce((s, n) => s + Number(n || 0), 0);
  const open = (r) => { setScreenState((st) => ({ ...st, priceProductId: r.productId, priceFrom: "pricing" })); setScreen("priceDetail"); };

  const TABS = [{ k: "all", label: "All", n: total }].concat(Object.keys(PR_REASONS).map((k) => ({ k, label: PR_REASONS[k].label, n: Number(counts[k] || 0) })));

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <span className="off-screen-eyebrow">live · this pharmacy · derived from cost + competitor facts</span>
          <h2 className="off-screen-title">Pricing review</h2>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          {data && <span title="The pricing method this store runs" style={{ fontSize: "var(--fs-11)", color: "var(--text-subtle)" }}>Method · <b style={{ color: "var(--text)" }}>{data.methodName}</b></span>}
          <button className="btn btn--secondary btn--sm" onClick={() => setReloadKey((k) => k + 1)}><window.OIcon name="refresh" /> Recompute</button>
        </div>
      </header>

      <div className="off-screen-body">
        <PrAdvisoryNote />

        {data && Kpi && (
          <div className="off-grid-kpis" style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, marginBottom: 18 }}>
            <Kpi label="Needs a decision" value={total.toLocaleString("en-AU")} delta={{ text: "lines in the queue right now" }} />
            <Kpi label="No price set" value={Number(counts.new || 0).toLocaleString("en-AU")} delta={{ text: "received, cannot be sold", dir: counts.new > 0 ? "down" : undefined }} />
            <Kpi label="Cost moved" value={Number(counts.cost || 0).toLocaleString("en-AU")} delta={{ text: "margin changed under the current price" }} />
            <Kpi label="Under the floor" value={Number(counts.floor || 0).toLocaleString("en-AU")} delta={{ text: "selling below cost + band", dir: counts.floor > 0 ? "down" : undefined }} />
          </div>
        )}

        <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, flexWrap: "wrap" }}>
          <div className="tabset">
            {TABS.map((t) => (
              <button key={t.k} className="tabset-item" aria-selected={filter === t.k} onClick={() => setFilter(t.k)}>
                {t.label}{t.n ? <span style={{ marginLeft: 6, opacity: .7, fontFamily: "var(--font-mono)", fontSize: "var(--fs-11)" }}>{t.n}</span> : null}
              </button>
            ))}
          </div>
          <input className="off-input" style={{ marginLeft: "auto", minWidth: 220 }} placeholder="Filter by product, SKU or brand…" value={search} onChange={(e) => setSearch(e.target.value)} />
        </div>

        {err && <div className="off-card" style={{ borderColor: "var(--void-border)", background: "var(--void-bg)", color: "var(--void-text)", padding: "12px 16px" }}><window.OIcon name="alert" /> {err}</div>}

        {!err && (
          <div className="off-card">
            <div className="off-card-header">
              <div>
                <div className="off-card-title">{loading ? "Working it out…" : rows.length + " line" + (rows.length === 1 ? "" : "s")}</div>
                <div className="off-card-meta">{data ? "Recomputed " + new Date(data.generatedAt).toLocaleTimeString("en-AU", { hour: "2-digit", minute: "2-digit" }) + " · sorted by why, then by size of move" : ""}</div>
              </div>
            </div>
            {!loading && rows.length === 0 && (
              <div style={{ padding: "28px 16px", textAlign: "center", color: "var(--text-subtle)", fontSize: "var(--fs-13)" }}>
                {total === 0
                  ? <span>Nothing needs a price decision right now. A line appears here when its cost moves on an invoice, it arrives with no price, it is selling under its cost floor, or an observed competitor price changes enough to matter.</span>
                  : <span>No lines match this filter.</span>}
              </div>
            )}
            {rows.length > 0 && (
              <div className="off-grid" style={{ gridTemplateColumns: "minmax(220px,1.4fr) minmax(200px,2fr) 96px 110px 90px 120px" }}>
                <div className="off-grid-headcell">Product</div>
                <div className="off-grid-headcell">Why it's here</div>
                <div className="off-grid-headcell" style={{ justifyContent: "flex-end" }}>Now</div>
                <div className="off-grid-headcell" style={{ justifyContent: "flex-end" }}>Recommended</div>
                <div className="off-grid-headcell" style={{ justifyContent: "flex-end" }}>Move</div>
                <div className="off-grid-headcell" style={{ justifyContent: "flex-end" }}>Margin</div>
                {rows.map((r) => (
                  <div key={r.productId} className="off-grid-row" style={{ cursor: "pointer" }} onClick={() => open(r)}>
                    <div className="off-grid-cell off-cell-strong" style={{ display: "flex", flexDirection: "column", gap: 2, minWidth: 0 }}>
                      <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{r.name}</span>
                      <span style={{ fontSize: "var(--fs-11)", color: "var(--text-subtle)", fontFamily: "var(--font-mono)", fontWeight: 400 }}>{r.sku || ""}{r.brand ? " · " + r.brand : ""}{r.kvi ? " · KVI" : ""}</span>
                    </div>
                    <div className="off-grid-cell" style={{ display: "flex", flexDirection: "column", gap: 4, minWidth: 0, alignItems: "flex-start" }}>
                      <span style={{ display: "flex", gap: 6, alignItems: "center" }}><PrReasonTag reason={r.reason} />{r.costNote && <span title={r.costNote} style={{ color: "var(--hold-text)", fontSize: 11, cursor: "help" }}>⚠ check pack</span>}</span>
                      <span style={{ fontSize: "var(--fs-11)", color: "var(--text-subtle)", lineHeight: 1.35, whiteSpace: "normal" }}>{r.reasonDetail}</span>
                    </div>
                    <div className="off-grid-cell off-cell-num off-muted">{prM(r.currentCents)}</div>
                    <div className="off-grid-cell off-cell-num off-cell-strong">{r.recommendedCents == null ? <span className="off-muted" title={r.warn || ""}>no anchor</span> : prM(r.recommendedCents)}</div>
                    <div className="off-grid-cell off-cell-num" style={{ color: r.deltaCents > 0 ? "var(--paid-text)" : r.deltaCents < 0 ? "var(--void-text)" : "var(--text-subtle)" }}>{prSigned(r.deltaCents)}</div>
                    <div className="off-grid-cell off-cell-num" style={{ fontFamily: "var(--font-mono)", fontSize: "var(--fs-12)" }}>
                      <span className="off-muted">{prPct(r.marginNowPct)}</span>{r.marginRecPct != null && <span> → {prPct(r.marginRecPct)}</span>}
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// =================================================================
// DETAIL — the working, shown
// =================================================================
function PrTrace({ trace }) {
  return (
    <div style={{ display: "grid", gridTemplateColumns: "130px 110px 1fr", rowGap: 0 }}>
      {trace.map((t, i) => (
        <React.Fragment key={i}>
          <div style={{ padding: "9px 0", borderTop: i ? "1px solid var(--line)" : "none", fontSize: "var(--fs-12)", fontWeight: 600 }}>{t.k}</div>
          <div style={{ padding: "9px 8px", borderTop: i ? "1px solid var(--line)" : "none", fontFamily: "var(--font-mono)", fontSize: "var(--fs-12)", textAlign: "right" }}>{t.v}</div>
          <div style={{ padding: "9px 0 9px 14px", borderTop: i ? "1px solid var(--line)" : "none", fontSize: "var(--fs-12)", color: "var(--text-subtle)", lineHeight: 1.4 }}>{t.d}</div>
        </React.Fragment>
      ))}
    </div>
  );
}

function PriceDetail() {
  const { screenState, setScreen, setScreenState } = window.useOffice();
  const productId = screenState.priceProductId;
  const backTo = screenState.priceFrom || "pricing";
  const [methodId, setMethodId] = prState(screenState.priceMethod || undefined);
  const [methods, setMethods] = prState([]);
  const [d, setD] = prState(null);
  const [err, setErr] = prState(null);
  const [loading, setLoading] = prState(true);

  prEffect(() => {
    let alive = true;
    window.OfficeAPI.pricingMethods().then((ms) => { if (alive) setMethods(ms || []); }).catch(() => {});
    return () => { alive = false; };
  }, []);

  prEffect(() => {
    if (!productId) { setErr("No product selected."); setLoading(false); return; }
    let alive = true;
    setLoading(true); setErr(null);
    window.OfficeAPI.priceRecommendation(productId, methodId ? { method: methodId } : undefined)
      .then((x) => { if (alive) setD(x); })
      .catch((e) => { if (alive) setErr(e && e.message ? e.message : "Couldn't load the recommendation."); })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [productId, methodId]);

  const rec = d && d.recommendation;
  const p = d && d.product;
  const openProduct = () => { setScreenState((st) => ({ ...st, activeProductId: productId, productFrom: "priceDetail" })); setScreen("productDetail"); };

  return (
    <div className="off-screen">
      <header className="off-screen-header">
        <div className="off-screen-header-meta">
          <button className="btn btn--ghost btn--sm" style={{ marginBottom: 6, paddingLeft: 0 }} onClick={() => setScreen(backTo)}><window.OIcon name="chevron-left" /> Back</button>
          <span className="off-screen-eyebrow">live · this pharmacy · price recommendation</span>
          <h2 className="off-screen-title">{p ? p.name : "Price recommendation"}</h2>
          {p && <div style={{ fontSize: "var(--fs-12)", color: "var(--text-subtle)", fontFamily: "var(--font-mono)" }}>{p.sku || ""}{p.brand ? " · " + p.brand : ""}{p.category ? " · " + p.category : ""}{p.kvi ? " · KVI" : ""}</div>}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          {methods.length > 1 && (
            <div className="tabset">
              {methods.map((m) => (
                <button key={m.id} className="tabset-item" aria-selected={(methodId || (d && rec && rec.methodId)) === m.id} title={m.blurb} onClick={() => setMethodId(m.id)}>{m.name}</button>
              ))}
            </div>
          )}
          <button className="btn btn--secondary btn--sm" onClick={openProduct}><window.OIcon name="edit" /> Open product</button>
        </div>
      </header>

      <div className="off-screen-body">
        <PrAdvisoryNote />
        {err && <div className="off-card" style={{ borderColor: "var(--void-border)", background: "var(--void-bg)", color: "var(--void-text)", padding: "12px 16px" }}><window.OIcon name="alert" /> {err}</div>}
        {loading && !d && <div className="off-card" style={{ padding: "16px" }}>Working it out…</div>}

        {d && rec && (
          <div style={{ display: "grid", gridTemplateColumns: "minmax(0, 3fr) minmax(280px, 2fr)", gap: 16, alignItems: "start" }}>
            <div style={{ display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
              {/* the number */}
              <div className="off-card">
                <div className="off-card-header">
                  <div>
                    <div className="off-card-title">Recommendation</div>
                    <div className="off-card-meta">{d.methodName} · {rec.mode === "standard" ? "anchored calculation" : rec.mode === "fallback" ? "market-average fallback" : "no data to anchor to"}</div>
                  </div>
                </div>
                <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 14, padding: "4px 16px 16px" }}>
                  {[
                    { l: "Now", v: prM(rec.currentCents), sub: rec.currentGp ? prPct(rec.currentGp.marginPct) + " margin" : "no price set" },
                    { l: "Recommended", v: rec.recommendedCents == null ? "—" : prM(rec.recommendedCents), sub: rec.gp ? prPct(rec.gp.marginPct) + " margin" : "—", strong: true },
                    { l: "Move", v: prSigned(rec.deltaCents), sub: rec.deltaCents == null ? "" : rec.deltaCents > 0 ? "up" : rec.deltaCents < 0 ? "down" : "hold",
                      tone: rec.deltaCents > 0 ? "var(--paid-text)" : rec.deltaCents < 0 ? "var(--void-text)" : undefined },
                    { l: "Cost floor", v: rec.floorCents == null ? "—" : prM(rec.floorCents), sub: rec.taxable ? "inc GST" : "GST-free" },
                  ].map((x) => (
                    <div key={x.l}>
                      <div style={{ fontSize: "var(--fs-11)", color: "var(--text-subtle)", textTransform: "uppercase", letterSpacing: ".04em", fontWeight: 600 }}>{x.l}</div>
                      <div style={{ fontFamily: "var(--font-mono)", fontSize: x.strong ? 26 : 20, fontWeight: 700, color: x.tone, lineHeight: 1.2, marginTop: 4 }}>{x.v}</div>
                      <div style={{ fontSize: "var(--fs-11)", color: "var(--text-subtle)" }}>{x.sub}</div>
                    </div>
                  ))}
                </div>
                {rec.warn && (
                  <div style={{ margin: "0 16px 16px", padding: "10px 12px", borderRadius: 8, background: "var(--hold-bg)", color: "var(--hold-text)", fontSize: "var(--fs-12)", display: "flex", gap: 8 }}>
                    <window.OIcon name="alert" /><span>{rec.warn}</span>
                  </div>
                )}
                {rec.kvi && (
                  <div style={{ margin: "0 16px 16px", padding: "12px 14px", borderRadius: 8, background: "var(--navy-100)", color: "var(--navy-800)", fontSize: "var(--fs-12)" }}>
                    <div style={{ fontWeight: 700, marginBottom: 4 }}>KVI second pass</div>
                    <div>{rec.kvi.reason} Priced against the cheapest of {rec.kvi.set.map((o) => o.retailerShort).join(", ")} — <b>{rec.kvi.cheapest.retailerShort} at {prM(rec.kvi.cheapest.priceCents)}</b>, floor {prM(rec.kvi.floorCents)}.</div>
                    {rec.kvi.missing.length > 0 && <div style={{ marginTop: 4, opacity: .85 }}>Not seen on: {rec.kvi.missing.join(", ")} — the evidence is incomplete.</div>}
                  </div>
                )}
              </div>

              {/* the working */}
              <div className="off-card">
                <div className="off-card-header"><div><div className="off-card-title">The working</div><div className="off-card-meta">Every number above, with the step behind it</div></div></div>
                <div style={{ padding: "0 16px 12px" }}><PrTrace trace={rec.trace} /></div>
              </div>
            </div>

            <div style={{ display: "flex", flexDirection: "column", gap: 16, minWidth: 0 }}>
              {/* observations */}
              <div className="off-card">
                <div className="off-card-header"><div><div className="off-card-title">What we observed</div><div className="off-card-meta">{d.observations.length ? "Latest price per retailer, last 90 days" : "No observations in the last 90 days"}</div></div></div>
                {d.observations.map((o) => (
                  <div key={o.retailerId} style={{ display: "flex", alignItems: "flex-start", gap: 10, padding: "10px 16px", borderTop: "1px solid var(--line)", fontSize: "var(--fs-12)" }}>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 600, display: "flex", gap: 6, alignItems: "center" }}>
                        {o.url ? <a href={o.url} target="_blank" rel="noopener noreferrer" style={{ color: "var(--brand)", textDecoration: "none" }}>{o.retailerName}</a> : o.retailerName}
                        {o.onSale && <span title={o.saleEvidence || ""} style={{ fontSize: 9, fontWeight: 700, letterSpacing: .4, color: "var(--hold-text)", border: "1px solid var(--hold)", borderRadius: 4, padding: "1px 5px" }}>INFERRED SALE</span>}
                      </div>
                      <div style={{ color: "var(--text-subtle)" }}>{prDate(o.observedAt)}{o.saleEvidence ? " · " + o.saleEvidence : ""}</div>
                    </div>
                    <div style={{ fontFamily: "var(--font-mono)", fontWeight: 700 }}>{prM(o.priceCents)}</div>
                  </div>
                ))}
                {!d.observations.length && <div style={{ padding: "12px 16px", fontSize: "var(--fs-12)", color: "var(--text-subtle)" }}>Add one from Price position, or wait for the nightly Healthylife watch.</div>}
              </div>

              {/* cost + gst facts */}
              <div className="off-card">
                <div className="off-card-header"><div><div className="off-card-title">The facts it ran on</div></div></div>
                <div style={{ padding: "0 16px 12px", fontSize: "var(--fs-12)" }}>
                  {[
                    ["Cost of goods (ex GST)", prM(p.cogCents), p.costNote ? p.costNote : p.costSource === "invoice" ? "latest supplier invoice line" : p.costSource === "product" ? "stock card cost" : "no cost on file"],
                    ["Previous cost", prM(p.prevCostCents), p.prevCostCents != null && p.cogCents !== p.prevCostCents ? "moved " + prSigned(p.cogCents - p.prevCostCents) : ""],
                    ["GST", p.taxable ? "Taxable" : "GST-free", p.taxable ? "floor grossed up ×1.1" : (p.gstFreeReason || "")],
                    ["Price-sensitive (KVI)", p.kvi ? "Yes" : "No", p.kviReason || "not on the named list"],
                  ].map(([k, v, s]) => (
                    <div key={k} style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: 10, padding: "8px 0", borderTop: "1px solid var(--line)" }}>
                      <div><div style={{ fontWeight: 600 }}>{k}</div>{s ? <div style={{ color: "var(--text-subtle)" }}>{s}</div> : null}</div>
                      <div style={{ fontFamily: "var(--font-mono)", textAlign: "right" }}>{v}</div>
                    </div>
                  ))}
                </div>
              </div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

window.OFFICE_SCREENS = Object.assign(window.OFFICE_SCREENS || {}, { pricing: PricingReview, priceDetail: PriceDetail });
