// SkuIntelligencePage — window.SkuIntelligencePage
//
// Per-SKU / product intelligence: revenue overview, profitability (real margin,
// not allocated), ABC analysis and a per-SKU detail panel.
//
// HONEST DATA SOURCING: built from data.dimensions.salesLineItems (sku,
// product_name, category, order_date, quantity, line_total_cents,
// line_cost_cents, line_gross_profit_cents, unit_price_cents). Margin is REAL
// (line_gross_profit_cents) — no allocation. When no sales line items exist the
// page shows an honest empty state. sales_line_items carries NO customer key, so
// the "customer mix" view is honestly gated, never fabricated.

(function () {
  const h = React.createElement;
  const { useState } = React;

  const num = (v) => { const n = Number(v); return Number.isFinite(n) ? n : 0; };
  const cents = (v) => num(v) / 100;
  const fmtMonYr = (d) => { try { return new Date(d).toLocaleDateString("en-US", { month: "short", year: "numeric" }); } catch (e) { return d || "—"; } };
  const fmtYM = (ym) => { try { const [y, m] = ym.split("-"); return new Date(+y, +m - 1, 1).toLocaleDateString("en-US", { month: "short", year: "2-digit" }); } catch (e) { return ym; } };

  function monthsInRange(range) {
    const out = [];
    if (!range || !range.start || !range.end) return out;
    let y = range.start.getFullYear(), m = range.start.getMonth();
    const ey = range.end.getFullYear(), em = range.end.getMonth();
    while (y < ey || (y === ey && m <= em)) { out.push(y + "-" + String(m + 1).padStart(2, "0")); m++; if (m > 11) { m = 0; y++; } if (out.length > 60) break; }
    return out;
  }

  function marginRisk(pct) {
    if (pct == null) return { dot: "⚪", label: "No cost data", color: "#6475a0" };
    if (pct >= 35) return { dot: "🟢", label: "Healthy", color: "#059669" };
    if (pct >= 20) return { dot: "🟡", label: "Watch", color: "#d97706" };
    return { dot: "🔴", label: "Thin", color: "#DC2626" };
  }

  function exportSkuCsv(s, months) {
    const headers = ["Month", "Revenue", "Units", "Avg Price"];
    const rows = months.map((ym) => { const rev = s.byMonth[ym] || 0; const u = s.unitsByMonth[ym] || 0; return [ym, Math.round(rev), u, u ? Math.round(rev / u) : ""]; });
    const meta = [["PerduraCFO — SKU Report: " + s.name + " (" + s.sku + ")"], ["Revenue (period): " + Math.round(s.revenue)], ["Units: " + s.units], ["Avg price: " + (s.avgPrice != null ? Math.round(s.avgPrice) : "n/a")], ["Margin: " + (s.marginPct != null ? s.marginPct.toFixed(1) + "%" : "n/a")], ["Exported: " + new Date().toLocaleDateString()], [], headers, ...rows];
    const csv = meta.map((row) => row.map((cell) => { const str = String(cell == null ? "" : cell); return (str.includes(",") || str.includes("\"") || str.includes("\n")) ? "\"" + str.replace(/"/g, "\"\"") + "\"" : str; }).join(",")).join("\n");
    const blob = new Blob(["﻿" + csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = String(s.sku || s.name).replace(/[^a-z0-9]/gi, "_") + "_sku_report.csv";
    document.body.appendChild(a); a.click(); document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }

  // ── SKU model from sales line items ─────────────────────────────────────────
  function buildModel(sli, range, cmpRange) {
    const start = +range.start, end = +range.end;
    const inWin = sli.filter((it) => { const d = it.order_date ? +new Date(it.order_date) : 0; return d >= start && d <= end; });
    const firstSeen = {};
    sli.forEach((it) => { const k = (it.sku || it.product_name || "—").toString(); const d = it.order_date || ""; if (!firstSeen[k] || d < firstSeen[k]) firstSeen[k] = d; });
    const priorByS = {};
    if (cmpRange) { const ps = +cmpRange.start, pe = +cmpRange.end; sli.forEach((it) => { const d = it.order_date ? +new Date(it.order_date) : 0; if (d >= ps && d <= pe) { const k = (it.sku || it.product_name || "—").toString(); priorByS[k] = (priorByS[k] || 0) + cents(it.line_total_cents); } }); }

    const by = {};
    inWin.forEach((it) => {
      const k = (it.sku || it.product_name || "—").toString();
      const rev = cents(it.line_total_cents);
      const cst = cents(it.line_cost_cents);
      const gp = it.line_gross_profit_cents != null ? cents(it.line_gross_profit_cents) : (rev - cst);
      const q = num(it.quantity);
      const o = by[k] || (by[k] = { sku: k, name: it.product_name || k, category: it.category || "Uncategorised", revenue: 0, units: 0, cost: 0, gp: 0, hasCost: false, byMonth: {}, unitsByMonth: {} });
      o.revenue += rev; o.units += q; o.cost += cst; o.gp += gp;
      if (it.line_cost_cents != null || it.line_gross_profit_cents != null) o.hasCost = true;
      const ym = (it.order_date || "").slice(0, 7);
      if (ym) { o.byMonth[ym] = (o.byMonth[ym] || 0) + rev; o.unitsByMonth[ym] = (o.unitsByMonth[ym] || 0) + q; }
    });

    const total = Object.values(by).reduce((s, x) => s + x.revenue, 0);
    const months = monthsInRange(range);
    let list = Object.values(by).map((s) => Object.assign({}, s, {
      pct: total > 0 ? s.revenue / total : 0,
      avgPrice: s.units ? s.revenue / s.units : null,
      marginPct: (s.hasCost && s.revenue > 0) ? s.gp / s.revenue * 100 : null,
      prior: priorByS[s.sku] || 0,
      trendPct: (priorByS[s.sku] > 0) ? (s.revenue - priorByS[s.sku]) / priorByS[s.sku] * 100 : null,
      isNew: !!firstSeen[s.sku] && (+new Date(firstSeen[s.sku]) >= start),
      spark: months.map((ym) => s.byMonth[ym] || 0),
    })).sort((a, b) => b.revenue - a.revenue);

    // ABC classification by cumulative revenue share (A ≤80%, B ≤95%, C rest).
    let cum = 0;
    list.forEach((s) => { cum += s.revenue; const share = total > 0 ? cum / total : 1; s.abc = share <= 0.8 ? "A" : share <= 0.95 ? "B" : "C"; });

    const top1 = list[0] ? list[0].pct : 0;
    const decliningCount = list.filter((s) => s.trendPct != null && s.trendPct < -5).length;
    const withMargin = list.filter((s) => s.marginPct != null);
    return { list, total, count: list.length, months, top1, decliningCount, withMargin };
  }

  function Page(props) {
    const K = window.PerduraPageKit;
    if (!K) return h("div", { className: "pc-page" }, "Loading…");
    const { data } = props;
    const MONO = K.MONO, INK = K.INK, MUTE = K.MUTE, POS = K.POS, NEG = K.NEG;
    const M = (v) => K.moneyStr(v, { compact: true });
    const Mf = (v) => K.moneyStr(v);

    const dims = (data && data.dimensions) || {};
    const sli = (dims.salesLineItems || data.salesLineItems || []).filter((it) => it && it.order_date);

    const plH = (data && (data.plHistory || data.pl)) || { labels: [], revenue: [] };
    const anchor = K.anchorFromPlH(plH);
    const ps = K.usePeriodState("sku_intel", "ltm");
    const range = K.resolvePeriod(ps.mode, anchor, ps.custom);
    const cmpRange = K.comparePeriod(range, ps.cmp);

    const [tab, setTab] = useState("overview");
    const [selected, setSelected] = useState(null);
    const [rowLimit, setRowLimit] = useState(25);

    if (!sli.length) {
      return h(K.Shell, { hero: { eyebrow: "ANALYTICS", title: "SKU Intelligence", subtitle: "Per-product revenue, margin and ABC analysis" } },
        h(K.Card, { title: "Product tracking not connected" },
          h("div", { style: { padding: 24, color: MUTE, fontSize: 13, lineHeight: 1.7 } },
            "Connect your accounting software and enable product tracking to unlock SKU intelligence. ",
            "Per-SKU revenue, units, real gross margin and ABC analysis are built from ", h("b", null, "sales line items"), " (sku, quantity, line total & cost). Once product-level sales sync, this page lights up automatically.")));
    }

    const model = buildModel(sli, range, cmpRange);
    const { list, total, count, months, top1, decliningCount, withMargin } = model;
    const revPerSku = count ? total / count : 0;
    const openSku = (sku) => { setSelected(sku); setTab("detail"); };

    const hero = {
      eyebrow: "ANALYTICS",
      title: "SKU Intelligence",
      subtitle: count + " SKU" + (count === 1 ? "" : "s") + " · " + Mf(total) + " revenue · " + Mf(revPerSku) + " avg per SKU · " + range.label,
      controls: h(K.PeriodControls, ps),
    };

    const TABS = [["overview", "📊 Revenue Overview"], ["profitability", "💰 Profitability"], ["detail", "📦 SKU Detail"]];
    const tabBar = h("div", { style: { display: "flex", gap: 4, borderBottom: "2px solid rgba(13,32,64,.08)", marginBottom: 22, overflowX: "auto" } },
      TABS.map(([id, label]) => h("button", { key: id, onClick: () => setTab(id), style: { padding: "10px 18px", fontSize: 12, fontWeight: 700, cursor: "pointer", border: "none", borderBottom: tab === id ? "3px solid #0d2040" : "3px solid transparent", background: "transparent", color: tab === id ? "#0d2040" : "#6475a0", whiteSpace: "nowrap" } }, label)));

    const kpiRow = h("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))", gap: 14, marginBottom: 22 } },
      h(K.Kpi, { label: "Total SKUs", value: String(count), sub: range.label, accent: "#1C4ED8" }),
      h(K.Kpi, { label: "Revenue / SKU", value: M(revPerSku), accent: "#0891B2" }),
      h(K.Kpi, { label: "Top SKU", value: (top1 * 100).toFixed(0) + "%", sub: list[0] ? list[0].name : "—", accent: top1 >= 0.3 ? "#DC2626" : "#059669", onClick: list[0] ? () => openSku(list[0].sku) : undefined }),
      h(K.Kpi, { label: "Declining SKUs", value: String(decliningCount), sub: "revenue down >5% vs prior", accent: decliningCount ? "#d97706" : "#18a867" }));

    // ── Tab 1 — Revenue Overview ──────────────────────────────────────────────
    function overviewTab() {
      const shown = list.slice(0, rowLimit);
      const trendCell = (s) => {
        if (s.trendPct == null) return h("span", { style: { color: MUTE, fontSize: 11 } }, s.isNew ? "new" : "—");
        const up = s.trendPct >= 0;
        return h("span", { style: { color: up ? POS : NEG, fontWeight: 700, fontFamily: MONO, fontSize: 11 } }, (up ? "▲ " : "▼ ") + Math.abs(s.trendPct).toFixed(0) + "%");
      };
      const rows = shown.map((s) => { const r = marginRisk(s.marginPct); return h("tr", { key: s.sku, style: { cursor: "pointer" }, onClick: () => openSku(s.sku), title: "Open " + s.name + " detail" },
        h("td", { style: { fontFamily: MONO, color: MUTE } }, s.sku),
        h("td", { style: { fontWeight: 700, color: INK } }, s.name, s.isNew ? h("span", { style: { marginLeft: 6, fontSize: 9, fontWeight: 700, color: "#065f46", background: "#d1fae5", padding: "1px 6px", borderRadius: 10 } }, "NEW") : null),
        h("td", { className: "num", style: { fontFamily: MONO, fontWeight: 700 } }, M(s.revenue)),
        h("td", { className: "num", style: { fontFamily: MONO } }, s.units ? Math.round(s.units).toLocaleString() : "—"),
        h("td", { className: "num", style: { fontFamily: MONO } }, s.avgPrice != null ? Mf(s.avgPrice) : "—"),
        h("td", { className: "num" }, trendCell(s)),
        h("td", { className: "num", style: { fontFamily: MONO, fontWeight: 700, color: r.color } }, s.marginPct != null ? s.marginPct.toFixed(0) + "%" : "—")); });
      const table = h("table", { className: "pa-table", style: { width: "100%" } },
        h("thead", null, h("tr", null, h("th", null, "SKU"), h("th", null, "Name"), h("th", { className: "num" }, "Revenue"), h("th", { className: "num" }, "Units"), h("th", { className: "num" }, "Avg Price"), h("th", { className: "num" }, "Trend"), h("th", { className: "num" }, "Margin"))),
        h("tbody", null, rows));
      const moreBtn = list.length > rowLimit ? h("div", { style: { padding: 12, textAlign: "center" } },
        h("button", { onClick: () => setRowLimit((n) => n + 25), style: { padding: "7px 16px", background: "#f0f4ff", color: "#1C4ED8", border: "1px solid #dbeafe", borderRadius: 8, cursor: "pointer", fontSize: 12, fontWeight: 600 } }, "Show 25 more (" + (list.length - rowLimit) + " left)")) : null;
      return h("div", null, kpiRow,
        h(K.Card, { title: "SKU Revenue", sub: "Sorted by revenue · click a SKU for full detail", padding: 0 }, h("div", { style: { overflowX: "auto" } }, table), moreBtn));
    }

    // ── Tab 2 — Profitability + ABC ───────────────────────────────────────────
    function profitabilityTab() {
      const noCost = withMargin.length === 0;
      const marginRanked = withMargin.slice().sort((a, b) => b.marginPct - a.marginPct);
      const barTop = marginRanked.slice(0, 15);
      const maxMargin = Math.max.apply(null, barTop.map((s) => s.marginPct).concat([1]));
      const marginBars = h("div", { style: { display: "flex", flexDirection: "column", gap: 8 } },
        barTop.map((s) => h("div", { key: s.sku, style: { cursor: "pointer" }, onClick: () => openSku(s.sku) },
          h("div", { style: { display: "flex", justifyContent: "space-between", fontSize: 12, marginBottom: 3 } },
            h("span", { style: { color: INK, fontWeight: 600 } }, s.name),
            h("span", { style: { color: marginRisk(s.marginPct).color, fontFamily: MONO, fontWeight: 700 } }, s.marginPct.toFixed(1) + "%")),
          h("div", { style: { height: 8, background: "#f0f4ff", borderRadius: 4 } }, h("div", { style: { width: Math.max(s.marginPct / maxMargin * 100, 1) + "%", height: "100%", background: marginRisk(s.marginPct).color, borderRadius: 4 } })))));
      const abc = { A: list.filter((s) => s.abc === "A"), B: list.filter((s) => s.abc === "B"), C: list.filter((s) => s.abc === "C") };
      const abcCard = (key, title, tone, note) => h("div", { style: { borderLeft: "3px solid " + tone, background: "rgba(13,32,64,.02)", borderRadius: 6, padding: "10px 14px", marginBottom: 10 } },
        h("div", { style: { fontSize: 12, fontWeight: 800, color: tone, marginBottom: 4 } }, title + " — " + abc[key].length + " SKU" + (abc[key].length === 1 ? "" : "s") + " · " + M(abc[key].reduce((s, x) => s + x.revenue, 0))),
        h("div", { style: { fontSize: 11.5, color: MUTE, marginBottom: 6 } }, note),
        h("div", { style: { fontSize: 11.5, color: INK } }, abc[key].slice(0, 12).map((s) => s.name).join(", ") + (abc[key].length > 12 ? " +" + (abc[key].length - 12) + " more" : "")));
      const caveat = noCost ? h("div", { style: { background: "#fff7ed", border: "1px solid #fed7aa", borderRadius: 10, padding: "12px 16px", marginBottom: 16, fontSize: 12.5, color: "#9a3412", lineHeight: 1.6 } }, h("b", null, "Margin unavailable: "), "Sales line items carry no unit cost for this window, so gross margin can't be computed. ABC analysis (below) is revenue-based and still valid.") : null;
      return h("div", null, caveat,
        h("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, alignItems: "start" } },
          h(K.Card, { title: "Margin by SKU", sub: noCost ? "No cost data in window" : "Top 15 by gross margin · click to drill" }, noCost ? h("div", { style: { padding: 16, color: MUTE, fontSize: 12.5 } }, "No SKUs with cost data in this window.") : marginBars),
          h(K.Card, { title: "ABC Analysis", sub: "By cumulative revenue share" },
            abcCard("A", "A items (top 80% of revenue)", "#059669", "Your revenue engine — protect availability, pricing and supply."),
            abcCard("B", "B items (next 15%)", "#d97706", "Solid mid-tail — monitor for movement into A or C."),
            abcCard("C", "C items (bottom 5%)", "#DC2626", "Long tail — review for rationalisation, bundling or discontinuation."))));
    }

    // ── Tab 3 — SKU Detail ────────────────────────────────────────────────────
    function detailTab() {
      const s = list.find((x) => x.sku === selected) || list[0];
      if (!s) return h(K.Card, { title: "SKU Detail" }, h("div", { style: { padding: 20, color: MUTE } }, "No SKU selected."));
      const monthBars = months.map((ym) => ({ ym, rev: s.byMonth[ym] || 0, units: s.unitsByMonth[ym] || 0 }));
      const maxRev = Math.max.apply(null, monthBars.map((m) => m.rev).concat([1]));
      const priceBars = monthBars.map((m) => ({ ym: m.ym, price: m.units ? m.rev / m.units : 0 }));
      const maxPrice = Math.max.apply(null, priceBars.map((m) => m.price).concat([1]));

      const picker = list.length > 1
        ? h("select", { value: s.sku, onChange: (e) => setSelected(e.target.value), style: { padding: "6px 10px", border: "1px solid " + K.LINE, borderRadius: 7, fontSize: 12, fontWeight: 600, color: INK, cursor: "pointer" } }, list.slice(0, 300).map((x) => h("option", { key: x.sku, value: x.sku }, x.name + " (" + x.sku + ")")))
        : null;
      const header = h("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, gap: 12, flexWrap: "wrap" } },
        h("div", { style: { display: "flex", alignItems: "center", gap: 12 } },
          h(K.BackButton, { label: "all SKUs", onClick: () => setTab("overview") }), picker,
          h("div", null, h("span", { style: { fontSize: 20, fontWeight: 800, color: INK } }, s.name), h("span", { style: { fontSize: 12, color: MUTE, marginLeft: 8, fontFamily: MONO } }, s.sku))),
        h("button", { onClick: () => exportSkuCsv(s, months), style: { padding: "7px 14px", background: "#f0fdf4", color: "#065f46", border: "1px solid #bbf7d0", borderRadius: 8, cursor: "pointer", fontSize: 12, fontWeight: 600 } }, "⬇️ Export SKU report"));

      const stat = (label, value, sub) => h("div", { style: { padding: "10px 4px" } },
        h("div", { style: { fontSize: 9, fontWeight: 700, letterSpacing: "1px", textTransform: "uppercase", color: "#6475a0", fontFamily: MONO, marginBottom: 4 } }, label),
        h("div", { style: { fontSize: 17, fontWeight: 800, color: INK, fontFamily: MONO } }, value),
        sub ? h("div", { style: { fontSize: 10.5, color: MUTE, marginTop: 2 } }, sub) : null);
      const statsGrid = h("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(150px,1fr))", gap: 8 } },
        stat("Revenue (" + range.label + ")", M(s.revenue), s.trendPct != null ? ((s.trendPct >= 0 ? "▲ " : "▼ ") + Math.abs(s.trendPct).toFixed(0) + "% vs prior") : (s.isNew ? "new this period" : null)),
        stat("Units", s.units ? Math.round(s.units).toLocaleString() : "—", s.category),
        stat("Avg price", s.avgPrice != null ? Mf(s.avgPrice) : "—"),
        stat("Margin", s.marginPct != null ? s.marginPct.toFixed(1) + "%" : "—", s.marginPct != null ? marginRisk(s.marginPct).label : "no cost data"),
        stat("ABC class", s.abc || "—", s.abc === "A" ? "top 80% of revenue" : s.abc === "B" ? "next 15%" : "bottom 5%"),
        stat("Share of revenue", (s.pct * 100).toFixed(1) + "%"));
      const statsCard = h(K.Card, { padding: "6px 18px" }, statsGrid);

      const revBars = h("div", { style: { display: "flex", alignItems: "flex-end", gap: 4, height: 90 } },
        monthBars.map((mb) => h("div", { key: mb.ym, title: fmtYM(mb.ym) + ": " + Mf(mb.rev) + " · " + Math.round(mb.units) + " units", style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 3 } },
          h("div", { style: { width: "100%", background: mb.rev ? "#1C4ED8" : "#eef2f9", height: Math.max((mb.rev / maxRev) * 70, 2), borderRadius: "3px 3px 0 0" } }),
          h("div", { style: { fontSize: 8, color: MUTE, whiteSpace: "nowrap" } }, fmtYM(mb.ym)))));
      const revCard = h("div", { style: { marginTop: 16 } }, h(K.Card, { title: "Monthly Revenue", sub: "Invoiced product revenue by month" }, revBars));

      const priceRow = h("div", { style: { display: "flex", alignItems: "flex-end", gap: 4, height: 70 } },
        priceBars.map((mb) => h("div", { key: mb.ym, title: fmtYM(mb.ym) + ": " + (mb.price ? Mf(mb.price) : "—"), style: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", gap: 3 } },
          h("div", { style: { width: "100%", background: mb.price ? "#0891B2" : "#e6f2f5", height: Math.max((mb.price / maxPrice) * 52, 2), borderRadius: "3px 3px 0 0" } }),
          h("div", { style: { fontSize: 8, color: MUTE, whiteSpace: "nowrap" } }, fmtYM(mb.ym)))));
      const priceCard = h("div", { style: { marginTop: 16 } }, h(K.Card, { title: "Average Selling Price Trend", sub: "Revenue ÷ units per month — watch for price erosion" }, priceRow));

      // Customer mix is NOT derivable: sales_line_items carries no customer key.
      const custCard = h("div", { style: { marginTop: 16 } },
        h(K.Card, { title: "Customer Mix", sub: "Which customers buy this SKU" },
          h("div", { style: { padding: 16, color: MUTE, fontSize: 12.5, lineHeight: 1.7 } },
            "Customer attribution isn't available on sales line items — the product-sales feed records SKU, quantity and amount, but no customer key. ",
            "Connect order-level customer linkage (order → customer) to see which customers buy ", h("b", null, s.name), ".")));

      return h("div", null, header, statsCard, revCard, priceCard, custCard);
    }

    const body = tab === "overview" ? overviewTab()
      : tab === "profitability" ? profitabilityTab()
      : detailTab();
    return h(K.Shell, { hero }, tabBar, body);
  }

  window.SkuIntelligencePage = Page;
})();
