// MostlyQR — public unit verification page at /Verify (F028).
//
// The consumer/reseller "is this genuine?" surface. A serialized code's printed destination points
// here (…/Verify?s=<serial>); the page reads the serial, calls the PUBLIC verifyUnitCode callable
// via window.MQRApi.verifyUnit (no auth — the printed serial is the credential), and shows a clear
// genuine / flagged / unknown verdict. Per-serial + runtime-fetched, so it's noindex (robots) and
// the prerendered shell is just the loading state; everything resolves client-side.
//
// English body copy by design (same as the /Compare + /Enterprise pages). Reuses the ent-vf styles
// from marketing.css.
// IIFE-scoped (see enterprise.jsx) — shared global scope across babel script tags, so keep all
// top-level names local; only export window.MQRVerify.
(function () {
const { Icon: IconVF, MQMark: MQMarkVF, Wordmark: WordmarkVF, QR: QRVF } = window.MQR;
const { Button: BtnVF } = window.ForgeDesignSystem_e40d74;

const HOME_VF = "/";

function serialFromUrl() {
  if (typeof window === "undefined" || !window.location) return "";
  try {
    const u = new URLSearchParams(window.location.search);
    const s = u.get("s") || u.get("serial") || "";
    return String(s).trim();
  } catch (e) { return ""; }
}

// Turn a scanned QR/DataMatrix payload into a candidate serial. Mirror of the tested
// `extractScannedSerial` in @mostly-tiny/serialize (the no-build web can't import the package);
// keep the two in lockstep. The backend validates the result, so this stays tolerant.
function serialFromScan(text) {
  const raw = typeof text === "string" ? text.trim() : "";
  if (!raw) return "";
  const dec = (v) => { try { return decodeURIComponent(v); } catch (e) { return v; } };
  const gs1 = raw.match(/(?:^|\/)21\/([^/?#]+)/); // GS1 Digital Link: serial = AI 21
  if (gs1) return dec(gs1[1]).trim();
  if (/:\/\//.test(raw) || raw.includes("/") || raw.includes("?")) {
    const qIdx = raw.indexOf("?");
    if (qIdx >= 0) {
      for (const pair of raw.slice(qIdx + 1).split(/[&#]/)) {
        const eq = pair.indexOf("=");
        const k = eq >= 0 ? pair.slice(0, eq) : pair;
        const v = eq >= 0 ? pair.slice(eq + 1) : "";
        if ((k === "s" || k === "serial") && v) return dec(v).trim();
      }
    }
    const seg = raw.split(/[?#]/)[0].split("/").filter(Boolean).pop();
    if (seg) return dec(seg).trim();
  }
  return raw;
}

// Lazy-load the html5-qrcode scanner (ZXing under the hood → reads QR *and* DataMatrix) — only on
// /Verify, only when the user taps Scan, so it never weighs on the marketing pages.
let _scannerLoad;
function loadScanner() {
  if (typeof window !== "undefined" && window.Html5Qrcode) return Promise.resolve(window.Html5Qrcode);
  if (_scannerLoad) return _scannerLoad;
  _scannerLoad = new Promise((resolve, reject) => {
    const sc = document.createElement("script");
    sc.src = "https://unpkg.com/html5-qrcode@2.3.8/html5-qrcode.min.js";
    sc.onload = () => resolve(window.Html5Qrcode);
    sc.onerror = () => { _scannerLoad = null; reject(new Error("scanner-load-failed")); };
    document.head.appendChild(sc);
  });
  return _scannerLoad;
}

const COPY = {
  genuine: { title: "Genuine", sub: "Authenticity confirmed", icon: "check" },
  flagged: { title: "Check this one", sub: "We couldn’t confirm this unit", icon: "shield" },
  unknown: { title: "Couldn’t verify", sub: "This code isn’t one we issued", icon: "x" },
};

// F032 v1 — certificate of authenticity, rendered CLIENT-SIDE (canvas → PNG). No backend needed,
// works on any device. (The server-side / bulk / variable-data PDF version is the MostlyRender
// integration — a deferred follow-up; this delivers the certificate to shoppers + resellers now.)
function downloadCertificate(result) {
  if (typeof document === "undefined") return;
  const pub = result.public || {};
  const W = 760, H = 1000, S = 2;
  const cv = document.createElement("canvas"); cv.width = W * S; cv.height = H * S;
  const x = cv.getContext("2d"); x.scale(S, S);
  x.fillStyle = "#ffffff"; x.fillRect(0, 0, W, H);
  x.strokeStyle = "#e6e8ee"; x.lineWidth = 2; x.strokeRect(24, 24, W - 48, H - 48);
  x.fillStyle = "#5b8def"; x.fillRect(24, 24, W - 48, 8);
  x.fillStyle = "#eaf1fd"; x.beginPath(); x.arc(W / 2, 150, 46, 0, Math.PI * 2); x.fill();
  x.strokeStyle = "#5b8def"; x.lineWidth = 3; x.beginPath(); x.arc(W / 2, 150, 46, 0, Math.PI * 2); x.stroke();
  x.strokeStyle = "#2f9e6f"; x.lineWidth = 6; x.lineCap = "round";
  x.beginPath(); x.moveTo(W / 2 - 18, 150); x.lineTo(W / 2 - 4, 164); x.lineTo(W / 2 + 20, 134); x.stroke();
  x.textAlign = "center";
  x.fillStyle = "#5b8def"; x.font = "700 15px ui-sans-serif, system-ui, sans-serif";
  x.fillText("CERTIFICATE OF AUTHENTICITY", W / 2, 252);
  x.fillStyle = "#1d1d1f"; x.font = "700 34px Georgia, 'Times New Roman', serif";
  x.fillText(pub.product || "Verified product", W / 2, 302);
  const rows = [];
  (pub.attributes || []).forEach((a) => rows.push([a.label, a.value]));
  if (result.serial) rows.push(["Serial", result.serial]);
  if (pub.batch) rows.push(["Batch", pub.batch]);
  let y = 384;
  rows.forEach(([k, v]) => {
    x.textAlign = "left"; x.fillStyle = "#8a8f98"; x.font = "600 13px ui-sans-serif, system-ui, sans-serif";
    x.fillText(String(k).toUpperCase(), 120, y);
    x.textAlign = "right"; x.fillStyle = "#1d1d1f"; x.font = "500 18px ui-sans-serif, system-ui, sans-serif";
    x.fillText(String(v), W - 120, y);
    x.strokeStyle = "#eef0f4"; x.lineWidth = 1; x.beginPath(); x.moveTo(120, y + 14); x.lineTo(W - 120, y + 14); x.stroke();
    y += 46;
  });
  x.textAlign = "center"; x.fillStyle = "#8a8f98"; x.font = "400 13px ui-sans-serif, system-ui, sans-serif";
  const d = new Date().toISOString().slice(0, 10);
  x.fillText("Verified by MostlyQR · " + d, W / 2, H - 92);
  x.fillStyle = "#b6bcc6"; x.font = "400 11px ui-sans-serif, system-ui, sans-serif";
  x.fillText("mostlyqr.com/Verify", W / 2, H - 68);
  cv.toBlob((b) => { const a = document.createElement("a"); a.href = URL.createObjectURL(b); a.download = "certificate-" + (result.serial || "unit") + ".png"; a.click(); });
}

function ResultCard({ result }) {
  const kind = result.status === "genuine" ? "genuine" : result.status === "flagged" ? "flagged" : "unknown";
  const c = COPY[kind];
  const pub = result.public || {};
  const flagged = kind !== "genuine";
  return (
    <div className={"ent-vf__card vf-result is-" + (kind === "genuine" ? "genuine" : "flagged")}>
      <div className="ent-vf__bar"><IconVF name="lock" size={11} sw={2.4} /> verified by MostlyQR</div>
      <div className="ent-vf__result">
        <span className={"ent-vf__badge " + (kind === "genuine" ? "is-good" : "is-bad")}>
          <IconVF name={c.icon} size={22} sw={2.4} />
        </span>
        <span className="ent-vf__verdict">{c.title}</span>
        <span className="ent-vf__sub">{result.detail || c.sub}</span>
      </div>
      <dl className="ent-vf__rows">
        {pub.product && <div><dt>Product</dt><dd>{pub.product}</dd></div>}
        {/* Digital product passport — the brand's attributes (Model, Release year, Material…). */}
        {Array.isArray(pub.attributes) && pub.attributes.map((a, i) => (
          <div key={"a" + i}><dt>{a.label}</dt><dd>{a.value}</dd></div>
        ))}
        {result.serial && <div><dt>Serial</dt><dd className="ent-mono">{result.serial}</dd></div>}
        {pub.batch && <div><dt>Batch</dt><dd className="ent-mono">{pub.batch}</dd></div>}
        {pub.region && (
          <div className={flagged ? "is-bad" : ""}>
            <dt>{flagged ? "Seen" : "Region"}</dt>
            <dd>{pub.region}{pub.scan_count ? ` · ${pub.scan_count} scan${pub.scan_count === 1 ? "" : "s"}` : ""}</dd>
          </div>
        )}
      </dl>
      {kind === "genuine" && (
        <div className="vf-cert">
          <button type="button" className="vf-certbtn" onClick={() => downloadCertificate(result)}>
            <IconVF name="download" size={14} sw={2} /> Download certificate of authenticity
          </button>
        </div>
      )}
    </div>
  );
}

function VerifyApp() {
  const [serial, setSerial] = React.useState("");
  const [input, setInput] = React.useState("");
  const [state, setState] = React.useState("idle"); // idle | loading | done | error
  const [result, setResult] = React.useState(null);
  const [scanning, setScanning] = React.useState(false);
  const [scanError, setScanError] = React.useState("");
  const scannerRef = React.useRef(null);
  const [mode, setMode] = React.useState("single"); // single | bulk (F029 reseller stock check)
  const [bulkText, setBulkText] = React.useState("");
  const [bulkResult, setBulkResult] = React.useState(null);
  const [bulkBusy, setBulkBusy] = React.useState(false);

  const run = React.useCallback(async (s) => {
    if (!s) return;
    setState("loading");
    try {
      const api = window.MQRApi;
      const r = api && api.verifyUnit ? await api.verifyUnit(s) : { serial: s, status: "unknown", reason: "not_found", public: {} };
      setResult(r);
      setState("done");
    } catch (e) { setState("error"); }
  }, []);

  const stopScan = React.useCallback(async () => {
    const r = scannerRef.current;
    scannerRef.current = null;
    if (r) { try { await r.stop(); } catch (e) { /* already stopped */ } try { r.clear(); } catch (e) { /* noop */ } }
    setScanning(false);
  }, []);

  const startScan = React.useCallback(async () => {
    setScanError("");
    setScanning(true);
    let Html5Qrcode;
    try { Html5Qrcode = await loadScanner(); }
    catch (e) { setScanError("Couldn’t load the scanner. Enter the serial below instead."); setScanning(false); return; }
    try {
      const fmts = window.Html5QrcodeSupportedFormats || {};
      // QR + ECC200 DataMatrix (2D) and the linear barcodes a brand might print the serial as
      // (Code 128 carries an arbitrary serial; EAN-13/UPC carry a GTIN). ZXith decodes them all.
      const reader = new Html5Qrcode("vf-reader", {
        formatsToSupport: [fmts.QR_CODE, fmts.DATA_MATRIX, fmts.CODE_128, fmts.EAN_13, fmts.UPC_A].filter((x) => x !== undefined),
        verbose: false,
      });
      scannerRef.current = reader;
      await reader.start(
        { facingMode: "environment" },
        { fps: 10, qrbox: { width: 230, height: 230 } },
        async (decoded) => { await stopScan(); const s = serialFromScan(decoded); setInput(s); setSerial(s); run(s); },
        () => {}, // per-frame "no code in view" — ignore
      );
    } catch (e) {
      scannerRef.current = null;
      setScanning(false);
      setScanError("Couldn’t open the camera — check permissions, or enter the serial below.");
    }
  }, [run, stopScan]);

  // On mount (client only): if the URL carries a serial, verify it straight away.
  React.useEffect(() => {
    const s = serialFromUrl();
    if (s) { setSerial(s); run(s); }
  }, [run]);

  // Always release the camera on unmount.
  React.useEffect(() => () => { stopScan(); }, [stopScan]);

  const onSubmit = (e) => {
    e.preventDefault();
    const s = input.trim();
    if (!s) return;
    setSerial(s);
    run(s);
  };

  // F029 — bulk reseller check: split on newlines/commas, verify all, render a table + CSV export.
  const runBulk = async () => {
    const lines = bulkText.split(/[\n,]+/).map((x) => x.trim()).filter(Boolean);
    if (!lines.length) return;
    setBulkBusy(true); setBulkResult(null);
    try {
      const api = window.MQRApi;
      const r = api && api.verifyUnitsBulk ? await api.verifyUnitsBulk(lines) : { count: 0, results: [] };
      setBulkResult(r);
    } catch (e) { setBulkResult({ error: true, results: [] }); } finally { setBulkBusy(false); }
  };
  const exportBulkCsv = () => {
    const rows = (bulkResult && bulkResult.results) || [];
    const esc = (v) => '"' + String(v == null ? "" : v).replace(/"/g, '""') + '"';
    const csv = ["serial,status,product,batch", ...rows.map((r) => [r.serial, r.status, (r.public || {}).product, (r.public || {}).batch].map(esc).join(","))].join("\n");
    const a = document.createElement("a");
    a.href = URL.createObjectURL(new Blob([csv], { type: "text/csv" }));
    a.download = "verify-results.csv"; a.click();
  };
  const bulkCounts = (bulkResult && bulkResult.results || []).reduce((m, r) => { m[r.status] = (m[r.status] || 0) + 1; return m; }, {});

  return (
    <div className="mk-root ent-root vf-page">
      <header className="mk-nav ent-nav">
        <div className="mk-wrap mk-nav__inner">
          <a className="mk-brand" href={HOME_VF}><MQMarkVF animate /><WordmarkVF /></a>
          <div className="mk-nav__cta" />
        </div>
      </header>

      <section className="vf-hero">
        <div className="mk-wrap vf-hero__inner">
          <span className="mk-eyebrow" style={{ color: "var(--accent)" }}>Product verification</span>
          <h1 className="ent-h1" style={{ color: "var(--fg)", fontSize: 40 }}>Is this the real thing?</h1>
          <p className="mk-lead" style={{ marginInline: "auto" }}>
            Scan or enter the code printed on your product and we’ll confirm it’s genuine — checked
            against the unit’s real history.
          </p>

          {mode === "single" ? (
            <div className="vf-stage">
              {/* Camera scanner — reads QR *and* DataMatrix. The reader div stays mounted so the
                  library always has its target element; CSS reveals it only while scanning. */}
              <div className={"vf-scanner" + (scanning ? " is-on" : "")}>
                <div id="vf-reader" className="vf-reader" />
                {scanning && (
                  <button type="button" className="vf-cancel" onClick={stopScan}>Cancel</button>
                )}
              </div>

              {state === "loading" && (
                <div className="vf-loading"><span className="vf-spinner" /> Verifying {serial}…</div>
              )}
              {state === "done" && result && <ResultCard result={result} />}
              {state === "error" && (
                <div className="vf-loading">Something went wrong. Please try again.</div>
              )}

              {!scanning && (state === "idle" || state === "done" || state === "error") && (
                <>
                  <button type="button" className="vf-scanbtn" onClick={startScan}>
                    <IconVF name="scan" size={18} sw={2} /> Scan with camera
                  </button>
                  {scanError && <div className="vf-scanerr"><IconVF name="x" size={13} sw={2.4} /> {scanError}</div>}
                  <div className="vf-or">or enter it by hand</div>
                  <form className="vf-form" onSubmit={onSubmit}>
                    <input
                      className="vf-input ent-mono"
                      placeholder="Enter serial (e.g. 00 084 7)"
                      value={input}
                      onChange={(e) => setInput(e.target.value)}
                      aria-label="Product serial"
                    />
                    <BtnVF type="submit" variant="primary" size="lg" iconRight={<IconVF name="arrow" size={16} />}>
                      Verify
                    </BtnVF>
                  </form>
                  <button type="button" className="vf-modelink" onClick={() => setMode("bulk")}>Checking a batch of stock? Verify many at once →</button>
                </>
              )}
            </div>
          ) : (
            <div className="vf-stage">
              {/* F029 — reseller / distributor bulk check */}
              <div className="vf-bulk">
                <p className="vf-bulk__lead">Paste the serials from your stock — one per line (bare serials, verify links, or scanned codes). We’ll check each against the brand’s records.</p>
                <textarea className="vf-bulk__input ent-mono" rows={6} placeholder={"00 084 7\n00 084 8\nhttps://mqr.sh/u/00 084 9"} value={bulkText} onChange={(e) => setBulkText(e.target.value)} />
                <BtnVF variant="primary" size="lg" disabled={bulkBusy} onClick={runBulk} iconRight={<IconVF name="arrow" size={16} />}>{bulkBusy ? "Checking…" : "Verify all"}</BtnVF>

                {bulkResult && bulkResult.results && bulkResult.results.length > 0 && (
                  <div className="vf-bulk__out">
                    <div className="vf-bulk__summary">
                      <span className="vf-chip is-good">{bulkCounts.genuine || 0} genuine</span>
                      <span className="vf-chip is-bad">{bulkCounts.flagged || 0} flagged</span>
                      <span className="vf-chip is-muted">{bulkCounts.unknown || 0} not found</span>
                      <button type="button" className="vf-bulk__csv" onClick={exportBulkCsv}><IconVF name="download" size={14} sw={2} /> Export CSV</button>
                    </div>
                    <div className="vf-bulk__table">
                      {bulkResult.results.map((r, i) => (
                        <div className={"vf-bulk__row is-" + (r.status === "genuine" ? "good" : r.status === "flagged" ? "bad" : "muted")} key={i}>
                          <span className="vf-bulk__sn ent-mono">{r.serial}</span>
                          <span className="vf-bulk__prod">{(r.public || {}).product || ""}</span>
                          <span className="vf-bulk__st">{r.status === "genuine" ? "Genuine" : r.status === "flagged" ? "Flagged" : "Not found"}</span>
                        </div>
                      ))}
                    </div>
                    {bulkResult.capped && <p className="vf-bulk__note">Showing the first {bulkResult.max}. Split larger lists into batches.</p>}
                  </div>
                )}
                {bulkResult && (!bulkResult.results || bulkResult.results.length === 0) && (
                  <div className="vf-loading">No serials to check.</div>
                )}
                <button type="button" className="vf-modelink" onClick={() => setMode("single")}>← Verify a single code</button>
              </div>
            </div>
          )}

          <p className="vf-foot">
            <IconVF name="shield" size={14} sw={2.2} /> Reads QR, DataMatrix &amp; barcodes · free · works on any phone — no app needed.
          </p>
        </div>
      </section>
    </div>
  );
}

window.MQRVerify = VerifyApp;
})();
