/* =========================================================================
   ScanIQ — Sales edge engine
   -------------------------------------------------------------------------
   Computes where the anchor (Honeywell) product objectively beats every
   competitor in the comparison, using only specs with an unambiguous
   "better" direction. Conservative by design: a row only counts when the
   hero value is strictly better than EVERY rival that publishes the spec.
   ========================================================================= */

/* ---------- parsers (return null when not confidently parseable) ---------- */
const SalesEdgeParse = {
  resArea(s) { const m = String(s || "").match(/(\d{2,4})\s*[x×]\s*(\d{2,4})/i); return m ? (+m[1]) * (+m[2]) : null; },
  firstNumOf(s) { const m = String(s || "").replace(/,/g, "").match(/\d+(\.\d+)?/); return m ? parseFloat(m[0]) : null; },
  weightG(s) { const ms = [...String(s || "").matchAll(/(\d+(?:\.\d+)?)\s*g\b/gi)].map((m) => parseFloat(m[1])); return ms.length ? Math.min(...ms) : null; },
  currentMa(s) { const m = String(s || "").match(/(\d+(?:\.\d+)?)\s*mA/i); return m ? parseFloat(m[1]) : null; },
  rangeMm(s) { const m = String(s || "").replace(/,/g, "").match(/(\d+(?:\.\d+)?)\s*mm\s*to\s*(\d+(?:\.\d+)?)\s*mm/i); return m ? { near: +m[1], far: +m[2], depth: +m[2] - +m[1] } : null; },
  tempSpan(s) { const m = String(s || "").match(/(-?\d+)\s*°?\s*C\s*to\s*(-?\d+)\s*°?\s*C/i); return m ? (+m[2]) - (+m[1]) : null; },
  months(s) { const m = String(s || "").match(/(\d+)\s*month/i); return m ? +m[1] : null; },
};

/* Directional rules: how to parse, which way is better, how to phrase it */
const SALES_EDGE_RULES = [
  { key: "resolution_px", label: "Sensor resolution", parse: SalesEdgeParse.resArea, dir: "high",
    phrase: (h, r, hv, rv) => `${hv} vs ${rv}`, show: (p) => p.specs.resolution_px },
  { key: "frames_per_second", label: "Frame rate", parse: SalesEdgeParse.firstNumOf, dir: "high",
    phrase: (h, r) => `${h} fps vs ${r} fps` },
  { key: "motion_tolerance_m_s", label: "Motion tolerance", parse: SalesEdgeParse.firstNumOf, dir: "high",
    phrase: (h, r) => (r > 0 ? `${(h / r).toFixed(1).replace(/\.0$/, "")}× higher — ${h} vs ${r} m/s` : `${h} m/s`) },
  { key: "resolution_1d", label: "Finest 1D resolution", parse: SalesEdgeParse.firstNumOf, dir: "low",
    phrase: (h, r) => `reads ${h} mil codes vs ${r} mil` },
  { key: "symbol_contrast", label: "Symbol contrast", parse: SalesEdgeParse.firstNumOf, dir: "low",
    phrase: (h, r) => `works from ${h}% contrast vs ${r}%` },
  { key: "weight", label: "Weight", parse: SalesEdgeParse.weightG, dir: "low",
    phrase: (h, r) => `${Math.round((1 - h / r) * 100)}% lighter — ${h} g vs ${r} g` },
  { key: "typical_current", label: "Power draw", parse: SalesEdgeParse.currentMa, dir: "low",
    phrase: (h, r) => `${h} mA vs ${r} mA while scanning` },
  { key: "operating_temperature", label: "Operating temperature", parse: SalesEdgeParse.tempSpan, dir: "high",
    phrase: (h, r) => `${h}°C span vs ${r}°C` },
  { key: "warranty", label: "Warranty", parse: SalesEdgeParse.months, dir: "high",
    phrase: (h, r) => `${h} months vs ${r}` },
];

/* hero strictly better than every rival that publishes the spec */
function edgeOnRule(rule, hero, rivals) {
  const hv = rule.parse(hero.specs[rule.key]);
  if (hv === null) return null;
  const rvs = rivals.map((p) => rule.parse(p.specs[rule.key])).filter((v) => v !== null);
  if (!rvs.length) return null;
  const better = (a, b) => (rule.dir === "high" ? a > b : a < b);
  if (!rvs.every((rv) => better(hv, rv))) return null;
  /* phrase against the closest rival (most honest comparison) */
  const closest = rule.dir === "high" ? Math.max(...rvs) : Math.min(...rvs);
  if (rule.key === "resolution_px") {
    const fmt = (p) => String(p.specs.resolution_px).match(/\d{2,4}\s*[x×]\s*\d{2,4}/i)[0].replace(/\s*[x×]\s*/i, " × ");
    const rBest = rivals.filter((p) => rule.parse(p.specs[rule.key]) === closest)[0];
    return { key: rule.key, label: rule.label, detail: `${fmt(hero)} vs ${fmt(rBest)} px` };
  }
  return { key: rule.key, label: rule.label, detail: rule.phrase(hv, closest) };
}

function computeSalesEdge(products) {
  const heroIdx = products.findIndex((p) => p.brand === "honeywell");
  const hero = heroIdx >= 0 ? products[heroIdx] : null;
  const rivals = products.filter((p) => p.brand !== "honeywell");
  if (!hero || !rivals.length) return { available: false, heroIdx: -1, items: [], keys: {} };

  const items = [];
  const keys = {};

  for (const rule of SALES_EDGE_RULES) {
    const win = edgeOnRule(rule, hero, rivals);
    if (win) { items.push(win); keys[win.key] = true; }
  }

  /* read-range rows: aggregate into one talking point, mark each winning row */
  const db = window.SPECDB;
  const rangeSec = db.sections.find((s) => /read range/i.test(s.name));
  if (rangeSec) {
    let wins = 0, comparable = 0;
    for (const row of rangeSec.rows) {
      const hv = SalesEdgeParse.rangeMm(hero.specs[row.key]);
      if (!hv) continue;
      const rvs = rivals.map((p) => SalesEdgeParse.rangeMm(p.specs[row.key])).filter(Boolean);
      if (!rvs.length) continue;
      comparable++;
      if (rvs.every((rv) => hv.depth > rv.depth)) { wins++; keys[row.key] = true; }
    }
    if (wins > 0) {
      items.push({
        key: "__readrange", label: "Read range",
        detail: `deeper working range on ${wins} of ${comparable} comparable barcodes`,
      });
    }
  }

  return { available: true, heroIdx, hero, rivals, items, keys };
}

/* ---------- "Why <hero>" summary card ---------- */
function WhyHeroCard({ edge }) {
  const b = window.SPECDB.brands[edge.hero.brand];
  return (
    <div className="whycard" data-comment-anchor="why-hero-card">
      <span className="whycard-bar" style={{ background: b.color }}></span>
      <div className="whycard-head">
        <div className="whycard-title">Why {edge.hero.model}</div>
        <div className="whycard-vs">vs {edge.rivals.map((r) => r.model).join(" · ")}</div>
      </div>
      {edge.items.length ? (
        <div className="whycard-grid">
          {edge.items.map((it) => (
            <div key={it.key} className="whycard-item">
              <span className="whycard-itemlabel">{it.label}</span>
              <span className="whycard-itemdetail">{it.detail}</span>
            </div>
          ))}
        </div>
      ) : (
        <div className="whycard-empty">No clear published-spec advantages in this match-up — lead with ecosystem, supply and support.</div>
      )}
      <div className="whycard-foot">Auto-generated from published specs · winning rows are marked ▲ in the table · visible only while Sales mode is on</div>
    </div>
  );
}

Object.assign(window, { computeSalesEdge, WhyHeroCard });
