/* global React, firebase, Icon, Photo, kDb, kAuth, PRODUCT, STORE_CONFIG */
const { useState, useEffect, useRef } = React;

// ─── KHQR generator (EMVCo + official Bakong NBC spec) ─────────────────────
// Tag 29 sub-tag 00 = account ID directly (e.g. "username@aba")
// No GUID domain string inside the QR data
function generateKHQR(accountId, merchantName, amount, billNumber, currency = "USD") {
  const crc16 = s => {
    let c = 0xFFFF;
    for (let i = 0; i < s.length; i++) {
      c ^= s.charCodeAt(i) << 8;
      for (let j = 0; j < 8; j++) {
        c = (c & 0x8000) ? ((c << 1) ^ 0x1021) & 0xFFFF : (c << 1) & 0xFFFF;
      }
    }
    return c.toString(16).toUpperCase().padStart(4, "0");
  };
  const tlv = (t, v) => `${t}${String(v.length).padStart(2, "0")}${v}`;
  const acct = tlv("00", "bakong.nbc.gov.kh") + tlv("01", accountId);
  let q = tlv("00", "01") +
          tlv("01", "12") +
          tlv("29", acct) +
          tlv("52", "5999") +
          tlv("53", currency === "KHR" ? "116" : "840") +
          tlv("54", Number(amount).toFixed(2)) +
          tlv("58", "KH") +
          tlv("59", merchantName.slice(0, 25)) +
          tlv("60", "Phnom Penh");
  if (billNumber) q += tlv("62", tlv("01", String(billNumber).slice(0, 25)));
  q += "6304";
  return q + crc16(q);
}

// ─── Bakong QR payment modal ────────────────────────────────────────────────
function BakongQRModal({ qr, md5Hash, amount, orderId, merchantName, expiresAt, onPaid, onCancel }) {
  const [qrDataUrl,   setQrDataUrl]   = useState(null);
  const [qrError,     setQrError]     = useState(null);
  const [downloadUrl, setDownloadUrl] = useState(null);
  const modalRef = useRef(null);
  const initSecs = expiresAt ? Math.max(0, Math.round((expiresAt - Date.now()) / 1000)) : 300;
  const [secsLeft, setSecsLeft] = useState(initSecs);

  useEffect(() => {
    if (!qr) return;
    if (typeof qrcode === "undefined") { setQrError("QR library not loaded"); return; }
    try {
      const gen = qrcode(0, "M");
      gen.addData(qr);
      gen.make();
      setQrDataUrl(gen.createDataURL(4, 8));
    } catch (e) {
      setQrError(String(e));
    }
  }, [qr]);

  // Build composite PNG for download (header + amount + QR + scan hint)
  useEffect(() => {
    if (!qrDataUrl) return;
    const LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="120" height="36" viewBox="12 14 42 13"><path d="M39.0751 19.3384V22.1689H36.1988C35.9038 22.1689 35.6826 21.933 35.6826 21.6609V19.3565C35.6826 19.0662 35.9223 18.8485 36.1988 18.8485H38.5404C38.8539 18.8303 39.0751 19.048 39.0751 19.3384Z" fill="white"/><path d="M52.5535 20.4817H51.1153C51.1153 18.7942 49.7141 17.4153 47.9994 17.4153C46.635 17.4153 45.4366 18.2862 45.0309 19.5563C44.9387 19.8648 44.8834 20.1732 44.8834 20.4817V24.9815H44.8466C44.0722 24.9815 43.4453 24.3646 43.4453 23.6025V20.4817H43.4637C43.4637 19.2478 43.98 18.0685 44.9019 17.2157C45.75 16.4355 46.8563 16 48.0178 16C50.5253 16 52.5535 18.014 52.5535 20.4817Z" fill="white"/><path d="M52.5715 24.9814L50.5433 24.9996L50.0455 24.5097L48.9393 23.421L47.4089 21.915H49.4371L52.5715 24.9814Z" fill="white"/><path d="M39.5549 23.5662H35.2221C34.6874 23.5662 34.2633 23.1489 34.2633 22.6227V18.3588C34.2633 17.8326 34.6874 17.4153 35.2221 17.4153H39.5549C40.0896 17.4153 40.5137 17.8326 40.5137 18.3588V22.6227L41.9518 24.038V17.379C41.9518 16.6169 41.3249 16 40.5505 16H34.2264C33.4521 16 32.8252 16.6169 32.8252 17.379V23.6025C32.8252 24.3646 33.4521 24.9815 34.2264 24.9815H40.993L39.5549 23.5662Z" fill="white"/><path d="M21.9466 24.9996H19.9185L15.6778 20.8083V24.9996H14V16H15.6778V20.0099L19.7525 16H21.7438L17.3188 20.3184L21.9466 24.9996Z" fill="white"/><path d="M29.5243 16H31.1652V24.9996H29.5243V21.0986H24.8411V24.9996H23.2002V16H24.8411V19.7559H29.5243V16Z" fill="white"/></svg>`;
    const logoUrl = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(LOGO_SVG);

    const W = 320, dpr = 2;
    const headerH = 60, bodyPad = 16, qrSize = 240, hintH = 56;
    const H = headerH + 10 + 10 + 10 + 18 + 40 + 16 + qrSize + bodyPad + hintH + bodyPad;

    const canvas = document.createElement("canvas");
    canvas.width = W * dpr; canvas.height = H * dpr;
    const ctx = canvas.getContext("2d");
    ctx.scale(dpr, dpr);

    let loaded = 0;
    const qrImg = new Image(), logoImg = new Image();

    const draw = () => {
      if (loaded < 2) return;
      const F = "-apple-system,BlinkMacSystemFont,Arial,sans-serif";

      // White background
      ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, W, H);

      // Red header (exact #E21A1A from official KHQR SVG)
      ctx.fillStyle = "#E21A1A"; ctx.fillRect(0, 0, W, headerH);
      try { ctx.drawImage(logoImg, (W - 120) / 2, (headerH - 36) / 2, 120, 36); } catch {}

      // Account info strip
      let y = headerH + 10;
      ctx.fillStyle = "#888"; ctx.font = `11px monospace`; ctx.textAlign = "center";
      ctx.fillText((merchantName || "KSHOP").toUpperCase(), W / 2, y);

      // Dotted separator
      y += 10;
      ctx.setLineDash([4, 4]);
      ctx.strokeStyle = "rgba(0,0,0,0.18)"; ctx.lineWidth = 1;
      ctx.beginPath(); ctx.moveTo(20, y); ctx.lineTo(W - 20, y); ctx.stroke();
      ctx.setLineDash([]);

      // Merchant name
      y += 18;
      ctx.fillStyle = "#aaa"; ctx.font = `10px monospace`; ctx.textAlign = "center";
      ctx.fillText(merchantName || "KSHOP", W / 2, y);

      // Amount + USD centered together
      y += 40;
      ctx.font = `bold 40px ${F}`;
      const amtStr = Number(amount).toFixed(2);
      const amtW = ctx.measureText(amtStr).width;
      ctx.font = `600 16px ${F}`;
      const usdW = ctx.measureText("USD").width;
      const rowW = amtW + 8 + usdW;
      const rx = (W - rowW) / 2;
      ctx.fillStyle = "#111"; ctx.font = `bold 40px ${F}`; ctx.textAlign = "left";
      ctx.fillText(amtStr, rx, y);
      ctx.fillStyle = "#bbb"; ctx.font = `500 14px ${F}`;
      ctx.fillText("USD", rx + amtW + 8, y - 6);

      // QR — plain, no decorations
      const qrX = (W - qrSize) / 2, qrY = y + 16;
      ctx.drawImage(qrImg, qrX, qrY, qrSize, qrSize);

      // Scan hint
      const hy = qrY + qrSize + bodyPad + 14;
      ctx.fillStyle = "#555"; ctx.font = `12px ${F}`; ctx.textAlign = "center";
      ctx.fillText("Scan with ABA, ACLEDA, Wing", W / 2, hy);
      ctx.fillStyle = "#777";
      ctx.fillText("or any Bakong-supported app", W / 2, hy + 18);

      setDownloadUrl(canvas.toDataURL("image/png"));
    };

    qrImg.onload = logoImg.onload = () => { loaded++; draw(); };
    qrImg.onerror = logoImg.onerror = () => { loaded++; draw(); };
    qrImg.src = qrDataUrl; logoImg.src = logoUrl;
  }, [qrDataUrl]);

  useEffect(() => {
    if (!qr || !md5Hash || !orderId) return;
    let alive = true;

    const check = async () => {
      if (!alive) return;
      try {
        const r = await fetch("https://checkbakongpayment-qsn4ilcqva-uc.a.run.app", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ md5: md5Hash, orderId }),
        });
        const d = await r.json();
        if (alive && d.paid) { alive = false; onPaid(); }
      } catch {}
    };

    check();
    const iv = setInterval(check, 3000);
    const to = setTimeout(() => { if (alive) { alive = false; clearInterval(iv); onCancel("timeout"); } }, 300000);
    return () => { alive = false; clearInterval(iv); clearTimeout(to); };
  }, [qr]);

  // Countdown timer
  useEffect(() => {
    const t = setInterval(() => setSecsLeft(s => s > 0 ? s - 1 : 0), 1000);
    return () => clearInterval(t);
  }, []);

  // Focus trap + Escape key
  useEffect(() => {
    const modal = modalRef.current;
    if (!modal) return;
    const focusables = modal.querySelectorAll('button:not([disabled]), [href], input:not([disabled]), [tabindex]:not([tabindex="-1"])');
    const first = focusables[0];
    const last  = focusables[focusables.length - 1];
    first?.focus();
    const onKey = (e) => {
      if (e.key === "Escape") { onCancel(); return; }
      if (e.key !== "Tab") return;
      if (e.shiftKey) {
        if (document.activeElement === first) { e.preventDefault(); last?.focus(); }
      } else {
        if (document.activeElement === last) { e.preventDefault(); first?.focus(); }
      }
    };
    document.addEventListener("keydown", onKey);
    return () => document.removeEventListener("keydown", onKey);
  }, []);

  const mins = String(Math.floor(secsLeft / 60)).padStart(1, "0");
  const secs = String(secsLeft % 60).padStart(2, "0");

  const KhqrPaths = ({ fill = "white" }) => (<>
    <path d="M39.0751 19.3384V22.1689H36.1988C35.9038 22.1689 35.6826 21.933 35.6826 21.6609V19.3565C35.6826 19.0662 35.9223 18.8485 36.1988 18.8485H38.5404C38.8539 18.8303 39.0751 19.048 39.0751 19.3384Z" fill={fill}/>
    <path d="M52.5535 20.4817H51.1153C51.1153 18.7942 49.7141 17.4153 47.9994 17.4153C46.635 17.4153 45.4366 18.2862 45.0309 19.5563C44.9387 19.8648 44.8834 20.1732 44.8834 20.4817V24.9815H44.8466C44.0722 24.9815 43.4453 24.3646 43.4453 23.6025V20.4817H43.4637C43.4637 19.2478 43.98 18.0685 44.9019 17.2157C45.75 16.4355 46.8563 16 48.0178 16C50.5253 16 52.5535 18.014 52.5535 20.4817Z" fill={fill}/>
    <path d="M52.5715 24.9814L50.5433 24.9996L50.0455 24.5097L48.9393 23.421L47.4089 21.915H49.4371L52.5715 24.9814Z" fill={fill}/>
    <path d="M39.5549 23.5662H35.2221C34.6874 23.5662 34.2633 23.1489 34.2633 22.6227V18.3588C34.2633 17.8326 34.6874 17.4153 35.2221 17.4153H39.5549C40.0896 17.4153 40.5137 17.8326 40.5137 18.3588V22.6227L41.9518 24.038V17.379C41.9518 16.6169 41.3249 16 40.5505 16H34.2264C33.4521 16 32.8252 16.6169 32.8252 17.379V23.6025C32.8252 24.3646 33.4521 24.9815 34.2264 24.9815H40.993L39.5549 23.5662Z" fill={fill}/>
    <path d="M21.9466 24.9996H19.9185L15.6778 20.8083V24.9996H14V16H15.6778V20.0099L19.7525 16H21.7438L17.3188 20.3184L21.9466 24.9996Z" fill={fill}/>
    <path d="M29.5243 16H31.1652V24.9996H29.5243V21.0986H24.8411V24.9996H23.2002V16H24.8411V19.7559H29.5243V16Z" fill={fill}/>
  </>);

  return (
    <div style={{
      position: "fixed", inset: 0, zIndex: 999, padding: "16px",
      background: "rgba(0,0,0,0.88)", backdropFilter: "blur(6px)",
      display: "flex", alignItems: "center", justifyContent: "center"
    }}>
      <div
        ref={modalRef}
        role="dialog"
        aria-modal="true"
        aria-label="Bakong KHQR Payment"
        style={{
          background: "#fff", borderRadius: 16, overflow: "hidden",
          maxWidth: 320, width: "100%", textAlign: "center",
          boxShadow: "0 28px 72px rgba(0,0,0,0.55)"
        }}
      >
        {/* ── KHQR RED HEADER ── */}
        <div style={{
          background: "#E21A1A", height: 80, paddingTop: 8,
          display: "flex", alignItems: "flex-start", justifyContent: "center",
          clipPath: "polygon(0 0, 100% 0, 100% 100%, 91.8% 67.9%, 0 67.9%)"
        }}>
          <svg width="130" height="38" viewBox="12 14 42 13" fill="none" xmlns="http://www.w3.org/2000/svg">
            <KhqrPaths />
          </svg>
        </div>

        {/* ── MERCHANT NAME + AMOUNT ── */}
        <div style={{ padding: "6px 24px 10px", textAlign: "center" }}>
          <div style={{
            fontSize: 13, color: "#222",
            letterSpacing: "0.08em", textTransform: "uppercase",
            marginBottom: 4, fontWeight: 600
          }}>
            {merchantName || "KSHOP"}
          </div>
          <div style={{ display: "flex", alignItems: "baseline", justifyContent: "center", gap: 5 }}>
            <span style={{
              fontSize: 40, fontWeight: 700, color: "#0d0d0d",
              letterSpacing: "-0.02em", lineHeight: 1, fontVariantNumeric: "tabular-nums"
            }}>
              {Number(amount).toFixed(2)}
            </span>
            <span style={{ fontSize: 12, fontWeight: 500, color: "#999", paddingBottom: 2 }}>USD</span>
          </div>
        </div>

        {/* ── DOTTED SEPARATOR — SVG y=16.364, after amount, before QR ── */}
        <div style={{ margin: "4px 20px 12px", borderTop: "1.5px dashed rgba(0,0,0,0.18)" }} />

        {/* ── QR CODE — $ center overlay, matches SVG 72.2% card width ── */}
        <div style={{ padding: "0 24px 20px", display: "flex", justifyContent: "center" }}>
          {qrDataUrl
            ? <div style={{ position: "relative", width: 196, height: 196 }}>
                <img src={qrDataUrl} alt="KHQR payment code" style={{ width: 196, height: 196, display: "block" }} />
                <div style={{
                  position: "absolute", top: "50%", left: "50%",
                  transform: "translate(-50%, -50%)",
                  width: 40, height: 40, borderRadius: "50%",
                  background: "#111", border: "3px solid #fff",
                  display: "flex", alignItems: "center", justifyContent: "center"
                }}>
                  <span style={{
                    fontSize: 20, fontWeight: 700, color: "#fff",
                    lineHeight: 1, fontFamily: "-apple-system,BlinkMacSystemFont,Arial,sans-serif"
                  }}>$</span>
                </div>
              </div>
            : qrError
              ? <div style={{ width: 196, height: 196, display: "grid", placeItems: "center" }}>
                  <span style={{ fontSize: 11, color: "#e53935", fontFamily: "monospace", padding: 12, textAlign: "center" }}>{qrError}</span>
                </div>
              : <div style={{ width: 196, height: 196, background: "#f8f8f8", display: "grid", placeItems: "center" }}>
                  <span style={{ fontSize: 11, color: "#ccc" }}>Generating…</span>
                </div>
          }
        </div>

        {/* ── DIVIDER ── */}
        <div style={{ height: 1, background: "#f0f0f0", margin: "0 20px" }} />

        {/* Download button */}
        {downloadUrl && (
          <div style={{ padding: "12px 24px 0" }}>
            <a href={downloadUrl} download="khqr-payment.png" style={{
              display: "flex", alignItems: "center", justifyContent: "center", gap: 8,
              padding: "10px 20px", borderRadius: 8, textDecoration: "none",
              background: "#f5f5f5", border: "1px solid #e0e0e0",
              color: "#333", fontSize: 13, fontFamily: "inherit", cursor: "pointer"
            }}>
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
              </svg>
              <span className="km-sans" style={{ fontSize: 13 }}>ទាញយក QR</span>
              <span style={{ color: "#888" }}>· Download QR</span>
            </a>
          </div>
        )}

        {/* Expiry + status */}
        <div style={{ padding: "14px 24px 20px" }}>
          <div style={{ fontSize: 13, color: "#555", marginBottom: 16 }}>
            Expires in: <strong style={{ color: secsLeft < 60 ? "#e53935" : "#222" }}>{mins}:{secs}</strong>
          </div>
          <div style={{ fontSize: 12, color: "#555", marginBottom: 16, lineHeight: 1.5 }}>
            Scan with <strong style={{ color: "#111" }}>ABA, ACLEDA, Wing</strong><br/>or any Bakong-supported app
          </div>
          <button type="button" onClick={() => onCancel()} style={{
            background: "none", border: "1px solid #e0e0e0", borderRadius: 8,
            padding: "9px 32px", cursor: "pointer", fontSize: 13, color: "#888", fontFamily: "inherit",
            width: "100%"
          }}>Cancel</button>
        </div>
      </div>
    </div>
  );
}


async function notifyOrderCF(orderId) {
  try {
    const token = await kAuth.currentUser.getIdToken();
    fetch("https://notifyorder-qsn4ilcqva-uc.a.run.app", {
      method: "POST",
      headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
      body: JSON.stringify({ orderId }),
    });
  } catch {} // Silent — order is already saved
}

// ─── Field with inline error ───────────────────────────────────────────────

function CField({ label, type = "text", value, onChange, placeholder, required, error }) {
  const fieldId = label.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase().slice(0, 20);
  const errId   = fieldId + "-err";
  return (
    <div className="col gap-6">
      <label htmlFor={fieldId} style={{
        fontSize: "var(--text-2xs)", fontFamily: "var(--font-mono)",
        letterSpacing: "0.08em", textTransform: "uppercase",
        color: error ? "var(--accent)" : "var(--fg-muted)"
      }}>
        {label}{required && <span style={{ color: "var(--accent)" }}> *</span>}
      </label>
      <input
        id={fieldId}
        type={type}
        value={value}
        onChange={onChange}
        placeholder={placeholder}
        aria-describedby={error ? errId : undefined}
        aria-invalid={!!error}
        style={{
          width: "100%", padding: "12px 14px",
          background: "var(--bg-2)",
          border: "1px solid " + (error ? "var(--accent)" : "var(--line-strong)"),
          borderRadius: "var(--radius)", font: "inherit",
          fontSize: "var(--text-base)", color: "var(--fg)",
          outline: "none", boxSizing: "border-box",
          transition: "border-color 140ms ease"
        }}
        onFocus={e => { e.target.style.borderColor = "var(--fg)"; }}
        onBlur={e  => { e.target.style.borderColor = error ? "var(--accent)" : "var(--line-strong)"; }}
      />
      {error && (
        <span id={errId} role="alert" style={{ fontSize: "var(--text-2xs)", color: "var(--accent)", fontFamily: "var(--font-mono)" }}>
          {error}
        </span>
      )}
    </div>
  );
}

// ─── Checkout page ─────────────────────────────────────────────────────────

function CheckoutPage({ items, user, onBack, onSuccess, setRoute }) {
  const [form,        setForm]        = useState({ name: "", phone: "", address: "", notes: "" });
  const [payment,     setPayment]     = useState("cod");
  const [loadingData, setLoadingData] = useState(true);
  const [submitting,  setSubmitting]  = useState(false);
  const [submitted,   setSubmitted]   = useState(false);
  const [orderId,     setOrderId]     = useState("");
  const [error,       setError]       = useState("");
  const [fieldErrors, setFieldErrors] = useState({});
  const [promoCode,   setPromoCode]   = useState("");
  const [promo,       setPromo]       = useState(null);
  const [promoErr,    setPromoErr]    = useState("");
  const [promoLoading,setPromoLoading]= useState(false);
  const [bakongPending,setBakongPending]= useState(null);

  // Compute totals (same logic as cart drawer)
  const lines = items.map(it => {
    const s = PRODUCT.sizes.find(x => x.id === it.sizeId);
    return { ...it, s, lineTotal: (s?.price || 0) * it.qty };
  });
  const subtotal = lines.reduce((a, l) => a + l.lineTotal, 0);
  const { shippingFreeThreshold = 75, shippingRate = 9 } = window.STORE_CONFIG || {};
  const shipping  = subtotal >= shippingFreeThreshold ? 0 : shippingRate;
  const discount  = promo
    ? promo.type === "percent"
      ? Math.round(subtotal * (promo.value / 100) * 100) / 100
      : Math.min(Number(promo.value), subtotal)
    : 0;
  const total = subtotal + shipping - discount;

  // Pre-fill from Firestore profile
  useEffect(() => {
    if (!user) { setLoadingData(false); return; }
    kDb.collection("users").doc(user.uid).get()
      .then(doc => {
        if (doc.exists) {
          const d = doc.data();
          setForm(prev => ({
            ...prev,
            name:    d.name    || user.displayName  || "",
            phone:   d.phone   || user.phoneNumber  || "",
            address: d.address || "",
          }));
        }
        setLoadingData(false);
      })
      .catch(() => setLoadingData(false));
  }, [user]);

  const set = k => e => setForm(prev => ({ ...prev, [k]: e.target.value }));

  const validate = () => {
    const errs = {};
    if (!form.name.trim())    errs.name    = "ឈ្មោះត្រូវការ · Required";
    if (!form.phone.trim())   errs.phone   = "លេខទូរស័ព្ទត្រូវការ · Required";
    if (!form.address.trim()) errs.address = "អាសយដ្ឋានត្រូវការ · Required";
    setFieldErrors(errs);
    return Object.keys(errs).length === 0;
  };

  const applyPromo = async () => {
    const code = promoCode.trim().toUpperCase();
    if (!code) return;
    setPromoLoading(true); setPromoErr(""); setPromo(null);
    try {
      const doc = await kDb.collection("promos").doc(code).get();
      if (!doc.exists || !doc.data().active) {
        setPromoErr("Invalid or expired promo code.");
        return;
      }
      const p = doc.data();
      if (subtotal < (p.minOrder || 0)) {
        setPromoErr(`Minimum order $${p.minOrder} required for this code.`);
        return;
      }
      setPromo(p);
    } catch {
      setPromoErr("Could not validate code. Please try again.");
    } finally {
      setPromoLoading(false);
    }
  };

  const placeOrder = async () => {
    if (!validate()) return;
    setError(""); setSubmitting(true);
    try {
      const orderItems = lines.map(l => ({
        productId: l.productId,
        sizeId:    l.sizeId,
        label:     l.s?.label   || l.sizeId,
        labelKh:   l.s?.labelKh || "",
        qty:       l.qty,
        price:     l.s?.price   || 0,
      }));
      const ref = await kDb.collection("orders").add({
        uid:           user.uid,
        name:          form.name.trim(),
        phone:         form.phone.trim(),
        address:       form.address.trim(),
        notes:         form.notes.trim(),
        items:         orderItems,
        subtotal,
        shipping,
        discount,
        promoCode:     promo?.code || null,
        total,
        paymentMethod: payment,
        status:        payment === "aba" ? "pending_payment" : "confirmed",
        createdAt:     firebase.firestore.FieldValue.serverTimestamp(),
      });
      if (promo?.code) {
        kDb.collection("promos").doc(promo.code).update({
          uses: firebase.firestore.FieldValue.increment(1),
        }).catch(() => {});
      }
      if (payment === "aba") {
        const khqrResp = await fetch("https://createkhqr-qsn4ilcqva-uc.a.run.app", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ orderId: ref.id, billNumber: "KS-" + ref.id.slice(0, 8).toUpperCase() }),
        });
        const khqr = await khqrResp.json();
        if (!khqr.qr) throw new Error(khqr.error || "Failed to generate payment QR");
        setBakongPending({ orderId: ref.id, qr: khqr.qr, md5: khqr.md5, amount: total, merchantName: khqr.merchantName || "KSHOP", expiresAt: khqr.expiresAt });
      } else {
        setOrderId(ref.id.slice(0, 8).toUpperCase());
        setSubmitted(true);
        onSuccess();
        notifyOrderCF(ref.id);
      }
    } catch (err) {
      setError("មានបញ្ហា · Could not place order. Please try again.");
    } finally {
      setSubmitting(false);
    }
  };

  // ── Not signed in ──────────────────────────────────────────────────────
  if (!user && !loadingData) {
    return (
      <main style={{ padding: "80px 0 96px" }}>
        <div className="wrap" style={{ maxWidth: 520 }}>
          <div className="col gap-20 items-center" style={{ textAlign: "center" }}>
            <div className="col gap-8">
              <span className="eyebrow">— <span className="km-sans">ទូទាត់ប្រាក់</span> · Checkout</span>
              <h1 className="display-lg km">ចូលគណនីជាមុន។</h1>
              <span className="serif text-muted" style={{ fontSize: "var(--text-2xl)" }}>
                <em>Sign in to place your order.</em>
              </span>
            </div>
            <div className="row gap-12">
              <button type="button" className="btn btn-primary btn-lg" onClick={() => setRoute("account")}>
                <span className="km-sans">ចូលគណនី</span> · Sign in <Icon name="arrow-right" size={16} />
              </button>
              <button type="button" className="btn btn-lg" onClick={onBack}>
                <span className="km-sans">ត្រឡប់</span> · Back to cart
              </button>
            </div>
          </div>
        </div>
      </main>
    );
  }

  // ── Success ────────────────────────────────────────────────────────────
  if (submitted) {
    return (
      <main style={{ padding: "80px 0 96px" }}>
        <div className="wrap" style={{ maxWidth: 520 }}>
          <div className="col gap-24 items-center" style={{ textAlign: "center" }}>
            <div style={{
              width: 72, height: 72, borderRadius: "50%",
              background: "var(--primary)", color: "var(--primary-fg)",
              display: "grid", placeItems: "center"
            }}>
              <Icon name="check" size={32} stroke={2.5} />
            </div>
            <div className="col gap-8">
              <span className="eyebrow">— <span className="km-sans">ការបញ្ជាទិញបានជោគជ័យ</span> · Order confirmed</span>
              <h1 className="display-lg km">អរគុណ!</h1>
              <span className="serif text-muted" style={{ fontSize: "var(--text-2xl)" }}>
                <em>Thank you for your order.</em>
              </span>
            </div>
            <div style={{
              background: "var(--bg-2)", border: "1px solid var(--line)",
              borderRadius: 12, padding: "20px 28px", width: "100%", textAlign: "left"
            }}>
              <div className="col gap-10">
                <div className="col gap-2">
                  <span className="mono text-muted" style={{ fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase" }}>
                    <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>លេខការបញ្ជាទិញ</span> · Order ID
                  </span>
                  <span className="mono" style={{ fontSize: "var(--text-base)", letterSpacing: "0.12em" }}>KS-{orderId}</span>
                </div>
                <div style={{ height: 1, background: "var(--line)" }} />
                <span className="km-sans text-muted" style={{ fontSize: "var(--text-xs)" }}>
                  យើងនឹងទូរស័ព្ទទៅ <strong style={{ color: "var(--fg)" }}>{form.phone}</strong> ដើម្បីបញ្ជាក់ ហើយរៀបចំដឹក។
                </span>
                <span className="text-muted" style={{ fontSize: "var(--text-xs)" }}>
                  We'll call <strong style={{ color: "var(--fg)" }}>{form.phone}</strong> to confirm and arrange delivery.
                </span>
              </div>
            </div>
            <div className="row gap-12">
              <button type="button" className="btn btn-primary" onClick={() => setRoute("account")}>
                <span className="km-sans">មើលការបញ្ជាទិញ</span> · View orders
              </button>
              <button type="button" className="btn" onClick={() => setRoute("home")}>
                <span className="km-sans">ទំព័រដើម</span> · Home
              </button>
            </div>
          </div>
        </div>
      </main>
    );
  }

  // ── Loading ────────────────────────────────────────────────────────────
  if (loadingData) {
    return (
      <main style={{ padding: "120px 0", display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div role="status" aria-label="Loading checkout…" style={{
          width: 40, height: 40, borderRadius: "50%",
          border: "2px solid var(--line-strong)", borderTopColor: "var(--accent)",
          animation: "ks-spin 0.8s linear infinite"
        }} />
      </main>
    );
  }

  // ── Main form ──────────────────────────────────────────────────────────
  return (
    <main style={{ padding: "48px 0 96px" }}>
      <div className="wrap">

        {/* Header */}
        <div className="col gap-6" style={{ marginBottom: 48 }}>
          <button
            type="button"
            onClick={onBack}
            style={{
              background: "none", border: 0, cursor: "pointer", padding: 0, marginBottom: 4,
              display: "inline-flex", alignItems: "center", gap: 6,
              color: "var(--fg-muted)", fontFamily: "var(--font-mono)",
              fontSize: "var(--text-2xs)", letterSpacing: "0.08em"
            }}
          >
            ← <span className="km-sans" style={{ letterSpacing: 0 }}>ត្រឡប់ទៅកន្ត្រក</span> · Back to cart
          </button>
          <span className="eyebrow">— <span className="km-sans">ទូទាត់ប្រាក់</span> · Checkout</span>
          <h1 className="display-lg km">ព័ត៌មានដឹកជញ្ជូន។</h1>
          <span className="serif text-muted" style={{ fontSize: "var(--text-2xl)" }}>
            <em>Delivery details.</em>
          </span>
        </div>

        <div className="checkout-grid">

          {/* ── LEFT: Form ── */}
          <div className="col gap-32">

            {/* Contact */}
            <div className="col gap-16">
              <span className="mono" style={{
                fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase",
                borderBottom: "1px solid var(--line)", paddingBottom: 10
              }}>
                <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>ព័ត៌មានទំនាក់ទំនង</span> · Contact
              </span>
              <CField label="ឈ្មោះ · Full name"         value={form.name}    onChange={set("name")}    placeholder="Sophea Chan"         required error={fieldErrors.name} />
              <CField label="លេខទូរស័ព្ទ · Phone"        type="tel" value={form.phone} onChange={set("phone")} placeholder="+855 92 555 014"  required error={fieldErrors.phone} />
            </div>

            {/* Address */}
            <div className="col gap-16">
              <span className="mono" style={{
                fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase",
                borderBottom: "1px solid var(--line)", paddingBottom: 10
              }}>
                <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>អាសយដ្ឋានដឹក</span> · Delivery address
              </span>
              <CField label="អាសយដ្ឋាន · Street address" value={form.address} onChange={set("address")} placeholder="St. 271, Toul Tompoung, Phnom Penh" required error={fieldErrors.address} />
              <CField label="កំណត់ចំណាំ · Notes (optional)" value={form.notes} onChange={set("notes")} placeholder="Gate code, landmark, call before arriving…" />
            </div>

            {/* Promo code */}
            <div className="col gap-12">
              <span className="mono" style={{
                fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase",
                borderBottom: "1px solid var(--line)", paddingBottom: 10
              }}>
                <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>កូដបញ្ចុះតម្លៃ</span> · Promo code
              </span>
              <div className="row gap-8">
                <input
                  type="text"
                  value={promoCode}
                  onChange={e => { setPromoCode(e.target.value.toUpperCase()); setPromo(null); setPromoErr(""); }}
                  aria-label="Promo code · កូដបញ្ចុះតម្លៃ"
                  placeholder="ENTER CODE"
                  style={{
                    flex: 1, padding: "12px 14px",
                    background: "var(--bg-2)", border: "1px solid var(--line-strong)",
                    borderRadius: "var(--radius)", font: "inherit",
                    fontSize: "var(--text-sm)", color: "var(--fg)",
                    outline: "none", letterSpacing: "0.08em",
                    fontFamily: "var(--font-mono)", textTransform: "uppercase"
                  }}
                />
                <button
                  type="button"
                  className="btn"
                  onClick={applyPromo}
                  disabled={promoLoading || !promoCode.trim()}
                >
                  {promoLoading ? "…" : <><span className="km-sans">ប្រើ</span> · Apply</>}
                </button>
              </div>
              {promoErr && (
                <span style={{ fontSize: "var(--text-xs)", color: "var(--accent)", fontFamily: "var(--font-mono)" }}>
                  {promoErr}
                </span>
              )}
              {promo && (
                <div className="row gap-8 items-center" style={{ color: "var(--primary)" }}>
                  <Icon name="check" size={13} />
                  <span className="mono" style={{ fontSize: "var(--text-xs)", letterSpacing: "0.06em" }}>
                    {promo.code} — {promo.type === "percent" ? `${promo.value}% off` : `$${promo.value} off`} applied
                  </span>
                </div>
              )}
            </div>

            {/* Payment */}
            <div className="col gap-16">
              <span className="mono" style={{
                fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase",
                borderBottom: "1px solid var(--line)", paddingBottom: 10
              }}>
                <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>វិធីទូទាត់</span> · Payment method
              </span>
              <div role="radiogroup" aria-label="Payment method" className="col gap-8">
                {[
                  { id: "cod", khLabel: "សាច់ប្រាក់នៅពេលដឹក", enLabel: "Cash on delivery",  sub: "Pay when your order arrives · COD", available: true  },
                  { id: "aba", khLabel: "បង់តាម KHQR · Bakong", enLabel: "Bakong KHQR",         sub: "Scan with ABA, ACLEDA, Wing or any Bakong app", available: true  },
                ].map(opt => (
                  <button
                    key={opt.id}
                    type="button"
                    role="radio"
                    aria-checked={payment === opt.id}
                    onClick={() => opt.available && setPayment(opt.id)}
                    style={{
                      display: "flex", alignItems: "center", gap: 14,
                      padding: "14px 16px", borderRadius: "var(--radius)", textAlign: "left",
                      border: "1.5px solid " + (payment === opt.id ? "var(--accent)" : "var(--line-strong)"),
                      background: payment === opt.id ? "color-mix(in oklab, var(--accent) 8%, var(--bg))" : "var(--bg-2)",
                      cursor: opt.available ? "pointer" : "default",
                      opacity: opt.available ? 1 : 0.6,
                      transition: "border-color 120ms, background 120ms"
                    }}
                  >
                    {/* Radio dot */}
                    <div style={{
                      width: 18, height: 18, borderRadius: "50%", flexShrink: 0,
                      border: "2px solid " + (payment === opt.id ? "var(--accent)" : "var(--line-strong)"),
                      background: payment === opt.id ? "var(--accent)" : "transparent",
                      display: "grid", placeItems: "center", transition: "all 120ms"
                    }}>
                      {payment === opt.id && <div style={{ width: 6, height: 6, borderRadius: "50%", background: "#fff" }} />}
                    </div>
                    <div className="col gap-2">
                      <span className="km-sans" style={{ fontSize: "var(--text-xs)", color: "var(--fg)" }}>{opt.khLabel}</span>
                      <span style={{ fontFamily: "var(--font-mono)", fontSize: "var(--text-2xs)", letterSpacing: "0.06em", color: "var(--fg)" }}>{opt.enLabel}</span>
                      <span style={{ fontSize: "var(--text-2xs)", color: "var(--fg-muted)" }}>{opt.sub}</span>
                    </div>
                  </button>
                ))}

                {error && (
                  <div style={{ padding: "10px 14px", background: "color-mix(in oklab, var(--accent) 12%, transparent)", borderRadius: "var(--radius)", border: "1px solid var(--accent)" }}>
                    <span className="km-sans" style={{ color: "var(--accent)", fontSize: "var(--text-xs)" }}>{error}</span>
                  </div>
                )}

                <button type="button" className="btn btn-primary btn-lg" style={{ width: "100%" }} onClick={placeOrder} disabled={submitting}>
              {submitting
                ? <span className="km-sans">កំពុងបញ្ជូន…</span>
                : <><span className="km-sans">ធ្វើការបញ្ជាទិញ</span> · Place order — ${total.toFixed(2)} <Icon name="arrow-right" size={16} /></>
              }
            </button>
              </div>
            </div>
            <div className="row gap-8 items-center justify-center" style={{ color: "var(--fg-muted)" }}>
              <Icon name="shield" size={13} />
              <span className="mono" style={{ fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase" }}>
                <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>ការបញ្ជាទិញមានសុវត្ថិភាព · ធានា ៣០ ថ្ងៃ</span> · Secure order · 30-day guarantee
              </span>
            </div>
          </div>

          {/* ── RIGHT: Order summary ── */}
          <div style={{ position: "sticky", top: 96 }}>
            <div style={{ border: "1px solid var(--line)", borderRadius: 12, overflow: "hidden" }}>

              {/* Summary header */}
              <div style={{ padding: "14px 20px", borderBottom: "1px solid var(--line)", background: "var(--bg-2)" }}>
                <span className="mono" style={{ fontSize: "var(--text-2xs)", letterSpacing: "0.1em", textTransform: "uppercase" }}>
                  <span className="km-sans" style={{ textTransform: "none", letterSpacing: 0 }}>សង្ខេបការបញ្ជាទិញ</span> · Order summary
                </span>
              </div>

              {/* Line items */}
              {lines.map((l, i) => (
                <div key={i} style={{
                  display: "grid", gridTemplateColumns: "56px 1fr auto",
                  gap: 12, padding: "14px 20px", alignItems: "center",
                  borderBottom: i < lines.length - 1 ? "1px solid var(--line)" : "none"
                }}>
                  <Photo src="uploads/termite-detail-1.jpeg" caption="" aspect="1/1" bg="#f5f1ea" />
                  <div className="col gap-2">
                    <span className="km-sans" style={{ fontSize: "var(--text-xs)" }}>{l.s?.labelKh}</span>
                    <span className="mono text-muted" style={{ fontSize: "var(--text-2xs)", letterSpacing: "0.06em" }}>
                      {l.s?.label} × {l.qty}
                    </span>
                  </div>
                  <span className="serif" style={{ fontSize: "var(--text-lg)" }}>${l.lineTotal}</span>
                </div>
              ))}

              {/* Totals */}
              <div className="col gap-8" style={{ padding: "16px 20px", borderTop: "1px solid var(--line-strong)", background: "var(--bg-2)" }}>
                <div className="row justify-between">
                  <span className="text-muted" style={{ fontSize: "var(--text-xs)" }}><span className="km-sans">តម្លៃរង</span> · Subtotal</span>
                  <span style={{ fontSize: "var(--text-xs)" }}>${subtotal.toFixed(2)}</span>
                </div>
                <div className="row justify-between">
                  <span className="text-muted" style={{ fontSize: "var(--text-xs)" }}><span className="km-sans">ថ្លៃដឹក</span> · Shipping</span>
                  <span style={{ fontSize: "var(--text-xs)", color: shipping === 0 ? "var(--accent)" : "inherit" }}>
                    {shipping === 0 ? <><span className="km-sans">ឥតគិតថ្លៃ</span> · Free</> : `$${shipping.toFixed(2)}`}
                  </span>
                </div>
                {discount > 0 && (
                  <div className="row justify-between">
                    <span className="text-muted" style={{ fontSize: "var(--text-xs)" }}>
                      <span className="km-sans">បញ្ចុះតម្លៃ</span> · Discount
                      <span className="mono" style={{ marginLeft: 4, fontSize: "var(--text-2xs)", letterSpacing: "0.06em" }}>({promo.code})</span>
                    </span>
                    <span style={{ fontSize: "var(--text-xs)", color: "var(--primary)" }}>−${discount.toFixed(2)}</span>
                  </div>
                )}
                <div style={{ height: 1, background: "var(--line-strong)", margin: "2px 0" }} />
                <div className="row justify-between items-center">
                  <span className="serif" style={{ fontSize: "var(--text-xl)" }}>
                    <span className="km" style={{ fontSize: "var(--text-lg)" }}>សរុប</span> · Total
                  </span>
                  <span className="serif" style={{ fontSize: "var(--text-2xl)" }}>${total.toFixed(2)}</span>
                </div>
                {shipping === 0 && (
                  <div className="row gap-6 items-center" style={{ color: "var(--accent)" }}>
                    <Icon name="check" size={12} />
                    <span className="mono" style={{ fontSize: "var(--text-2xs)", letterSpacing: "0.06em" }}>
                      <span className="km-sans" style={{ letterSpacing: 0 }}>ដឹកឥតគិតថ្លៃ</span> · FREE SHIPPING
                    </span>
                  </div>
                )}
              </div>

            </div>
          </div>

        </div>
      </div>

      {bakongPending && (
        <BakongQRModal
          qr={bakongPending.qr}
          md5Hash={bakongPending.md5}
          expiresAt={bakongPending.expiresAt}
          amount={bakongPending.amount}
          orderId={bakongPending.orderId}
          merchantName={bakongPending.merchantName}
          onPaid={() => {
            const { orderId } = bakongPending;
            // Order confirmed + notification fully handled server-side by checkBakongPayment CF
            setOrderId(orderId.slice(0, 8).toUpperCase());
            setBakongPending(null);
            setSubmitted(true);
            onSuccess();
          }}
          onCancel={(reason) => {
            kDb.collection("orders").doc(bakongPending.orderId)
              .update({ status: "cancelled" }).catch(() => {});
            setBakongPending(null);
            if (reason === "timeout") setError("Payment timed out. Try again or choose Cash on Delivery.");
          }}
        />
      )}
    </main>
  );
}

Object.assign(window, { CheckoutPage });
