// qr.jsx — real QR generation (qrcode-generator) + custom SVG render + downloads.
// Exports to window: buildQRPayload, QRPreview, downloadQRPng, downloadQRSvg, qrContentLabel

// Build the string that gets encoded based on the chosen content type.
function buildQRPayload(form) {
  if (!form) return " ";
  const type = form.contentType || "contact";
  if (type === "url") {
    return (form.url || "").trim() || "https://example.com";
  }
  if (type === "text") {
    return (form.text || form.message || "").trim() || " ";
  }
  // contact -> vCard 3.0
  const fn = `${form.firstName || ""} ${form.lastName || ""}`.trim();
  const lines = [
    "BEGIN:VCARD",
    "VERSION:3.0",
    `N:${form.lastName || ""};${form.firstName || ""};;;`,
    `FN:${fn || "Contact"}`,
  ];
  if (form.phone) lines.push(`TEL;TYPE=CELL:${form.phone}`);
  if (form.email) lines.push(`EMAIL;TYPE=INTERNET:${form.email}`);
  if (form.message) lines.push(`NOTE:${form.message.replace(/\n/g, "\\n")}`);
  const handle = (v) => (v || "").trim().replace(/^@+/, "");
  if (handle(form.instagram)) lines.push(`URL;TYPE=Instagram:https://instagram.com/${handle(form.instagram)}`);
  if (handle(form.snapchat)) lines.push(`URL;TYPE=Snapchat:https://snapchat.com/add/${handle(form.snapchat)}`);
  if (handle(form.tiktok)) lines.push(`URL;TYPE=TikTok:https://tiktok.com/@${handle(form.tiktok)}`);
  lines.push("END:VCARD");
  return lines.join("\n");
}

function qrContentLabel(form, t) {
  const type = form.contentType || "contact";
  if (type === "url") return form.url || "—";
  if (type === "text") return form.text || form.message || "—";
  const fn = `${form.firstName || ""} ${form.lastName || ""}`.trim();
  const bits = [fn, form.phone, form.email].filter(Boolean);
  return bits.join(" · ") || "—";
}

// Compute boolean matrix from text using global `qrcode` (qrcode-generator).
function qrMatrix(text, ecc) {
  try {
    const qr = window.qrcode(0, ecc || "M");
    qr.addData(text && text.length ? text : " ");
    qr.make();
    const n = qr.getModuleCount();
    const m = [];
    for (let r = 0; r < n; r++) {
      const row = [];
      for (let c = 0; c < n; c++) row.push(qr.isDark(r, c));
      m.push(row);
    }
    return m;
  } catch (e) {
    return null;
  }
}

// Is this module part of one of the 3 finder (corner) eyes?
function inFinder(r, c, n) {
  const f = 7;
  return (r < f && c < f) || (r < f && c >= n - f) || (r >= n - f && c < f);
}

// React component: renders a styled, scannable SVG QR.
function QRPreview(props) {
  const {
    text,
    plate = "#FFFFFF",
    code = "#101114",
    size = 240,
    pad = 4, // quiet zone in modules
    rounded = true,
    showPlate = true,
    ecc = "M",
    style,
    id,
  } = props;

  const matrix = React.useMemo(() => qrMatrix(text, ecc), [text, ecc]);

  // Geometry is built ONCE per code content/shape and reused across color changes.
  // Colors are applied purely via CSS vars on the <svg> (code = currentColor,
  // plate = --qp), so tapping a swatch only updates one style attribute — no
  // rebuild/diff of the hundreds of module rects. Keeps recoloring instant.
  const geom = React.useMemo(() => {
    if (!matrix) return null;
    const n = matrix.length;
    const total = n + pad * 2;
    const dotSize = rounded ? 0.88 : 1;
    const dotOff = (1 - dotSize) / 2;
    const rects = [];
    for (let r = 0; r < n; r++) {
      for (let c = 0; c < n; c++) {
        if (!matrix[r][c]) continue;
        if (inFinder(r, c, n)) continue;
        rects.push(React.createElement("rect", {
          key: `${r}-${c}`, x: c + pad + dotOff, y: r + pad + dotOff,
          width: dotSize, height: dotSize, rx: rounded ? dotSize * 0.42 : 0,
          fill: "currentColor",
        }));
      }
    }
    const eye = (cx, cy, key) => React.createElement("g", { key },
      React.createElement("rect", { x: cx, y: cy, width: 7, height: 7, rx: rounded ? 1.8 : 0, fill: "currentColor" }),
      React.createElement("rect", { x: cx + 1, y: cy + 1, width: 5, height: 5, rx: rounded ? 1.2 : 0, fill: "var(--qp)" }),
      React.createElement("rect", { x: cx + 2, y: cy + 2, width: 3, height: 3, rx: rounded ? 0.8 : 0, fill: "currentColor" }),
    );
    const eyes = [eye(pad, pad, "tl"), eye(pad + n - 7, pad, "tr"), eye(pad, pad + n - 7, "bl")];
    const plateRect = React.createElement("rect", { key: "plate", x: 0, y: 0, width: total, height: total, rx: 2.2, fill: "var(--qp)" });
    return { total, rects, eyes, plateRect };
  }, [matrix, pad, rounded]);

  if (!geom) {
    return React.createElement("div", { style: { width: size, height: size } });
  }

  return React.createElement(
    "svg",
    {
      id,
      width: size,
      height: size,
      viewBox: `0 0 ${geom.total} ${geom.total}`,
      style: { display: "block", borderRadius: 18, color: code, "--qp": plate, ...(style || {}) },
      shapeRendering: "geometricPrecision",
      role: "img",
    },
    showPlate ? geom.plateRect : null,
    geom.rects,
    geom.eyes
  );
}

// Render the QR to a canvas at hi-res and trigger a PNG download.
function downloadQRPng(text, opts) {
  const o = opts || {};
  const plate = o.plate || "#FFFFFF";
  const code = o.code || "#101114";
  const ecc = o.ecc || "M";
  const filename = o.filename || "qrcode.png";
  const px = o.px || 1024;
  const pad = o.pad != null ? o.pad : 4;

  const matrix = qrMatrix(text, ecc);
  if (!matrix) return;
  const n = matrix.length;
  const total = n + pad * 2;
  const scale = px / total;
  const canvas = document.createElement("canvas");
  canvas.width = px;
  canvas.height = px;
  const ctx = canvas.getContext("2d");
  // plate
  ctx.fillStyle = plate;
  ctx.fillRect(0, 0, px, px);
  ctx.fillStyle = code;
  const radius = (v) => Math.max(0, v);
  function roundRect(x, y, w, h, r) {
    r = Math.min(r, w / 2, h / 2);
    ctx.beginPath();
    ctx.moveTo(x + r, y);
    ctx.arcTo(x + w, y, x + w, y + h, r);
    ctx.arcTo(x + w, y + h, x, y + h, r);
    ctx.arcTo(x, y + h, x, y, r);
    ctx.arcTo(x, y, x + w, y, r);
    ctx.closePath();
    ctx.fill();
  }
  for (let r = 0; r < n; r++) {
    for (let c = 0; c < n; c++) {
      if (!matrix[r][c]) continue;
      if (inFinder(r, c, n)) continue;
      const s = 0.88 * scale;
      const x = (c + pad + 0.06) * scale;
      const y = (r + pad + 0.06) * scale;
      roundRect(x, y, s, s, s * 0.42);
    }
  }
  // finder eyes with standard 1:1:3:1:1 proportions (scannable)
  function eye(cx, cy) {
    const x = (cx + pad) * scale, y = (cy + pad) * scale;
    ctx.fillStyle = code;
    roundRect(x, y, 7 * scale, 7 * scale, 1.8 * scale);
    ctx.fillStyle = plate;
    roundRect(x + 1 * scale, y + 1 * scale, 5 * scale, 5 * scale, 1.2 * scale);
    ctx.fillStyle = code;
    roundRect(x + 2 * scale, y + 2 * scale, 3 * scale, 3 * scale, 0.8 * scale);
  }
  eye(0, 0); eye(n - 7, 0); eye(0, n - 7);

  canvas.toBlob((blob) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    a.click();
    setTimeout(() => URL.revokeObjectURL(url), 2000);
  }, "image/png");
}

function downloadQRSvg(text, opts) {
  const o = opts || {};
  const plate = o.plate || "#FFFFFF";
  const code = o.code || "#101114";
  const pad = o.pad != null ? o.pad : 4;
  const matrix = qrMatrix(text, o.ecc || "M");
  if (!matrix) return;
  const n = matrix.length;
  const total = n + pad * 2;
  // No background: only the QR shapes, ready for 3D-print extrusion.
  let parts = "";
  for (let r = 0; r < n; r++) {
    for (let c = 0; c < n; c++) {
      if (!matrix[r][c] || inFinder(r, c, n)) continue;
      parts += `<rect x="${(c + pad + 0.06).toFixed(2)}" y="${(r + pad + 0.06).toFixed(2)}" width="0.88" height="0.88" rx="0.37" fill="${code}"/>`;
    }
  }
  // rounded-rect subpath (for even-odd ring cutouts)
  function rr(x, y, w, h, r) {
    return `M${x + r},${y} h${w - 2 * r} a${r},${r} 0 0 1 ${r},${r} v${h - 2 * r} a${r},${r} 0 0 1 -${r},${r} h-${w - 2 * r} a${r},${r} 0 0 1 -${r},-${r} v-${h - 2 * r} a${r},${r} 0 0 1 ${r},-${r} Z`;
  }
  // Finder eye = hollow ring (outer minus middle, true hole) + solid center.
  function eye(cx, cy) {
    const x = cx + pad, y = cy + pad;
    return `<path fill-rule="evenodd" d="${rr(x, y, 7, 7, 1.8)} ${rr(x + 1, y + 1, 5, 5, 1.2)}" fill="${code}"/>` +
      `<rect x="${x + 2}" y="${y + 2}" width="3" height="3" rx="0.8" fill="${code}"/>`;
  }
  parts += eye(0, 0) + eye(n - 7, 0) + eye(0, n - 7);
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${total} ${total}" width="1024" height="1024">${parts}</svg>`;
  const blob = new Blob([svg], { type: "image/svg+xml" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = o.filename || "qrcode.svg";
  a.click();
  setTimeout(() => URL.revokeObjectURL(url), 2000);
}

const QRPreviewMemo = React.memo(QRPreview);

Object.assign(window, {
  buildQRPayload, QRPreview: QRPreviewMemo, downloadQRPng, downloadQRSvg, qrContentLabel,
});
