﻿/* ============================================================
   INside quote generator — Módulo RFQ (Request For Quotation) a fábrica
   Libreta de fábricas + RFQs (desde cotización o desde cero) + PDF fillable.
   ============================================================ */

function RFQView() {
  const ctx = React.useContext(window.AppCtx);
  const { rfqs, addRfq, updateRfq, removeRfq, nextRfqNumber, factories, openRfqId, setOpenRfqId } = ctx;
  const [editingId, setEditingId] = React.useState(null);
  const [factoryMgr, setFactoryMgr] = React.useState(false);
  const [confirm, setConfirm] = React.useState(null);

  React.useEffect(() => {
    if (openRfqId) { setEditingId(openRfqId); setOpenRfqId(null); }
  }, [openRfqId]);

  const editing = rfqs.find((r) => r.id === editingId);

  const newBlank = async () => {
    const id = await addRfq({
      rfq_number: nextRfqNumber(),
      date: new Date().toISOString().split("T")[0],
      project_ref: "", client_ref: "", from_quote: "",
      factory_id: null, factory_name: "", factory_contact: "", factory_email: "",
      need_by: "", notes: "",
      logistics: {
        shipping_method: "", incoterm: "", port_of_origin: "",
        production_lead_time: "", total_quantity: "",
        hs_code: "", net_weight: "", gross_weight: "",
        dimensions: "", packaging_type: "",
      },
      items: []
    });
    setEditingId(id);
  };

  if (editing) {
    return <RFQEditor rfq={editing} onClose={() => setEditingId(null)}
      onChange={(patch) => updateRfq(editing.id, patch)} factories={factories} />;
  }

  const STATUS = { draft: "Borrador", sent: "Enviado", quoted: "Cotizado", ordered: "Pedido" };

  return (
    <div style={{ padding: "28px 36px 80px", maxWidth: 1280, margin: "0 auto" }}>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginBottom: 22, gap: 20, flexWrap: "wrap" }}>
        <div>
          <div className="eyebrow">Módulo · Solicitudes a proveedor</div>
          <h1 className="page-title">Solicitudes a Proveedor</h1>
          <p className="page-sub">{rfqs.length} {rfqs.length === 1 ? "solicitud" : "solicitudes"} · pide precio o haz el pedido a proveedor</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <window.Btn variant="outline" icon="factory" onClick={() => setFactoryMgr(true)}>Proveedores</window.Btn>
          <window.Btn variant="gold" icon="plus" onClick={newBlank}>Nueva solicitud</window.Btn>
        </div>
      </div>

      {rfqs.length === 0 ? (
        <div className="empty" style={{ padding: "50px 20px" }}>
          <window.Icon name="factory" size={28} style={{ color: "var(--muted)", marginBottom: 12 }} />
          <div style={{ fontSize: 15, color: "var(--text)", marginBottom: 4 }}>Aún no hay solicitudes a proveedor</div>
          <div style={{ fontSize: 13 }}>Crea una con «Nueva solicitud», o desde una cotización con el botón «Crear solicitud».</div>
        </div>
      ) : (
        <window.Card pad={0} style={{ overflow: "hidden" }}>
          <table className="hist-table">
            <thead><tr>
              <th>N.º</th><th>Fábrica</th><th>Proyecto / cliente</th><th>Ítems</th><th>Necesito</th><th>Estado</th><th style={{ textAlign: "right" }}>Acciones</th>
            </tr></thead>
            <tbody>
              {rfqs.map((r) => (
                <tr key={r.id} className="hist-row">
                  <td style={{ fontFamily: "var(--mono)", fontWeight: 600, color: "var(--gold)" }}>{r.rfq_number}</td>
                  <td style={{ fontWeight: 600 }}>{r.factory_name || <span style={{ color: "var(--muted)", fontWeight: 400 }}>— sin asignar —</span>}</td>
                  <td><div>{r.project_ref || "—"}</div><div style={{ fontSize: 11, color: "var(--muted)" }}>{r.client_ref}</div></td>
                  <td style={{ fontFamily: "var(--mono)" }}>{(r.items || []).length}</td>
                  <td style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)" }}>{r.need_by || "—"}</td>
                  <td>
                    <window.Select value={r.status || "draft"} onChange={(v) => updateRfq(r.id, { status: v })}
                      options={Object.keys(STATUS).map((k) => ({ value: k, label: STATUS[k] }))} style={{ minWidth: 118 }} />
                  </td>
                  <td>
                    <div style={{ display: "flex", gap: 4, justifyContent: "flex-end" }}>
                      <button className="iconbtn" title="Abrir / editar" onClick={() => setEditingId(r.id)}><window.Icon name="edit" size={15} /></button>
                      <button className="iconbtn danger" title="Eliminar"
                        onClick={() => setConfirm({ title: "Eliminar RFQ", message: `Se eliminará ${r.rfq_number}. Esta acción no se puede deshacer.`, onConfirm: () => removeRfq(r.id) })}>
                        <window.Icon name="trash" size={15} /></button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </window.Card>
      )}

      {factoryMgr && <FactoryManager onClose={() => setFactoryMgr(false)} />}
      <window.ConfirmModal open={!!confirm} title={confirm && confirm.title} message={confirm && confirm.message}
        onConfirm={() => confirm && confirm.onConfirm()} onClose={() => setConfirm(null)} />
    </div>
  );
}

// ---------- Editor de RFQ ----------
function RFQEditor({ rfq, onClose, onChange, factories }) {
  const { settings } = React.useContext(window.AppCtx);
  const [showPdf, setShowPdf] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const set = (patch) => onChange(patch);

  const sendRfqEmail = async () => {
    if (busy) return;
    if (!rfq.factory_email) return;
    if (!window.GAuth) { alert("Error: google-auth.js no cargó."); return; }
    setBusy(true);
    try {
      const token = await window.GAuth.ensureToken(settings.google_client_id);
      const { bytes, filename } = await buildRfqPdf(rfq, "es", settings);
      const fill = (tpl) => (tpl || "").replace(/\{\{(\w+)\}\}/g, (_, k) => ({
        contacto: rfq.factory_contact || "Team",
        numero: rfq.rfq_number || "",
        proyecto: rfq.project_ref || "",
        proyecto_linea: rfq.project_ref ? " for project " + rfq.project_ref : "",
        fecha_limite: rfq.need_by ? " before " + rfq.need_by : " at your earliest convenience",
      })[k] || "");
      await Promise.all([
        window.GAuth.createDraftWithPdf({
          token,
          to: rfq.factory_email,
          subject: fill(settings.email_rfq_subject),
          body: fill(settings.email_rfq_body),
          pdfBytes: bytes,
          pdfFilename: filename,
        }),
        window.GAuth.uploadToDrive({
          token,
          folderId: settings.google_drive_folder_id || null,
          folderName: settings.google_drive_folder || "03 HISTORIAL DE COTIZACIONES",
          pdfBytes: bytes,
          pdfFilename: filename,
        }).catch(e => console.warn("Drive upload:", e.message)),
      ]);
    } catch (e) {
      console.error("RFQ send error:", e);
      alert("Error al enviar: " + e.message);
    }
    setBusy(false);
  };
  const setLog = (patch) => onChange({ logistics: { ...rfq.logistics, ...patch } });
  const items = rfq.items || [];
  const setItems = (next) => onChange({ items: next });
  const updItem = (id, patch) => setItems(items.map((it) => it.id === id ? { ...it, ...patch } : it));
  const addItem = () => setItems([...items, {
    id: "ri-" + Date.now().toString(36) + Math.random().toString(36).slice(2, 5),
    name: "", sku: "", specs: "", quantity: 1, unit: "und",
  }]);
  const delItem = (id) => setItems(items.filter((it) => it.id !== id));

  if (showPdf) return <RFQPdf rfq={rfq} onBack={() => setShowPdf(false)} />;

  const loadFactory = (id) => {
    const f = factories.find((x) => x.id === id);
    if (!f) { set({ factory_id: null }); return; }
    set({ factory_id: f.id, factory_name: f.name, factory_contact: f.contact || "", factory_email: f.email || "",
      logistics: { ...rfq.logistics, port_of_origin: rfq.logistics.port_of_origin || f.port || "" } });
  };

  const buildRfqExcel = async () => {
    if (typeof XLSX === "undefined") { alert("La librería de Excel aún no cargó. Intenta de nuevo."); return; }
    const sane = (s) => String(s || "").replace(/[\\/:*?"<>|]/g, "").replace(/\s+/g, " ").trim();
    let wb;
    try {
      const resp = await fetch("cotizador/assets/rfq-template.xlsx");
      const buf = await resp.arrayBuffer();
      wb = XLSX.read(buf, { type: "array", cellStyles: true });
    } catch (e) {
      alert("No se pudo cargar la plantilla. Intenta de nuevo."); return;
    }
    const ws = wb.Sheets["Solicitud"];
    const setCell = (addr, val) => {
      if (!ws[addr]) ws[addr] = {};
      ws[addr].v = val; ws[addr].t = typeof val === "number" ? "n" : "s";
    };
    setCell("B2", rfq.rfq_number || ""); setCell("E2", rfq.date || "");
    setCell("B3", rfq.factory_name || ""); setCell("E3", rfq.factory_contact || "");
    setCell("B4", rfq.factory_email || ""); setCell("E4", rfq.need_by || "");
    setCell("B5", rfq.project_ref || ""); setCell("E5", rfq.client_ref || "");
    ["A8","B8","C8","D8","E8","A9","B9","C9","D9","E9"].forEach(a => { delete ws[a]; });
    items.forEach((it, i) => {
      const r = 8 + i;
      setCell(`A${r}`, i + 1); setCell(`B${r}`, it.name || "");
      setCell(`C${r}`, it.specs || ""); setCell(`D${r}`, Number(it.quantity) || 0);
      ws[`D${r}`].t = "n"; setCell(`E${r}`, it.unit || "");
    });
    if (items.length === 0) setCell("B8", "(sin ítems)");
    const delta = items.length - 2;
    if (delta !== 0) {
      const logStart = 11, logEnd = 23;
      if (delta > 0) {
        for (let r = logEnd + delta; r >= logStart + delta; r--) {
          const srcR = r - delta;
          ["A","B","C","D","E"].forEach(col => {
            const dst = `${col}${r}`, src = `${col}${srcR}`;
            if (ws[src]) { ws[dst] = {...ws[src]}; delete ws[src]; } else delete ws[dst];
          });
        }
      } else {
        for (let r = logStart + delta; r <= logEnd + delta; r++) {
          const srcR = r - delta;
          ["A","B","C","D","E"].forEach(col => {
            const dst = `${col}${r}`, src = `${col}${srcR}`;
            if (ws[src]) { ws[dst] = {...ws[src]}; delete ws[src]; } else delete ws[dst];
          });
        }
      }
      if (ws["!merges"]) {
        ws["!merges"] = ws["!merges"].map(m => {
          if (m.s.r >= logStart - 1) return { s:{r:m.s.r+delta,c:m.s.c}, e:{r:m.e.r+delta,c:m.e.c} };
          return m;
        });
      }
    }
    const lastRow = Math.max(21, 8 + Math.max(items.length, 1)) + delta + 2;
    ws["!ref"] = `A1:E${lastRow}`;
    XLSX.writeFile(wb, sane(rfq.rfq_number || "RFQ") + " - " + sane(rfq.factory_name || "Proveedor") + ".xlsx");
  };

  const LFields = [
    ["shipping_method",      "Shipping method",         "Sea / Air / Courier"],
    ["incoterm",             "Incoterm",                "FOB / CIF / EXW"],
    ["port_of_origin",       "Port of origin",          "Shenzhen, CN"],
    ["production_lead_time", "Production lead time",    "4–6 semanas"],
    ["total_quantity",       "Total quantity",           "120 pcs / 350 m²"],
    ["hs_code",              "Código HS",               "ej. 6809.11"],
    ["net_weight",           "Net weight (kg)",         "kg"],
    ["gross_weight",         "Gross weight (kg)",       "kg"],
    ["dimensions",           "Dimensions (L×W×H / CBM)", "cm o CBM"],
    ["packaging_type",       "Packaging type",          "Pallet / carton / crate"],
  ];

  return (
    <div style={{ padding: "24px 36px 80px", maxWidth: 1180, margin: "0 auto" }}>
      <div className="pdf-toolbar" style={{ maxWidth: "none", marginBottom: 22 }}>
        <window.Btn variant="outline" icon="chevron" onClick={onClose} style={{ flexDirection: "row-reverse" }}>Volver</window.Btn>
        <div>
          <div className="eyebrow" style={{ textAlign: "center" }}>{rfq.rfq_number}{rfq.from_quote ? " · desde " + rfq.from_quote : ""}</div>
          <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "var(--muted)", textAlign: "center" }}>{items.length} ítem{items.length === 1 ? "" : "s"}</div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          <window.Btn variant="outline" icon="send"
            disabled={!rfq.factory_email || busy}
            title={rfq.factory_email ? "Crear borrador en Gmail con el PDF adjunto" : "Agrega el email del proveedor primero"}
            onClick={sendRfqEmail}>
            {busy ? "Generando…" : "Enviar"}
          </window.Btn>
          <window.Btn variant="gold" icon="download" onClick={() => setShowPdf(true)}>Ver PDF</window.Btn>
        </div>
      </div>

      <div className="rfq-grid">
        {/* datos generales */}
        <window.Card pad={20}>
          <h3 className="col-title">Solicitud</h3>
          <div className="rfq-fields">
            <RF label="N.º RFQ"><input className="inp" value={rfq.rfq_number} onChange={(e) => set({ rfq_number: e.target.value })} /></RF>
            <RF label="Necesito respuesta para"><input className="inp" type="date" value={rfq.need_by} onChange={(e) => set({ need_by: e.target.value })} /></RF>
            <RF label="Proyecto / referencia" full><input className="inp" value={rfq.project_ref} onChange={(e) => set({ project_ref: e.target.value })} placeholder="Auditorio Corporativo" /></RF>
            <RF label="Cliente (referencia)" full><input className="inp" value={rfq.client_ref} onChange={(e) => set({ client_ref: e.target.value })} placeholder="CREATIVE DEV, INC." /></RF>
          </div>

          <div className="hr" />
          <h3 className="col-title">Proveedor</h3>
          {factories.length > 0 && (
            <div style={{ marginBottom: 11 }}>
              <window.Select value={rfq.factory_id || ""} onChange={loadFactory} style={{ width: "100%" }}
                options={[{ value: "", label: "— Elegir de la libreta —" }, ...factories.map((f) => ({ value: f.id, label: f.name + (f.country ? " · " + f.country : "") }))]} />
            </div>
          )}
          <div className="rfq-fields">
            <RF label="Nombre" full><input className="inp" value={rfq.factory_name} onChange={(e) => set({ factory_name: e.target.value })} placeholder="Foshan Acoustics Co." /></RF>
            <RF label="Contacto"><input className="inp" value={rfq.factory_contact} onChange={(e) => set({ factory_contact: e.target.value })} placeholder="Ms. Li" /></RF>
            <RF label="Email"><input className="inp" value={rfq.factory_email} onChange={(e) => set({ factory_email: e.target.value })} placeholder="sales@factory.com" style={{ fontFamily: "var(--mono)" }} /></RF>
          </div>
        </window.Card>

        {/* logística */}
        <window.Card pad={20}>
          <h3 className="col-title">Datos logísticos generales</h3>
          <div className="rfq-fields">
            {LFields.map(([k, label, ph]) => (
              <RF key={k} label={label}><input className="inp" value={(rfq.logistics || {})[k] || ""} onChange={(e) => setLog({ [k]: e.target.value })} placeholder={ph} /></RF>
            ))}
          </div>
          <div className="hr" />
          <h3 className="col-title">Notas / observaciones</h3>
          <textarea className="inp" rows={4} value={rfq.notes} onChange={(e) => set({ notes: e.target.value })}
            placeholder="Especificaciones, certificaciones, requisitos de empaque, términos de pago…" style={{ resize: "vertical", fontFamily: "var(--body)" }} />
        </window.Card>
      </div>

      {/* ítems */}
      <window.Card pad={0} style={{ marginTop: 16, overflow: "hidden" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "16px 18px", borderBottom: "1px solid var(--border)" }}>
          <h3 className="col-title" style={{ margin: 0 }}>Ítems solicitados</h3>
          <window.Btn variant="outline" size="sm" icon="plus" onClick={addItem}>Agregar ítem</window.Btn>
        </div>
        {items.length === 0 ? (
          <div className="empty" style={{ padding: "34px 18px" }}>Sin ítems. Agrégalos aquí, o crea la solicitud desde una cotización con «Crear solicitud».</div>
        ) : (
          <div style={{ overflowX: "auto" }}>
            <table className="rfq-table">
              <thead><tr>
                <th style={{ minWidth: 200 }}>Producto</th>
                <th style={{ minWidth: 200 }}>Especificaciones</th>
                <th style={{ width: 80 }}>Cant.</th>
                <th style={{ width: 80 }}>Unidad</th>
                <th style={{ width: 34 }}></th>
              </tr></thead>
              <tbody>
                {items.map((it) => (
                  <tr key={it.id}>
                    <td><input className="cell-inp" value={it.name} onChange={(e) => updItem(it.id, { name: e.target.value })} placeholder="Producto" /></td>
                    <td><input className="cell-inp" value={it.specs} onChange={(e) => updItem(it.id, { specs: e.target.value })} placeholder="Acabado, medidas, color…" /></td>
                    <td><window.NumInput className="cell-inp num" value={it.quantity} onChange={(v) => updItem(it.id, { quantity: v })} /></td>
                    <td><input className="cell-inp" value={it.unit} onChange={(e) => updItem(it.id, { unit: e.target.value })} placeholder="und" /></td>
                    <td><button className="iconbtn danger" onClick={() => delItem(it.id)} title="Eliminar"><window.Icon name="trash" size={14} /></button></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </window.Card>
    </div>
  );
}

function RF({ label, children, full }) {
  return (
    <div style={{ gridColumn: full ? "1 / -1" : "auto" }}>
      <label className="field-lbl">{label}</label>
      {children}
    </div>
  );
}

// ---------- Libreta de fábricas ----------
function FactoryManager({ onClose }) {
  const { factories, addFactory, updateFactory, removeFactory } = React.useContext(window.AppCtx);
  const [editing, setEditing] = React.useState(null);
  const [confirm, setConfirm] = React.useState(null);

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ width: 560, maxHeight: "90vh", overflowY: "auto" }}>
        <div className="modal-head">
          <div>
            <div className="eyebrow">RFQ</div>
            <h3 style={{ margin: "3px 0 0", fontFamily: "var(--display)", fontSize: 20, fontWeight: 600 }}>Proveedores</h3>
          </div>
          <button className="iconbtn" onClick={onClose}><window.Icon name="x" size={18} /></button>
        </div>
        <div style={{ padding: "4px 22px 0", display: "flex", justifyContent: "flex-end" }}>
          <window.Btn variant="gold" size="sm" icon="plus" onClick={() => setEditing("new")}>Agregar proveedor</window.Btn>
        </div>
        <div style={{ padding: "12px 22px 4px", display: "flex", flexDirection: "column", gap: 8 }}>
          {factories.length === 0 && <div className="empty" style={{ padding: "26px 10px" }}>Sin proveedores guardados.</div>}
          {factories.map((f) => (
            <div key={f.id} style={{ display: "flex", alignItems: "center", gap: 12, padding: "11px 13px", background: "var(--bg)", border: "1px solid var(--border)", borderRadius: 10 }}>
              <window.Icon name="factory" size={16} style={{ color: "var(--muted)", flexShrink: 0 }} />
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 14, fontWeight: 600 }}>{f.name}</div>
                <div style={{ fontSize: 12, color: "var(--muted)", fontFamily: "var(--mono)" }}>{[f.contact, f.email, f.country].filter(Boolean).join(" · ")}</div>
              </div>
              <button className="iconbtn" onClick={() => setEditing(f)} title="Editar"><window.Icon name="edit" size={15} /></button>
              <button className="iconbtn danger" title="Eliminar"
                onClick={() => setConfirm({ title: "Eliminar fábrica", message: `Se eliminará «${f.name}» de la libreta.`, onConfirm: () => removeFactory(f.id) })}>
                <window.Icon name="trash" size={15} /></button>
            </div>
          ))}
        </div>
        <div className="modal-foot"><div style={{ flex: 1 }} /><window.Btn variant="outline" onClick={onClose}>Cerrar</window.Btn></div>
      </div>
      {editing && <FactoryForm factory={editing === "new" ? null : editing}
        onClose={() => setEditing(null)}
        onSave={(data) => { if (editing === "new") addFactory(data); else updateFactory(editing.id, data); setEditing(null); }} />}
      <window.ConfirmModal open={!!confirm} title={confirm && confirm.title} message={confirm && confirm.message}
        onConfirm={() => confirm && confirm.onConfirm()} onClose={() => setConfirm(null)} />
    </div>
  );
}

function FactoryForm({ factory, onClose, onSave }) {
  const [f, setF] = React.useState({
    name: factory ? factory.name : "", contact: factory ? factory.contact || "" : "",
    email: factory ? factory.email || "" : "", phone: factory ? factory.phone || "" : "",
    country: factory ? factory.country || "" : "", port: factory ? factory.port || "" : "",
  });
  const set = (p) => setF((s) => ({ ...s, ...p }));
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ width: 440 }}>
        <div className="modal-head">
          <div><div className="eyebrow">Fábricas</div>
            <h3 style={{ margin: "3px 0 0", fontFamily: "var(--display)", fontSize: 19, fontWeight: 600 }}>{factory ? "Editar proveedor" : "Nuevo proveedor"}</h3></div>
          <button className="iconbtn" onClick={onClose}><window.Icon name="x" size={18} /></button>
        </div>
        <div style={{ padding: "6px 22px 4px", display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
          <div style={{ gridColumn: "1 / -1" }}><label className="field-lbl">Nombre *</label><input className="inp" autoFocus value={f.name} onChange={(e) => set({ name: e.target.value })} placeholder="Foshan Acoustics Co." /></div>
          <div><label className="field-lbl">Contacto</label><input className="inp" value={f.contact} onChange={(e) => set({ contact: e.target.value })} placeholder="Ms. Li" /></div>
          <div><label className="field-lbl">Email</label><input className="inp" value={f.email} onChange={(e) => set({ email: e.target.value })} placeholder="sales@factory.com" style={{ fontFamily: "var(--mono)" }} /></div>
          <div><label className="field-lbl">Teléfono</label><input className="inp" value={f.phone} onChange={(e) => set({ phone: e.target.value })} style={{ fontFamily: "var(--mono)" }} /></div>
          <div><label className="field-lbl">País</label><input className="inp" value={f.country} onChange={(e) => set({ country: e.target.value })} placeholder="China" /></div>
          <div style={{ gridColumn: "1 / -1" }}><label className="field-lbl">Puerto de origen (por defecto)</label><input className="inp" value={f.port} onChange={(e) => set({ port: e.target.value })} placeholder="Shenzhen, CN" /></div>
        </div>
        <div className="modal-foot"><div style={{ flex: 1 }} />
          <window.Btn variant="outline" onClick={onClose}>Cancelar</window.Btn>
          <window.Btn variant="gold" icon="check" disabled={!f.name.trim()} onClick={() => onSave({ name: f.name.trim(), contact: f.contact.trim(), email: f.email.trim(), phone: f.phone.trim(), country: f.country.trim(), port: f.port.trim() })}>{factory ? "Guardar" : "Crear"}</window.Btn>
        </div>
      </div>
    </div>
  );
}

// ---------- PDF de solicitud a proveedor ----------

function _sanitize(s) {
  return String(s || "").replace(/[\\/:*?"<>|]/g, "").replace(/\s+/g, " ").trim();
}

async function buildRfqPdf(rfq, lang, settings) {
  if (!window.jspdf) throw new Error("La librería jsPDF aún no cargó. Intenta de nuevo.");
  const { jsPDF } = window.jspdf;
  const items = rfq.items || [];
  const log = rfq.logistics || {};
  const t = RFQ_LANGS[lang] || RFQ_LANGS["es"];
  const sanitize = _sanitize;

  // Pre-calculate total content height so we can create a single page of the right size
  const logValues = [
    log.shipping_method, log.incoterm, log.port_of_origin, log.production_lead_time,
    log.total_quantity, log.hs_code, log.net_weight, log.gross_weight,
    log.dimensions, log.packaging_type,
  ];
  const itemsBlockH = 6 + 7 + (items.length === 0 ? 8 : items.length * 9) + 8 + 5;
  const logBlockH   = 6 + 6 + (t.logLabels.length * 8) + 6;
  const notesBlockH = rfq.notes
    ? 6 + Math.max(12, Math.ceil(rfq.notes.length / 55) * 4.5 + 6) + 8
    : 0;
  const totalContentH = 18 + 24 + 33 + itemsBlockH + logBlockH + notesBlockH + 16;
  const pageH = Math.max(297, Math.ceil(totalContentH));

  const doc = new jsPDF({ unit: "mm", format: [210, pageH], orientation: "portrait" });
  const fn = sanitize(rfq.rfq_number || "RFQ") + " - " + sanitize(rfq.factory_name || "Proveedor") + (rfq.project_ref ? " - " + sanitize(rfq.project_ref) : "") + ".pdf";

  const L = 15, RR = 195, W = 180;
  let y = 18;
  let currentPage = 0;
  const fieldSpecs = [];

  const addField = (name, fx, fy, fw, fh, value) => {
    fieldSpecs.push({ name, x: fx, y: fy, w: fw, h: fh, page: currentPage, value: value || "" });
  };

  let logoDataUrl = null, logoW = 45, logoH = 16;
  try {
    const resp = await fetch("cotizador/assets/logo-lockup-black.png");
    const blob = await resp.blob();
    const rawUrl = await new Promise((res) => { const r = new FileReader(); r.onloadend = () => res(r.result); r.readAsDataURL(blob); });
    await new Promise((res) => {
      const img = new Image();
      img.onload = () => {
        const ratio = img.naturalWidth / img.naturalHeight;
        logoH = 16;
        logoW = Math.round(logoH * ratio * 10) / 10;
        const PY = 600, PX = Math.round(PY * ratio);
        const cv = document.createElement("canvas");
        cv.width = PX; cv.height = PY;
        const ctx = cv.getContext("2d");
        ctx.fillStyle = "#ffffff";
        ctx.fillRect(0, 0, PX, PY);
        ctx.drawImage(img, 0, 0, PX, PY);
        logoDataUrl = cv.toDataURL("image/png");
        res();
      };
      img.onerror = res;
      img.src = rawUrl;
    });
  } catch(e) { /* fallback to text */ }

  const headerH = 20;
  if (logoDataUrl) {
    doc.addImage(logoDataUrl, "PNG", L, y + (headerH - logoH) / 2, logoW, logoH);
  } else {
    doc.setFontSize(11); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
    doc.text("INside Elementos Arquitectónicos", L, y + headerH / 2 + 2);
  }
  doc.setFontSize(14); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
  doc.text(t.docTitle, RR, y + headerH / 2, { align: "right" });
  doc.setFontSize(7); doc.setFont("helvetica", "normal"); doc.setTextColor(122,125,130);
  const addr = [settings.company_address, settings.company_phone].filter(Boolean).join(" · ");
  if (addr) doc.text(addr, RR, y + headerH / 2 + 5, { align: "right" });
  y += headerH + 4;

  const lw = 42, vw = 48, mRH = 7;
  const dateStr = rfq.date ? rfq.date.split("-").reverse().join("/") : new Date().toLocaleDateString("es-PA");
  const metaRows = [
    [t.rfqNum, rfq.rfq_number, t.date, dateStr],
    [t.supplier, rfq.factory_name, t.contact, rfq.factory_contact],
    [t.email, rfq.factory_email, t.replyBy, rfq.need_by],
    [t.project, rfq.project_ref, t.clientRef, rfq.client_ref],
  ];
  metaRows.forEach(([l1, v1, l2, v2]) => {
    [[L, lw, l1, true], [L+lw, vw, v1, false], [L+lw+vw, lw, l2, true], [L+lw+vw+lw, vw, v2, false]].forEach(([x, w, val, hdr]) => {
      doc.setFillColor(...(hdr ? [217,217,217] : [255,255,255]));
      doc.setDrawColor(187, 187, 187);
      doc.rect(x, y, w, mRH, "FD");
      doc.setFontSize(7);
      doc.setFont("helvetica", hdr ? "bold" : "normal");
      doc.setTextColor(22, 24, 27);
      if (val) doc.text(String(val), x + 2, y + 4.5, { maxWidth: w - 4 });
    });
    y += mRH;
  });
  y += 5;

  const sectionBar = (label) => {
    doc.setFillColor(217, 217, 217);
    doc.setDrawColor(187, 187, 187);
    doc.rect(L, y, W, 6, "FD");
    doc.setFontSize(7.5); doc.setFont("helvetica", "bold"); doc.setTextColor(22, 24, 27);
    doc.text(label, L + 2, y + 4);
    y += 6;
  };

  sectionBar(t.products);

  const IC = [
    { label: "#",          w: 7,  align: "center", fill: false },
    { label: t.colProduct, w: 45, fill: false },
    { label: t.colSpecs,   w: 43, fill: false },
    { label: t.colQty,     w: 11, align: "center", fill: false },
    { label: t.colUnit,    w: 14, align: "center", fill: false },
    { label: t.colPrice,   w: 30, fill: true },
    { label: t.colTotal,   w: 30, fill: true },
  ];

  {
    let cx = L;
    IC.forEach(col => {
      if (col.fill) {
        doc.setFillColor(215, 228, 245);
        doc.rect(cx, y, col.w, 7, "F");
      } else {
        doc.setFillColor(217, 217, 217);
        doc.setDrawColor(187, 187, 187);
        doc.rect(cx, y, col.w, 7, "FD");
      }
      doc.setFontSize(6.5); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
      doc.text(col.label, col.align === "center" ? cx + col.w/2 : cx + 2, y + 4.5,
        { align: col.align || "left", maxWidth: col.w - 3 });
      cx += col.w;
    });
    y += 7;
  }

  const priceX = L + 7 + 45 + 43 + 11 + 14;

  items.forEach((it, i) => {
    const RH = 9;
    const even = i % 2 === 0;
    const vals = [String(i+1), it.name||"", it.specs||"", String(it.quantity||""), it.unit||"", "", ""];
    let cx = L;
    vals.forEach((v, ci) => {
      const col = IC[ci];
      if (col.fill) {
        doc.setFillColor(235, 242, 255);
        doc.rect(cx, y, col.w, RH, "F");
      } else {
        doc.setFillColor(...(even ? [255,255,255] : [249,249,249]));
        doc.setDrawColor(221,221,221);
        doc.rect(cx, y, col.w, RH, "FD");
      }
      if (v && !col.fill) {
        doc.setFontSize(7); doc.setFont("helvetica", "normal");
        doc.setTextColor(ci === 0 ? 136 : 22, ci === 0 ? 136 : 24, ci === 0 ? 136 : 27);
        doc.text(v, col.align === "center" ? cx + col.w/2 : cx + 2, y + 5.5,
          { align: col.align||"left", maxWidth: col.w - 3 });
      }
      cx += col.w;
    });
    addField("item_price_" + i, priceX,      y, 30, RH);
    addField("item_total_" + i, priceX + 30, y, 30, RH);
    y += RH;
  });

  if (items.length === 0) {
    doc.setFillColor(255,255,255); doc.setDrawColor(221,221,221);
    doc.rect(L, y, W, 8, "FD");
    doc.setFontSize(7); doc.setFont("helvetica", "italic"); doc.setTextColor(170,170,170);
    doc.text(t.noItems, L + W/2, y+5, { align: "center" });
    y += 8;
  }

  {
    const subH = 8;
    doc.setFillColor(217,217,217); doc.setDrawColor(187,187,187);
    doc.rect(L, y, priceX - L, subH, "FD");
    doc.setFontSize(7.5); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
    doc.text(t.subtotal, priceX - 4, y + 5.5, { align: "right" });
    doc.setFillColor(215,228,245);
    doc.rect(priceX,      y, 30, subH, "F");
    doc.rect(priceX + 30, y, 30, subH, "F");
    addField("subtotal", priceX + 30, y, 30, subH);
    y += subH + 5;
  }

  sectionBar(t.logistics);

  const LCW = [70, 110];
  {
    let cx = L;
    [t.colField, t.colRequest].forEach((h, i) => {
      if (i === 1) {
        doc.setFillColor(215, 228, 245);
        doc.rect(cx, y, LCW[i], 6, "F");
      } else {
        doc.setFillColor(217, 217, 217);
        doc.setDrawColor(187, 187, 187);
        doc.rect(cx, y, LCW[i], 6, "FD");
      }
      doc.setFontSize(7); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
      doc.text(h, cx + 2, y + 4);
      cx += LCW[i];
    });
    y += 6;
  }

  t.logLabels.forEach((label, ri) => {
    const LRH = 8;
    const even = ri % 2 === 0;
    doc.setFillColor(...(even ? [255,255,255] : [249,249,249]));
    doc.setDrawColor(221,221,221);
    doc.rect(L, y, LCW[0], LRH, "FD");
    doc.setFontSize(7); doc.setFont("helvetica", "bold"); doc.setTextColor(22,24,27);
    doc.text(label, L + 2, y + 5, { maxWidth: LCW[0] - 4 });
    doc.setFillColor(235, 242, 255);
    doc.rect(L + LCW[0], y, LCW[1], LRH, "F");
    addField("log_" + ri, L + LCW[0], y, LCW[1], LRH, logValues[ri]);
    y += LRH;
  });
  y += 6;

  if (rfq.notes) {
    sectionBar(t.notes);
    const lines = doc.splitTextToSize(String(rfq.notes), W - 6);
    const noteH = Math.max(12, lines.length * 4.5 + 6);
    doc.setFillColor(255,255,255); doc.setDrawColor(221,221,221);
    doc.rect(L, y, W, noteH, "FD");
    doc.setFontSize(7.5); doc.setFont("helvetica", "normal"); doc.setTextColor(68,68,68);
    doc.text(lines, L + 3, y + 5.5);
    y += noteH + 8;
  }

  const footerY = pageH - 8;
  doc.setDrawColor(224,224,224);
  doc.line(L, footerY, RR, footerY);
  doc.setFontSize(7); doc.setFont("helvetica", "normal"); doc.setTextColor(170,170,170);
  if (settings.tagline) doc.text(settings.tagline, L, footerY + 4);
  if (settings.company_web) doc.text(settings.company_web, RR, footerY + 4, { align: "right" });

  if (window.PDFLib && fieldSpecs.length > 0) {
    const { PDFDocument, rgb } = window.PDFLib;
    const rawBytes = doc.output("arraybuffer");
    const pdfDoc = await PDFDocument.load(rawBytes);
    const pages = pdfDoc.getPages();
    const form = pdfDoc.getForm();
    const pt = (mm) => mm * 2.8346;
    const A4H_PT = pt(pageH);

    fieldSpecs.forEach((f) => {
      const page = pages[Math.min(f.page, pages.length - 1)];
      const tf = form.createTextField(f.name);
      tf.addToPage(page, {
        x: pt(f.x),
        y: A4H_PT - pt(f.y + f.h),
        width: pt(f.w),
        height: pt(f.h),
        borderColor: rgb(0.50, 0.63, 0.85),
        backgroundColor: rgb(0.91, 0.95, 1.0),
        borderWidth: 0.5,
      });
      tf.setFontSize(8);
      if (f.value) tf.setText(String(f.value));
    });

    const finalBytes = await pdfDoc.save();
    return { bytes: finalBytes, filename: fn };
  } else {
    const rawBytes = doc.output("arraybuffer");
    return { bytes: new Uint8Array(rawBytes), filename: fn };
  }
}

const RFQ_LANGS = {
  es: {
    docTitle: "SOLICITUD DE COTIZACIÓN", rfqNum: "N.º SOLICITUD", date: "FECHA",
    supplier: "PROVEEDOR", contact: "CONTACTO", email: "CORREO",
    replyBy: "RESPUESTA ANTES DE", project: "PROYECTO", clientRef: "REFERENCIA CLIENTE",
    products: "PRODUCTOS SOLICITADOS", colProduct: "Producto / Descripción",
    colSpecs: "Especificaciones", colQty: "Cant.", colUnit: "Unidad",
    colPrice: "Precio unitario", colTotal: "Total", subtotal: "SUBTOTAL",
    logistics: "INFORMACIÓN LOGÍSTICA", colField: "Campo", colRequest: "Solicitud",
    notes: "NOTAS", noItems: "Sin ítems",
    logLabels: ["Método de envío","Incoterm","Puerto de origen","Lead time de producción",
      "Total cantidad","Código HS","Peso neto total (kg)","Peso bruto total (kg)",
      "Dimensiones embalaje","Tipo de embalaje"],
  },
  en: {
    docTitle: "REQUEST FOR QUOTATION", rfqNum: "RFQ NUMBER", date: "DATE",
    supplier: "SUPPLIER", contact: "CONTACT", email: "EMAIL",
    replyBy: "REPLY BY", project: "PROJECT", clientRef: "CLIENT REFERENCE",
    products: "REQUESTED PRODUCTS", colProduct: "Product / Description",
    colSpecs: "Specifications", colQty: "Qty.", colUnit: "Unit",
    colPrice: "Unit price", colTotal: "Total", subtotal: "SUBTOTAL",
    logistics: "LOGISTICS INFORMATION", colField: "Field", colRequest: "Request",
    notes: "NOTES", noItems: "No items",
    logLabels: ["Shipping method","Incoterm","Port of origin","Production lead time",
      "Total quantity","HS Code","Net weight total (kg)","Gross weight total (kg)",
      "Packaging dimensions","Packaging type"],
  },
};

function RFQPdf({ rfq, onBack }) {
  const { settings } = React.useContext(window.AppCtx);
  const sheetRef = React.useRef(null);
  const [busy, setBusy] = React.useState(false);
  const [lang, setLang] = React.useState("es");
  const SHEET_W = 794;
  const items = rfq.items || [];
  const log = rfq.logistics || {};
  const t = RFQ_LANGS[lang];


  const download = async () => {
    if (busy) return;
    setBusy(true);
    try {
      const { bytes, filename } = await buildRfqPdf(rfq, lang, settings);
      const blob = new Blob([bytes], { type: "application/pdf" });
      const url = URL.createObjectURL(blob);
      const a = document.createElement("a"); a.href = url; a.download = filename; a.click();
      setTimeout(() => URL.revokeObjectURL(url), 5000);
    } catch (e) {
      console.error("RFQ PDF error:", e);
      alert("Error al generar el PDF: " + e.message);
    }
    setBusy(false);
  };

  const sendRfqEmail = async () => {
    if (busy) return;
    if (!rfq.factory_email) return;
    if (!window.GAuth) { alert("Error: google-auth.js no cargó."); return; }
    setBusy(true);
    try {
      const token = await window.GAuth.ensureToken(settings.google_client_id);
      const { bytes, filename } = await buildRfqPdf(rfq, lang, settings);
      const fill = (tpl) => (tpl || "").replace(/\{\{(\w+)\}\}/g, (_, k) => ({
        contacto: rfq.factory_contact || "Team",
        numero: rfq.rfq_number || "",
        proyecto: rfq.project_ref || "",
        proyecto_linea: rfq.project_ref ? " for project " + rfq.project_ref : "",
        fecha_limite: rfq.need_by ? " before " + rfq.need_by : " at your earliest convenience",
      })[k] || "");
      await Promise.all([
        window.GAuth.createDraftWithPdf({
          token,
          to: rfq.factory_email,
          subject: fill(settings.email_rfq_subject),
          body: fill(settings.email_rfq_body),
          pdfBytes: bytes,
          pdfFilename: filename,
        }),
        window.GAuth.uploadToDrive({
          token,
          folderId: settings.google_drive_folder_id || null,
          folderName: settings.google_drive_folder || "03 HISTORIAL DE COTIZACIONES",
          pdfBytes: bytes,
          pdfFilename: filename,
        }).catch(e => console.warn("Drive upload:", e.message)),
      ]);
    } catch (e) {
      console.error("RFQ send error:", e);
      alert("Error al enviar: " + e.message);
    }
    setBusy(false);
  };

  // ---- HTML preview styles ----
  const TH = { background: "#D9D9D9", fontSize: 8, fontWeight: 700, color: "#16181b",
    padding: "5px 8px", border: "1px solid #bbb", textTransform: "uppercase", letterSpacing: ".04em" };
  const TD = { fontSize: 9, color: "#16181b", padding: "5px 8px", border: "1px solid #ddd", verticalAlign: "top" };
  const LBL = { ...TH, fontWeight: 700, width: 120, whiteSpace: "nowrap" };
  const VAL = { ...TD, minWidth: 130 };
  const FILL = { ...TD, background: "#e8f1ff", borderColor: "#c8d8f0" };
  const THF = { ...TH, background: "#d4e3f7" }; // fillable column header

  const dateStr = rfq.date ? rfq.date.split("-").reverse().join("/") : "";
  const logValues = [
    log.shipping_method, log.incoterm, log.port_of_origin, log.production_lead_time,
    log.total_quantity, log.hs_code, log.net_weight, log.gross_weight,
    log.dimensions, log.packaging_type,
  ];

  return (
    <div style={{ padding: "26px 36px 80px" }}>
      {/* toolbar */}
      <div className="pdf-toolbar no-print">
        <window.Btn variant="outline" icon="chevron" onClick={onBack} style={{ flexDirection: "row-reverse" }}>Volver al editor</window.Btn>
        <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }}>
          <div className="eyebrow">Solicitud de cotización · {rfq.rfq_number}</div>
          {/* Language selector */}
          <div className="seg sm">
            {[["es","Español"],["en","English"]].map(([k,l]) => (
              <button key={k} className={lang === k ? "on" : ""} onClick={() => setLang(k)}>{l}</button>
            ))}
          </div>
        </div>
        <window.Btn variant="gold" icon="download" onClick={download} disabled={busy}>
          {busy ? "Generando…" : "Descargar PDF"}
        </window.Btn>
      </div>

      {/* hoja A4 preview */}
      <div className="a4-wrap">
        <div ref={sheetRef} style={{ width: SHEET_W, background: "#fff", fontFamily: "Arial, sans-serif", boxSizing: "border-box" }}>
          <div style={{ padding: "36px 44px 32px" }}>

            {/* cabecera */}
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: 20 }}>
              <img src="cotizador/assets/logo-lockup-black.png" alt="INside" style={{ height: 54, width: "auto" }} />
              <div style={{ textAlign: "right" }}>
                <div style={{ fontSize: 17, fontWeight: 700, color: "#16181b", letterSpacing: "-.01em" }}>{t.docTitle}</div>
                <div style={{ fontSize: 9, color: "#7a7d82", marginTop: 2 }}>{settings.company_address} · {settings.company_phone}</div>
              </div>
            </div>

            {/* meta */}
            <table style={{ width: "100%", borderCollapse: "collapse", marginBottom: 14 }}>
              <tbody>
                <tr>
                  <td style={LBL}>{t.rfqNum}</td><td style={VAL}>{rfq.rfq_number || ""}</td>
                  <td style={LBL}>{t.date}</td><td style={VAL}>{dateStr}</td>
                </tr>
                <tr>
                  <td style={LBL}>{t.supplier}</td><td style={VAL}>{rfq.factory_name || ""}</td>
                  <td style={LBL}>{t.contact}</td><td style={VAL}>{rfq.factory_contact || ""}</td>
                </tr>
                <tr>
                  <td style={LBL}>{t.email}</td><td style={VAL}>{rfq.factory_email || ""}</td>
                  <td style={LBL}>{t.replyBy}</td><td style={VAL}>{rfq.need_by || ""}</td>
                </tr>
                <tr>
                  <td style={LBL}>{t.project}</td><td style={VAL}>{rfq.project_ref || ""}</td>
                  <td style={LBL}>{t.clientRef}</td><td style={VAL}>{rfq.client_ref || ""}</td>
                </tr>
              </tbody>
            </table>

            {/* ítems */}
            <div style={{ ...TH, padding: "6px 8px", marginBottom: 0, fontSize: 9 }}>{t.products}</div>
            <table className="rfq-pdf-items" style={{ width: "100%", borderCollapse: "collapse", marginBottom: 0 }}>
              <thead>
                <tr>
                  <th style={{ ...TH, width: 26, textAlign: "center" }}>#</th>
                  <th style={{ ...TH, width: "26%" }}>{t.colProduct}</th>
                  <th style={{ ...TH }}>{t.colSpecs}</th>
                  <th style={{ ...TH, width: 50, textAlign: "center" }}>{t.colQty}</th>
                  <th style={{ ...TH, width: 50, textAlign: "center" }}>{t.colUnit}</th>
                  <th style={{ ...THF, width: 88 }}>{t.colPrice}</th>
                  <th style={{ ...THF, width: 88 }}>{t.colTotal}</th>
                </tr>
              </thead>
              <tbody>
                {items.length === 0 && (
                  <tr><td colSpan={7} style={{ ...TD, textAlign: "center", color: "#aaa" }}>{t.noItems}</td></tr>
                )}
                {items.map((it, i) => (
                  <tr key={it.id}>
                    <td style={{ ...TD, textAlign: "center", color: "#888" }}>{i + 1}</td>
                    <td style={{ ...TD, fontWeight: 600 }}>{it.name}</td>
                    <td style={{ ...TD, color: "#444" }}>{it.specs}</td>
                    <td style={{ ...TD, textAlign: "center" }}>{it.quantity}</td>
                    <td style={{ ...TD, textAlign: "center", color: "#555" }}>{it.unit}</td>
                    <td style={FILL}>&nbsp;</td>
                    <td style={FILL}>&nbsp;</td>
                  </tr>
                ))}
              </tbody>
              <tfoot>
                <tr>
                  <td colSpan={5} style={{ ...TH, textAlign: "right", border: "1px solid #bbb" }}>{t.subtotal}</td>
                  <td style={{ ...THF, border: "1px solid #c8d8f0" }}>&nbsp;</td>
                  <td style={{ ...FILL }}>&nbsp;</td>
                </tr>
              </tfoot>
            </table>
            <div style={{ marginBottom: 16 }} />

            {/* logística — 2 columnas */}
            <div style={{ ...TH, padding: "6px 8px", marginBottom: 0, fontSize: 9 }}>{t.logistics}</div>
            <table style={{ width: "100%", borderCollapse: "collapse", marginBottom: 20 }}>
              <thead>
                <tr>
                  <th style={{ ...TH, width: "37%" }}>{t.colField}</th>
                  <th style={THF}>{t.colRequest}</th>
                </tr>
              </thead>
              <tbody>
                {t.logLabels.map((label, i) => (
                  <tr key={i}>
                    <td style={{ ...LBL, width: "auto", whiteSpace: "normal" }}>{label}</td>
                    <td style={FILL}>{logValues[i] || " "}</td>
                  </tr>
                ))}
              </tbody>
            </table>

            {/* notas */}
            {rfq.notes && (
              <div style={{ marginBottom: 20 }}>
                <div style={{ ...TH, padding: "6px 8px", marginBottom: 0, fontSize: 9 }}>{t.notes}</div>
                <div style={{ fontSize: 8.5, color: "#444", padding: "8px", border: "1px solid #ddd", borderTop: "none", lineHeight: 1.6, whiteSpace: "pre-wrap" }}>{rfq.notes}</div>
              </div>
            )}

            {/* pie */}
            <div style={{ borderTop: "1px solid #e0e0e0", paddingTop: 10, display: "flex", justifyContent: "space-between", alignItems: "center" }}>
              <span style={{ fontSize: 7.5, color: "#aaa" }}>{settings.tagline}</span>
              <span style={{ fontSize: 7.5, color: "#aaa" }}>{settings.company_web}</span>
            </div>

          </div>
        </div>
      </div>
    </div>
  );
}

window.RFQView = RFQView;
