// Catálogo · Imcopartes (Fase 1 — Cotizador rápido + descarga PDF)

const { useState, useEffect, useMemo } = React;

/* ===== Page head ===== */
function CatalogHead() {
  return (
    <header className="page-head page-head--catalog">
      <div className="page-head__diagonal"></div>
      <div className="page-head__inner">
        <div>
          <div className="page-head__eyebrow">Catálogo mayorista · Colombia</div>
          <h1 className="page-head__title">
            Descarga el catálogo.<br />Pide tu cotización <em>por WhatsApp</em>.
          </h1>
          <p className="page-head__lead">
            Descarga la lista vigente de productos con todas las referencias y compatibilidades.
            Cuando estés listo, envía los SKUs y cantidades por WhatsApp y un asesor te responde
            con precios mayoristas y tiempos de despacho.
          </p>
        </div>
        <div className="page-head__side">
          <h4>Lista de productos</h4>
          <p>Listado oficial de referencias con descripción y compatibilidad.</p>
          <a
            className="btn btn-on-dark"
            href="assets/catalogo/Lista-de-Productos-Imcopartes-2026.pdf"
            download="Lista-de-Productos-Imcopartes-2026.pdf"
            target="_blank"
            rel="noopener noreferrer"
          >
            <i data-lucide="file-text" style={{ width: 16, height: 16 }}></i>
            Descargar PDF
          </a>
          <a
            className="btn btn-on-dark-outline"
            href={waLink("Hola, soy distribuidor y quiero acceso al catálogo mayorista.")}
            target="_blank"
            rel="noopener noreferrer"
          >
            <i data-lucide="message-circle" style={{ width: 16, height: 16 }}></i>
            Solicitar catálogo mayorista
          </a>
        </div>
      </div>
    </header>
  );
}

/* ===== Quote builder ===== */
const MINIMO_PEDIDO = 1_000_000; // monto mínimo en COP para habilitar el envío
const REDONDEO_TOTAL = 50_000;   // redondeo del total mostrado al cliente

function fmtCOP(n) {
  return "$" + n.toLocaleString("es-CO");
}

// Title Case en español (deja en minúsculas las palabras vacías comunes)
function toTitleCase(s) {
  if (!s) return "";
  const small = new Set(["de","del","la","el","los","las","y","con","sin","en","para","a","o","u","por"]);
  const txt = String(s).toLowerCase();
  return txt.replace(/[\p{L}\p{N}]+/gu, (w, idx) => {
    if (idx > 0 && small.has(w)) return w;
    return w.charAt(0).toUpperCase() + w.slice(1);
  });
}

// Genera un código corto único para cada cotización (informativo, no comprometido)
function makeQuoteRef() {
  const d = new Date();
  const yy = String(d.getFullYear()).slice(2);
  const mm = String(d.getMonth() + 1).padStart(2, "0");
  const dd = String(d.getDate()).padStart(2, "0");
  const rand = Math.random().toString(36).slice(2, 6).toUpperCase();
  return `IMC-${yy}${mm}${dd}-${rand}`;
}

/* Iconos SVG inline (Lucide-shape) — usados en zonas con condicional, para evitar
   conflictos entre la mutación DOM de lucide y los re-renders de React. */
function SvgIcon({ d, size = 18, strokeWidth = 2, ...rest }) {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round"
      aria-hidden="true" {...rest}>
      <g dangerouslySetInnerHTML={{ __html: d }} />
    </svg>
  );
}
const ICON_PATHS = {
  alertCircle:    `<circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line>`,
  packagePlus:    `<path d="M16 16h6"></path><path d="M19 13v6"></path><path d="M21 10V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l2-1.14"></path><path d="M16.5 9.4 7.55 4.24"></path><polyline points="3.29 7 12 12 20.71 7"></polyline><line x1="12" y1="22" x2="12" y2="12"></line>`,
  checkCircle:    `<path d="M21.801 10A10 10 0 1 1 17 3.335"></path><path d="m9 11 3 3L22 4"></path>`,
  alertTriangle:  `<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line>`,
  loader:         `<line x1="12" y1="2" x2="12" y2="6"></line><line x1="12" y1="18" x2="12" y2="22"></line><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line><line x1="2" y1="12" x2="6" y2="12"></line><line x1="18" y1="12" x2="22" y2="12"></line><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line>`,
  send:           `<path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"></path><path d="m21.854 2.147-10.94 10.939"></path>`,
  lock:           `<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path>`,
  x:              `<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>`,
};

function QuoteBuilder() {
  /* ---- Carga del catálogo de precios (silencioso) ---- */
  const [catalog, setCatalog] = useState(null);
  const [catalogStatus, setCatalogStatus] = useState("loading"); // loading | ready | error
  const [logoDataUrl, setLogoDataUrl] = useState(null);

  useEffect(() => {
    let cancelled = false;
    fetch("assets/data/price-list.json")
      .then((r) => {
        if (!r.ok) throw new Error("No se pudo cargar el catálogo de precios.");
        return r.json();
      })
      .then((data) => {
        if (cancelled) return;
        const map = {};
        data.forEach((it) => { map[String(it.sku).toUpperCase()] = it; });
        setCatalog(map);
        setCatalogStatus("ready");
      })
      .catch((e) => {
        console.error(e);
        if (!cancelled) setCatalogStatus("error");
      });
    return () => { cancelled = true; };
  }, []);

  // Carga del logo (SVG → PNG dataURL para embebido en PDF)
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const r = await fetch("assets/logos/imcopartes-blanco.svg");
        let svg = await r.text();
        // El SVG usa class="cls-1" sin definir color (queda en negro). Forzamos fill blanco.
        svg = svg.replace("<defs></defs>", `<defs><style>.cls-1 { fill: #ffffff; }</style></defs>`);
        if (!svg.includes(".cls-1 { fill")) {
          // Si el SVG no tenía <defs></defs>, inyectamos un <style> al inicio
          svg = svg.replace("<svg", `<svg`).replace(/>/, `><style>.cls-1{fill:#ffffff}</style>`);
        }
        const blob = new Blob([svg], { type: "image/svg+xml" });
        const url = URL.createObjectURL(blob);
        const img = new Image();
        img.crossOrigin = "anonymous";
        img.onload = () => {
          if (cancelled) return;
          const canvas = document.createElement("canvas");
          canvas.width = img.naturalWidth * 2; // 2x para mejor resolución
          canvas.height = img.naturalHeight * 2;
          const ctx = canvas.getContext("2d");
          ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
          setLogoDataUrl(canvas.toDataURL("image/png"));
          URL.revokeObjectURL(url);
        };
        img.onerror = () => { URL.revokeObjectURL(url); };
        img.src = url;
      } catch (e) { /* silencioso, el PDF cae a texto */ }
    })();
    return () => { cancelled = true; };
  }, []);

  /* ---- Estado del cotizador ---- */
  const [items, setItems] = useState(() => {
    try {
      const raw = localStorage.getItem("imco_quote_items");
      return raw ? JSON.parse(raw) : [];
    } catch (e) { return []; }
  });
  const [sku, setSku] = useState("");
  const [qty, setQty] = useState("");
  const [note, setNote] = useState("");

  // Datos del cliente (obligatorios) — persistidos en localStorage
  const initCust = (() => {
    try {
      const raw = localStorage.getItem("imco_quote_customer");
      return raw ? JSON.parse(raw) : {};
    } catch (e) { return {}; }
  })();
  const [empresa, setEmpresa]   = useState(initCust.empresa  || "");
  const [nit, setNit]           = useState(initCust.nit      || "");
  const [contacto, setContacto] = useState(initCust.contacto || "");
  const [telefono, setTelefono] = useState(initCust.telefono || "");
  const [ciudad, setCiudad]     = useState(initCust.ciudad   || "");
  const [empresaError, setEmpresaError]   = useState(false);
  const [nitError, setNitError]           = useState(false);
  const [contactoError, setContactoError] = useState(false);
  const [telefonoError, setTelefonoError] = useState(false);
  const [ciudadError, setCiudadError]     = useState(false);
  const [skuError, setSkuError] = useState(false);

  useEffect(() => {
    try { localStorage.setItem("imco_quote_items", JSON.stringify(items)); } catch (e) {}
  }, [items]);

  useEffect(() => {
    try {
      localStorage.setItem("imco_quote_customer", JSON.stringify({ empresa, nit, contacto, telefono, ciudad }));
    } catch (e) {}
  }, [empresa, nit, contacto, telefono, ciudad]);

  function addItem(e) {
    e?.preventDefault();
    const skuClean = sku.trim().toUpperCase();
    if (!skuClean) {
      setSkuError(true);
      return;
    }
    const qtyNum = Math.max(1, parseInt(qty, 10) || 1);
    setItems((prev) => {
      const idx = prev.findIndex((i) => String(i.sku).toUpperCase() === skuClean);
      if (idx >= 0) {
        const next = [...prev];
        next[idx] = { ...next[idx], qty: next[idx].qty + qtyNum, note: note.trim() || next[idx].note };
        return next;
      }
      return [...prev, { sku: skuClean, qty: qtyNum, note: note.trim() }];
    });
    setSku("");
    setQty("");
    setNote("");
    setSkuError(false);
    document.getElementById("qf-sku")?.focus();
  }

  function removeItem(idx) {
    setItems((prev) => prev.filter((_, i) => i !== idx));
  }
  function updateItemQty(idx, newQty) {
    setItems((prev) => {
      const next = [...prev];
      const q = Math.max(1, parseInt(newQty, 10) || 1);
      next[idx] = { ...next[idx], qty: q };
      return next;
    });
  }
  function clearAll() {
    if (items.length === 0) return;
    if (confirm("¿Vaciar la cotización?")) setItems([]);
  }

  /* ---- Enriquecimiento con catálogo ---- */
  const enriched = useMemo(() => {
    return items.map((it) => {
      const found = catalog?.[String(it.sku).toUpperCase()];
      const unitPrice = found && typeof found.price === "number" ? found.price : 0;
      return {
        ...it,
        desc: found?.desc || null,
        agotado: !!found?.agotado,
        unknown: !found,
        unitPrice,
        lineTotal: unitPrice * it.qty,
      };
    });
  }, [items, catalog]);

  const totalUnits = useMemo(() => items.reduce((s, i) => s + (i.qty || 0), 0), [items]);
  const totalRaw   = useMemo(() => enriched.reduce((s, i) => s + i.lineTotal, 0), [enriched]);
  const totalRounded = Math.round(totalRaw / REDONDEO_TOTAL) * REDONDEO_TOTAL;
  const aboveThreshold = totalRaw >= MINIMO_PEDIDO;

  /* ---- Mensaje WhatsApp ---- */
  function buildMessage() {
    if (items.length === 0) return "";
    const lines = [];
    lines.push("*Solicitud de cotización · Imcopartes*");
    lines.push("");
    lines.push(`*Empresa:* ${empresa.trim()}`);
    if (nit.trim())      lines.push(`*NIT / CC:* ${nit.trim()}`);
    if (contacto.trim()) lines.push(`*Contacto:* ${contacto.trim()}`);
    if (telefono.trim()) lines.push(`*Teléfono:* ${telefono.trim()}`);
    if (ciudad.trim())   lines.push(`*Ciudad:* ${ciudad.trim()}`);
    lines.push("");
    lines.push(`*Referencias (${items.length}):*`);
    enriched.forEach((it, i) => {
      const descPart = it.desc ? ` — ${toTitleCase(it.desc)}` : (it.unknown ? " — (pendiente verificación)" : "");
      const notePart = it.note ? `  [${it.note}]` : "";
      lines.push(`${i + 1}. ${it.sku.toUpperCase()}  ×${it.qty}${descPart}${notePart}`);
    });
    lines.push("");
    lines.push(`*Total unidades:* ${totalUnits}`);
    if (aboveThreshold) {
      lines.push(`*Valor aproximado:* COP ${fmtCOP(totalRounded)}`);
    }
    lines.push("");
    lines.push("Adjunto PDF con el detalle. Por favor confirmar cotización mayorista y tiempos de despacho.");
    return lines.join("\n");
  }

  /* ---- PDF ---- */
  function generatePDF() {
    const { jsPDF } = window.jspdf || {};
    if (!jsPDF) { alert("No se pudo generar el PDF (librería no cargada)."); return false; }
    const doc = new jsPDF({ unit: "pt", format: "letter" });
    const pageW = doc.internal.pageSize.getWidth();
    const pageH = doc.internal.pageSize.getHeight();
    const margin = 48;

    /* === Header azul con logo + datos === */
    const headerH = 110;
    doc.setFillColor(20, 93, 158);
    doc.rect(0, 0, pageW, headerH, "F");
    // Banda diagonal sutil
    doc.setFillColor(15, 73, 124);
    doc.setLineWidth(0);
    const triPts = [
      [pageW - 180, 0],
      [pageW, 0],
      [pageW, headerH],
    ];
    doc.triangle(triPts[0][0], triPts[0][1], triPts[1][0], triPts[1][1], triPts[2][0], triPts[2][1], "F");

    // Logo (si está cargado) o fallback de texto
    if (logoDataUrl) {
      const logoH = 38;
      const logoW = logoH * (698 / 146); // proporción del SVG original
      doc.addImage(logoDataUrl, "PNG", margin, 28, logoW, logoH);
    } else {
      doc.setTextColor(255, 255, 255);
      doc.setFont("helvetica", "bold");
      doc.setFontSize(24);
      doc.text("IMCOPARTES", margin, 56);
    }
    // Datos de contacto al pie del header
    doc.setTextColor(220, 230, 245);
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    doc.text(`WhatsApp ${IMCO.whatsappDisplay}   ·   ${IMCO.emailContacto}   ·   Bogotá D.C., Colombia`,
      margin, headerH - 16);

    /* === Bloque título + referencia === */
    const ref = makeQuoteRef();
    const stamp = new Date();
    const stampStr = stamp.toLocaleDateString("es-CO", { year: "numeric", month: "long", day: "numeric" });

    doc.setTextColor(20, 20, 20);
    doc.setFont("helvetica", "bold");
    doc.setFontSize(20);
    doc.text("Solicitud de cotización", margin, headerH + 50);

    // Lado derecho: referencia + fecha
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    doc.setTextColor(120, 120, 120);
    doc.text("REFERENCIA", pageW - margin, headerH + 36, { align: "right" });
    doc.setFont("courier", "bold");
    doc.setFontSize(11);
    doc.setTextColor(20, 93, 158);
    doc.text(ref, pageW - margin, headerH + 52, { align: "right" });
    doc.setFont("helvetica", "normal");
    doc.setFontSize(9);
    doc.setTextColor(120, 120, 120);
    doc.text(`Fecha: ${stampStr}`, pageW - margin, headerH + 66, { align: "right" });

    /* === Datos del cliente (tarjeta clara) === */
    let y = headerH + 88;
    const cardX = margin;
    const cardW = pageW - margin * 2;
    const cardH = 88;
    doc.setFillColor(247, 247, 246);
    doc.setDrawColor(225, 225, 220);
    doc.setLineWidth(0.8);
    doc.roundedRect(cardX, y, cardW, cardH, 6, 6, "FD");

    doc.setTextColor(120, 120, 120);
    doc.setFont("helvetica", "bold");
    doc.setFontSize(8);
    doc.text("DATOS DEL CLIENTE", cardX + 18, y + 18);

    const colW = (cardW - 18 * 2) / 2;
    function clientField(label, value, col, row) {
      const x0 = cardX + 18 + (col === 1 ? colW : 0);
      const y0 = y + 34 + row * 18;
      doc.setFont("helvetica", "normal");
      doc.setFontSize(8);
      doc.setTextColor(120, 120, 120);
      doc.text(label, x0, y0);
      doc.setFont("helvetica", "bold");
      doc.setFontSize(10);
      doc.setTextColor(20, 20, 20);
      doc.text(value || "—", x0 + 70, y0);
    }
    clientField("Empresa:",   empresa.trim(),   0, 0);
    clientField("NIT / CC:",  nit.trim(),       1, 0);
    clientField("Contacto:",  contacto.trim(),  0, 1);
    clientField("Teléfono:",  telefono.trim(),  1, 1);
    clientField("Ciudad:",    ciudad.trim(),    0, 2);

    y += cardH + 22;

    /* === Tabla de referencias === */
    const head = [["#", "SKU", "Descripción", "Cant."]];
    const body = enriched.map((it, i) => [
      `${i + 1}`,
      it.sku.toUpperCase(),
      (it.desc ? toTitleCase(it.desc) : (it.unknown ? "(Pendiente de verificación)" : "")) +
        (it.note ? `\n${toTitleCase(it.note)}` : ""),
      `${it.qty}`,
    ]);

    doc.autoTable({
      startY: y,
      head, body,
      theme: "plain",
      styles: { fontSize: 9.5, cellPadding: 7, overflow: "linebreak", lineColor: [232, 232, 228], lineWidth: 0.5, textColor: [40, 40, 40] },
      headStyles: { fillColor: [20, 93, 158], textColor: 255, fontStyle: "bold", fontSize: 9, lineWidth: 0 },
      alternateRowStyles: { fillColor: [250, 250, 248] },
      columnStyles: {
        0: { cellWidth: 28, halign: "center", textColor: [140, 140, 140] },
        1: { cellWidth: 92, font: "courier", fontStyle: "bold", textColor: [20, 93, 158] },
        2: { cellWidth: "auto" },
        3: { cellWidth: 50, halign: "center", fontStyle: "bold" },
      },
      margin: { left: margin, right: margin },
    });

    const finalY = doc.lastAutoTable.finalY + 16;

    // Resumen totales
    doc.setFillColor(20, 93, 158);
    doc.rect(margin, finalY, pageW - margin * 2, 30, "F");
    doc.setTextColor(255, 255, 255);
    doc.setFont("helvetica", "bold");
    doc.setFontSize(11);
    doc.text(`Total referencias: ${items.length}`, margin + 16, finalY + 19);
    doc.text(`Total unidades: ${totalUnits}`, pageW - margin - 16, finalY + 19, { align: "right" });

    /* === Footer === */
    const footY = pageH - 64;
    doc.setDrawColor(230, 230, 226);
    doc.setLineWidth(0.5);
    doc.line(margin, footY, pageW - margin, footY);

    doc.setFont("helvetica", "bold");
    doc.setFontSize(9);
    doc.setTextColor(20, 20, 20);
    doc.text(IMCO.empresa, margin, footY + 16);
    doc.setFont("helvetica", "normal");
    doc.setFontSize(8);
    doc.setTextColor(120, 120, 120);
    doc.text(`${IMCO.direccion} · ${IMCO.ciudad}`, margin, footY + 30);

    doc.setFont("helvetica", "italic");
    doc.setFontSize(7.5);
    doc.setTextColor(150, 150, 150);
    doc.text(
      "Documento informativo. No constituye una cotización formal. Precios, disponibilidad y condiciones comerciales son confirmados por el asesor comercial.",
      pageW - margin, footY + 16, { maxWidth: 300, align: "right" }
    );

    const stampFile = stamp.toISOString().slice(0, 10);
    doc.save(`cotizacion-imcopartes-${stampFile}-${ref.slice(-4)}.pdf`);
    return true;
  }

  function sendQuote() {
    if (!aboveThreshold) return;
    // Validar TODOS los datos del cliente (obligatorios)
    const checks = [
      { val: empresa.trim(),  set: setEmpresaError,  id: "qf-empresa"  },
      { val: nit.trim(),      set: setNitError,      id: "qf-nit"      },
      { val: contacto.trim(), set: setContactoError, id: "qf-contacto" },
      { val: telefono.trim(), set: setTelefonoError, id: "qf-telefono" },
      { val: ciudad.trim(),   set: setCiudadError,   id: "qf-ciudad"   },
    ];
    let firstBadId = null;
    checks.forEach((c) => {
      const ok = c.val.length > 0;
      c.set(!ok);
      if (!ok && !firstBadId) firstBadId = c.id;
    });
    if (firstBadId) {
      setTimeout(() => { document.getElementById(firstBadId)?.focus(); }, 50);
      return;
    }
    const ok = generatePDF();
    if (!ok) return;
    // Pequeño delay para que el navegador procese la descarga antes de abrir la nueva pestaña
    setTimeout(() => {
      window.open(waLink(buildMessage()), "_blank", "noopener,noreferrer");
    }, 350);
  }

  /* ---- Render ---- */
  return (
    <section className="quote-section">
      <div className="quote-head">
        <span className="eye">Cotizador rápido</span>
        <h2>Cotiza por SKU en minutos.</h2>
        <p>
          Escribe las referencias que necesitas con su cantidad. Cuando tu cotización
          esté lista, envíala al asesor comercial con un clic — descarga automática del
          PDF y mensaje por WhatsApp.
        </p>
      </div>

      <div className="quote-grid">
        {/* ===== FORM ===== */}
        <div className="quote-card">
          <h3>Agregar referencia</h3>
          <p className="quote-card__sub">
            Si no conoces el SKU exacto, escribe la descripción o el número OEM en la nota — el asesor te ayuda a identificarlo.
          </p>

          <form className="quote-form" onSubmit={addItem}>
            <div className={"qf-field qf-field--sku" + (skuError ? " qf-field--error" : "")}>
              <label htmlFor="qf-sku">SKU / Referencia *</label>
              <input
                id="qf-sku"
                value={sku}
                onChange={(e) => { setSku(e.target.value); setSkuError(false); }}
                placeholder="ICP-1221L"
                autoComplete="off"
              />
            </div>
            <div className="qf-field">
              <label htmlFor="qf-qty">Cantidad</label>
              <input
                id="qf-qty"
                type="number"
                min="1"
                step="1"
                value={qty}
                onChange={(e) => setQty(e.target.value)}
                placeholder="1"
                inputMode="numeric"
              />
            </div>
            <button type="submit" className="btn btn-primary qf-btn">
              <i data-lucide="plus" style={{ width: 16, height: 16 }}></i>
              Agregar
            </button>
          </form>

          <div className="qf-extras">
            <textarea
              placeholder="Nota opcional (vehículo, modelo, año, OEM…)"
              value={note}
              onChange={(e) => setNote(e.target.value)}
            />
          </div>

          <div style={{
            display: "flex", gap: 12, alignItems: "center", marginTop: 18,
            padding: 14, background: "var(--blue-50)", borderRadius: 8,
            fontSize: 12, color: "var(--imco-black)", lineHeight: 1.55
          }}>
            <i data-lucide="info" style={{ width: 16, height: 16, color: "var(--imco-blue)", flexShrink: 0 }}></i>
            <span>
              <strong>Tip:</strong> mientras agregas referencias verificamos la descripción contra nuestro catálogo.
              Las marcadas como "pendiente verificación" se confirman con el asesor al recibirlas.
            </span>
          </div>
        </div>

        {/* ===== CART ===== */}
        <div className="quote-cart">
          <div className="quote-cart__head">
            <h3>Tu cotización</h3>
            <span className={"quote-cart__count" + (items.length > 0 ? " quote-cart__count--active" : "")}>
              {items.length} ref · {totalUnits} und
            </span>
          </div>

          {items.length === 0 ? (
            <div className="quote-empty">
              <i data-lucide="package" style={{ width: 40, height: 40 }}></i>
              <p>Aún no has agregado referencias.</p>
              <p className="small">Empieza escribiendo un SKU en el formulario.</p>
            </div>
          ) : (
            <div className="quote-list">
              {enriched.map((it, i) => (
                <div key={i} className={"quote-item" + (it.unknown ? " quote-item--unknown" : "")}>
                  <div className="quote-item__main">
                    <span className="quote-item__sku">{it.sku.toUpperCase()}</span>
                    {it.desc ? (
                      <span className="quote-item__desc">{toTitleCase(it.desc)}</span>
                    ) : it.unknown ? (
                      <span className="quote-item__desc quote-item__desc--unknown">
                        <SvgIcon d={ICON_PATHS.alertCircle} size={11} />
                        Pendiente de verificación
                      </span>
                    ) : null}
                    {it.note && <span className="quote-item__note">{it.note}</span>}
                  </div>
                  <div className="quote-item__qty-edit" role="group" aria-label={`Cantidad de ${it.sku}`}>
                    <button
                      type="button"
                      className="quote-item__qty-btn"
                      aria-label="Disminuir cantidad"
                      onClick={() => updateItemQty(i, Math.max(1, it.qty - 1))}
                      disabled={it.qty <= 1}
                    >−</button>
                    <input
                      type="number"
                      min="1"
                      step="1"
                      inputMode="numeric"
                      value={it.qty}
                      onChange={(e) => updateItemQty(i, e.target.value)}
                      onBlur={(e) => updateItemQty(i, e.target.value)}
                      className="quote-item__qty-input"
                      aria-label="Cantidad"
                    />
                    <button
                      type="button"
                      className="quote-item__qty-btn"
                      aria-label="Aumentar cantidad"
                      onClick={() => updateItemQty(i, it.qty + 1)}
                    >+</button>
                  </div>
                  <button
                    className="quote-item__remove"
                    type="button"
                    aria-label={`Quitar ${it.sku}`}
                    onClick={() => removeItem(i)}
                  >
                    <SvgIcon d={ICON_PATHS.x} size={16} />
                  </button>
                </div>
              ))}
            </div>
          )}

          {items.length > 0 && (
            <div className="quote-cart__send">
              {/* Estado del umbral */}
              {catalogStatus === "loading" && (
                <div className="quote-threshold quote-threshold--loading">
                  <SvgIcon d={ICON_PATHS.loader} size={16} />
                  Cargando catálogo de referencias…
                </div>
              )}
              {catalogStatus === "ready" && !aboveThreshold && (
                <div className="quote-threshold quote-threshold--below">
                  <SvgIcon d={ICON_PATHS.packagePlus} size={18} />
                  <div>
                    <strong>Tu cotización aún no alcanza el mínimo para enviar.</strong>
                    <span>Sigue agregando referencias del catálogo. Cuando estés listo, podrás enviar tu solicitud al asesor con un solo clic.</span>
                  </div>
                </div>
              )}
              {catalogStatus === "ready" && aboveThreshold && (
                <div className="quote-threshold quote-threshold--above">
                  <SvgIcon d={ICON_PATHS.checkCircle} size={18} />
                  <div>
                    <strong>Listo para enviar.</strong>
                    <span>Valor aproximado: <strong>COP {fmtCOP(totalRounded)}</strong>. El asesor confirma precios y disponibilidad final.</span>
                  </div>
                </div>
              )}
              {catalogStatus === "error" && (
                <div className="quote-threshold quote-threshold--below">
                  <SvgIcon d={ICON_PATHS.alertTriangle} size={18} />
                  <div>
                    <strong>No pudimos verificar el catálogo.</strong>
                    <span>Puedes igualmente descargar tu lista en PDF o enviarla por WhatsApp y un asesor la procesa manualmente.</span>
                  </div>
                </div>
              )}

              <div className="qf-customer">
                <div className={"qf-field qf-field--full" + (empresaError ? " qf-field--error" : "")}>
                  <label htmlFor="qf-empresa">Empresa / Taller *</label>
                  <input
                    id="qf-empresa"
                    type="text"
                    value={empresa}
                    onChange={(e) => { setEmpresa(e.target.value); if (empresaError) setEmpresaError(false); }}
                    placeholder="Taller XYZ S.A.S."
                  />
                </div>
                <div className={"qf-field" + (nitError ? " qf-field--error" : "")}>
                  <label htmlFor="qf-nit">NIT / Cédula *</label>
                  <input
                    id="qf-nit"
                    type="text"
                    value={nit}
                    onChange={(e) => { setNit(e.target.value); if (nitError) setNitError(false); }}
                    placeholder="900.000.000-0"
                    style={{ fontFamily: "var(--font-mono)", fontSize: 13 }}
                  />
                </div>
                <div className={"qf-field" + (ciudadError ? " qf-field--error" : "")}>
                  <label htmlFor="qf-ciudad">Ciudad *</label>
                  <input
                    id="qf-ciudad"
                    type="text"
                    value={ciudad}
                    onChange={(e) => { setCiudad(e.target.value); if (ciudadError) setCiudadError(false); }}
                    placeholder="Bogotá D.C."
                  />
                </div>
                <div className={"qf-field" + (contactoError ? " qf-field--error" : "")}>
                  <label htmlFor="qf-contacto">Nombre *</label>
                  <input
                    id="qf-contacto"
                    type="text"
                    value={contacto}
                    onChange={(e) => { setContacto(e.target.value); if (contactoError) setContactoError(false); }}
                    placeholder="Tu nombre"
                  />
                </div>
                <div className={"qf-field" + (telefonoError ? " qf-field--error" : "")}>
                  <label htmlFor="qf-telefono">Teléfono *</label>
                  <input
                    id="qf-telefono"
                    type="tel"
                    value={telefono}
                    onChange={(e) => { setTelefono(e.target.value); if (telefonoError) setTelefonoError(false); }}
                    placeholder="300 000 0000"
                    inputMode="tel"
                  />
                </div>
              </div>

              <button
                className={"btn btn-lg quote-send-btn " + (aboveThreshold ? "btn-success" : "btn-disabled")}
                type="button"
                onClick={sendQuote}
                disabled={!aboveThreshold || catalogStatus !== "ready"}
              >
                <SvgIcon d={aboveThreshold ? ICON_PATHS.send : ICON_PATHS.lock} size={18} />
                {aboveThreshold ? "Enviar cotización al asesor" : "Sigue agregando para enviar"}
              </button>

              <button
                className="btn btn-ghost btn-sm"
                type="button"
                onClick={clearAll}
                style={{ alignSelf: "center", color: "var(--fg-muted)" }}
              >
                <i data-lucide="trash-2" style={{ width: 14, height: 14 }}></i>
                Vaciar lista
              </button>

              {aboveThreshold && (
                <p className="quote-cart__hint">
                  Se descarga el PDF con tu solicitud y se abre WhatsApp con el resumen para enviarlo al asesor.
                </p>
              )}
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

/* ===== Líneas de producto ===== */
function CatalogLines() {
  const lines = [
    { icon: "zap",        name: "Switches eléctricos",       desc: "Switches de elevavidrios, encendido, luces y principales. Componentes de uso intensivo con respuesta confiable.",                          brand: "MrSwitch" },
    { icon: "fan",        name: "Cremalleras y Motores elevavidrios",         desc: "Cremalleras y motores que devuelven el accionamiento original al sistema de elevavidrios en múltiples plataformas.",     brand: "MrSwitch" },
    { icon: "rotate-cw",  name: "Cintas de airbag, pito y mandos", desc: "Carretes (clock springs) que aseguran la continuidad eléctrica del airbag, pito y mandos del volante. Compatibilidad verificada por modelo.", brand: "MrSwitch" },
    { icon: "cylinder",   name: "Amortiguadores a gas",       desc: "Amortiguadores a gas para capó, compuerta y platón. Amplio surtido en medidas originales y adaptaciones, respaldado con garantía de fabricante.",         brand: "ProLift" },
    { icon: "gamepad-2",  name: "Peras y palancas de cambio", desc: "Peras y palancas de transmisión que renuevan el tacto del cambio. Variedad de modelos para múltiples marcas y años.",                   brand: "MrShift" },
    { icon: "key-round",  name: "Manijas y cerraduras",       desc: "Cerraduras, manijas exteriores e interiores que recuperan la seguridad y el acabado original. Línea principal Novparts.",   brand: "Novparts" },
  ];
  return (
    <section className="cat-lines">
      <div className="cat-lines__inner">
        <div className="section__head">
          <div>
            <span className="eye">Líneas representadas</span>
            <h2 style={{ fontSize: 32 }}>Lo que distribuimos.</h2>
          </div>
          <a
            className="btn btn-secondary"
            href="assets/catalogo/Lista-de-Productos-Imcopartes-2026.pdf"
            download="Lista-de-Productos-Imcopartes-2026.pdf"
            target="_blank" rel="noopener noreferrer"
          >
            <i data-lucide="file-text" style={{ width: 16, height: 16 }}></i>
            Ver lista completa
          </a>
        </div>
        <div className="cat-lines-grid">
          {lines.map((l, i) => (
            <div key={i} className="cat-line">
              <div className="cat-line__icon"><i data-lucide={l.icon}></i></div>
              <h3>{l.name}</h3>
              <p>{l.desc}</p>
              <span className="cat-line__count">Marca · {l.brand}</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ===== Coming soon strip ===== */
function ComingSoon() {
  return (
    <section className="coming-soon">
      <div className="coming-soon__inner">
        <div className="coming-soon__badge">
          <i data-lucide="key-round"></i>
        </div>
        <div>
          <h3>Próximamente: catálogo navegable para distribuidores autorizados.</h3>
          <p>
            Estamos preparando el portal con búsqueda por SKU, OEM, vehículo y compatibilidad,
            con acceso por usuario para distribuidores, vendedores y administrativos.
            Si quieres recibir la invitación cuando esté listo, escríbenos por WhatsApp.
          </p>
        </div>
      </div>
    </section>
  );
}

/* ===== Notice top ===== */
function Notice() {
  return (
    <div className="catalog-notice">
      <div className="catalog-notice__inner">
        <i data-lucide="info"></i>
        <div>
          <strong>Atención mayorista.</strong>
          <span>
            Imcopartes atiende únicamente a clientes mayoristas con RUT vigente en Colombia
            (personas naturales o jurídicas).
          </span>
        </div>
      </div>
    </div>
  );
}

/* ===== App ===== */
function App() {
  useLucide();
  return (
    <div data-screen-label="Catálogo">
      <Nav active="catalogo" />
      <CatalogHead />
      <Notice />
      <QuoteBuilder />
      <CatalogLines />
      <ComingSoon />
      <Footer />
      <WhatsAppFAB message="Hola Imcopartes, quisiera cotizar referencias del catálogo." />
      <CookieBanner />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
