/* NGIPL PLM — Print & export view (A4 price list in brand style) */
const { useState, useEffect, useMemo } = React;

/* ---- direct PDF export (no browser print dialog) ---- */
const PDF_LIBS = [
  { global: "html2canvas", src: "https://unpkg.com/html2canvas@1.4.1/dist/html2canvas.min.js" },
  { global: "jspdf", src: "https://unpkg.com/jspdf@2.5.1/dist/jspdf.umd.min.js" },
];
function loadPdfLibs() {
  return Promise.all(PDF_LIBS.map((lib) => new Promise((resolve, reject) => {
    if (window[lib.global]) return resolve();
    const s = document.createElement("script");
    s.src = lib.src;
    s.onload = () => resolve();
    s.onerror = () => reject(new Error("Could not load " + lib.src));
    document.head.appendChild(s);
  })));
}

/* Renders the sheet to a paginated A4 PDF: rows never cut, fixed 9mm/8mm margins, zero bleed. */
async function sheetToPdf(sheetEl, filename) {
  await loadPdfLibs();
  const wrap = document.createElement("div");
  wrap.style.cssText = "position:fixed;left:-10000px;top:0;width:794px;background:#ffffff;";
  const clone = sheetEl.cloneNode(true);
  clone.style.transform = "none";
  wrap.appendChild(clone);
  document.body.appendChild(wrap);
  try {
    if (document.fonts && document.fonts.ready) { try { await document.fonts.ready; } catch (e) {} }
    const canvas = await window.html2canvas(clone, { scale: 2, useCORS: true, backgroundColor: "#ffffff", logging: false });
    const sheetRect = clone.getBoundingClientRect();
    const sheetTop = sheetRect.top;
    const totalH = clone.offsetHeight;
    /* invisible text layer — makes the PDF searchable/selectable */
    const texts = [];
    clone.querySelectorAll("th, td, .sheet-title, .sheet-wef, .sheet-for, .co-block > div, .fnote, .fmark").forEach((el) => {
      const t = (el.innerText || "").trim().replace(/\s+/g, " ");
      if (!t) return;
      const r = el.getBoundingClientRect();
      texts.push({ t, x: r.left - sheetRect.left, y: r.top - sheetTop, h: r.height, fs: parseFloat(getComputedStyle(el).fontSize) || 10 });
    });
    const stops = [];
    clone.querySelectorAll("tbody tr, .sheet-foot").forEach((el) => {
      stops.push(el.getBoundingClientRect().top - sheetTop);
    });
    stops.push(totalH);
    const sorted = Array.from(new Set(stops.map((v) => Math.max(0, Math.round(v))))).sort((a, b) => a - b);
    const pageWmm = 210, pageHmm = 297, mSide = 9, mTop = 8, mBot = 10;
    const contentWmm = pageWmm - 2 * mSide;
    const pxPerMm = 794 / contentWmm;
    const usablePx = (pageHmm - mTop - mBot) * pxPerMm;
    const pdf = new window.jspdf.jsPDF({ unit: "mm", format: "a4", compress: true });
    let start = 0, page = 0;
    while (start < totalH - 1) {
      let end = Math.min(start + usablePx, totalH);
      if (end < totalH) {
        const cands = sorted.filter((v) => v > start + usablePx * 0.4 && v <= end);
        if (cands.length) end = cands[cands.length - 1];
      }
      const slice = end - start;
      const c2 = document.createElement("canvas");
      c2.width = canvas.width;
      c2.height = Math.max(1, Math.round(slice * 2));
      const ctx = c2.getContext("2d");
      ctx.fillStyle = "#ffffff";
      ctx.fillRect(0, 0, c2.width, c2.height);
      ctx.drawImage(canvas, 0, Math.round(start * 2), canvas.width, c2.height, 0, 0, canvas.width, c2.height);
      if (page > 0) pdf.addPage();
      pdf.addImage(c2.toDataURL("image/jpeg", 0.95), "JPEG", mSide, mTop, contentWmm, slice / pxPerMm);
      const s = start, e = end;
      pdf.setTextColor(0, 0, 0);
      texts.forEach((o) => {
        if (o.y < s - 0.5 || o.y + o.h > e + 1) return;
        pdf.setFontSize((o.fs / pxPerMm) * 2.8346);
        pdf.text(o.t, mSide + o.x / pxPerMm, mTop + (o.y - s + o.h * 0.78) / pxPerMm, { renderingMode: "invisible" });
      });
      page++;
      start = end;
    }
    pdf.save(filename);
    return page;
  } finally {
    wrap.remove();
  }
}

function PrintView({ source, onSource, headerStyle, onHeaderStyle, nav }) {
  const state = PLM.useStore();
  const isQuote = source.indexOf("quote:") === 0;
  const quote = isQuote ? PLM.quoteById(source.slice(6)) : null;
  const party = !isQuote && source !== "general" ? PLM.partyById(source) : null;
  const entity = PLM.entityById(quote ? quote.entityId : party ? party.entityId : state.settings.defaultEntityId);
  const deskRef = React.useRef(null);
  const wrapRef = React.useRef(null);
  const [fit, setFit] = useState({ scale: 1, h: 0, pages: 1 });

  useEffect(() => {
    function measure() {
      const desk = deskRef.current, wrap = wrapRef.current;
      if (!desk || !wrap || !wrap.firstChild) return;
      const sheet = wrap.firstChild;
      const avail = desk.clientWidth - 56;
      const scale = Math.min(1, avail / 794);
      const h = sheet.offsetHeight;
      const pages = Math.max(1, Math.ceil(h / 1045));
      setFit((f) => (Math.abs(f.scale - scale) > 0.005 || Math.abs(f.h - h) > 2 || f.pages !== pages) ? { scale, h, pages } : f);
    }
    const raf = requestAnimationFrame(measure);
    window.addEventListener("resize", measure);
    return () => { cancelAnimationFrame(raf); window.removeEventListener("resize", measure); };
  });

  const docLabel = quote
    ? quote.ref + (quote.customer ? " — " + quote.customer : "")
    : party ? "Price list — " + party.name : "General price list";
  const [pdfBusy, setPdfBusy] = useState(false);

  async function onDownloadPdf() {
    if (pdfBusy) return;
    const sheet = wrapRef.current ? wrapRef.current.querySelector(".sheet") : null;
    if (!sheet) return;
    setPdfBusy(true);
    try {
      const base = (quote ? quote.ref : party ? "Price List - " + party.name : "NGIPL Price List")
        .replace(/[\\/:*?"<>|]/g, "-");
      const name = base + (quote ? "" : " WEF " + state.settings.wef) + ".pdf";
      await sheetToPdf(sheet, name);
      PLM.logPrint("Downloaded PDF — " + docLabel + (quote ? "" : " (W.E.F. " + state.settings.wef + ")"));
    } catch (err) {
      console.error(err);
      window.alert("PDF export failed: " + err.message + "\nUse Print / Save PDF instead.");
    }
    setPdfBusy(false);
  }

  return (
    <div data-screen-label="Print &amp; Export">
      <div className="print-controls">
        <div className="toolbar" style={{ marginBottom: 12 }}>
          <Field label="Document">
            <select className="f-select" style={{ width: 320 }} value={source} onChange={(e) => onSource(e.target.value)}>
              <optgroup label="Price lists">
                <option value="general">General price list (master)</option>
                {state.parties.map((pa) => <option key={pa.id} value={pa.id}>{pa.name}</option>)}
              </optgroup>
              {state.quotes.length ? (
                <optgroup label="Quotations">
                  {state.quotes.map((q) => (
                    <option key={q.id} value={"quote:" + q.id}>{q.ref}{q.customer ? " — " + q.customer : ""}</option>
                  ))}
                </optgroup>
              ) : null}
            </select>
          </Field>
          <Field label="Letterhead">
            <Seg options={[{ value: "charcoal", label: "Charcoal" }, { value: "minimal", label: "Minimal" }]}
              value={headerStyle} onChange={onHeaderStyle}></Seg>
          </Field>
          <div className="spacer"></div>
          <span className="caption tnum" style={{ whiteSpace: "nowrap" }}>A4 · ≈ {fit.pages} page{fit.pages === 1 ? "" : "s"}</span>
          <Btn variant="ghost" onClick={onDownloadPdf} disabled={pdfBusy}><IDownload size={14}></IDownload> {pdfBusy ? "Preparing…" : "Download PDF"}</Btn>
          <Btn title="In the print dialog use: Margins — Default · Scale — 100% · Background graphics — ON" onClick={() => {
            PLM.logPrint("Printed " + docLabel + (quote ? "" : " (W.E.F. " + state.settings.wef + ")"));
            window.print();
          }}><IPrinter size={14}></IPrinter> Print</Btn>
        </div>

        {quote ? (
          <div className="print-opts panel">
            <span className="caption">Quotation contents and rates are edited under the Quotations tab.</span>
            <div className="spacer"></div>
            <Btn variant="ghost" size="sm" onClick={() => nav.goTab("quotes")}>Open Quotations</Btn>
          </div>
        ) : (
          <div className="print-opts panel">
            {party ? (
              <span className="caption" style={{ alignSelf: "center" }}>
                Billed by <strong>{entity.short}</strong> — set under Party Rates
              </span>
            ) : (
              <Field label="Billing entity">
                <select className="f-select" style={{ width: 300, height: 34, fontSize: 12.5 }} value={state.settings.defaultEntityId}
                  onChange={(e) => PLM.setSettings({ defaultEntityId: e.target.value })}>
                  {state.entities.map((en) => <option key={en.id} value={en.id}>{en.name}</option>)}
                </select>
              </Field>
            )}
            <Field label="Effective date (W.E.F.)">
              <WefField value={state.settings.wef} btnStyle={{ width: 180, height: 34, fontSize: 12.5 }} onChange={(v) => PLM.setWef(v)}></WefField>
            </Field>
            <Field label="Footer note" style={{ flex: 1 }}>
              <input className="f-input" style={{ height: 34, fontSize: 12.5 }} value={state.settings.priceNote}
                onChange={(e) => PLM.setSettings({ priceNote: e.target.value })} />
            </Field>
          </div>
        )}
      </div>

      <div className="print-desk" ref={deskRef}>
        <div className="desk-doclabel">{docLabel}</div>
        <div className="sheet-scale" ref={wrapRef}
          style={{ transform: "scale(" + fit.scale + ")", height: fit.h ? fit.h * fit.scale : "auto" }}>
          <PriceSheet party={party} quote={quote} entity={entity} headerStyle={headerStyle}></PriceSheet>
        </div>
      </div>
    </div>
  );
}

/* Rows for general list: master grouped; party: partyGrouped; quote: by category */
function sheetRows(state, party, quote) {
  const rows = [];
  if (quote) {
    const pb = PLM.productsById();
    const nm = PLM.numberMap();
    const sorted = quote.items.slice().sort((a, b) => {
      const an = a.productId && nm[a.productId] ? nm[a.productId] : 9999;
      const bn = b.productId && nm[b.productId] ? nm[b.productId] : 9999;
      return an - bn;
    });
    const byCat = {};
    sorted.forEach((it) => {
      const p = pb[it.productId];
      const catId = p ? p.categoryId : "cat-other";
      (byCat[catId] = byCat[catId] || []).push(it);
    });
    state.categories.forEach((c) => {
      if (!byCat[c.id]) return;
      rows.push({ kind: "cat", cat: c });
      byCat[c.id].forEach((it) => {
        const p = pb[it.productId];
        rows.push({
          kind: "item", name: p ? p.name : "—", note: p ? p.note : "",
          rate: it.rate, unit: it.unit, pack: it.packSize, gst: it.gst,
        });
      });
    });
    return rows;
  }
  if (!party) {
    PLM.groupedProducts().forEach((band) => {
      rows.push({ kind: "cat", cat: band.cat });
      band.groups.forEach((g) => {
        if (g.sub) rows.push({ kind: "sub", name: g.sub.name });
        g.items.forEach((p) => rows.push({
          kind: "item", name: p.name, note: p.note,
          rate: p.rate, unit: p.unit, pack: p.packSize, gst: p.gst,
        }));
      });
    });
  } else {
    const pb = PLM.productsById();
    PLM.partyGrouped(party).forEach((band) => {
      rows.push({ kind: "cat", cat: band.cat });
      band.items.forEach((it) => {
        const p = it.productId ? pb[it.productId] : null;
        rows.push({
          kind: "item",
          name: p ? (it.displayName || p.name) : it.customName,
          note: p ? p.note : "",
          rate: it.rate,
          unit: it.unit !== null && it.unit !== undefined && it.unit !== "" ? it.unit : (p ? p.unit : ""),
          pack: it.packSize !== null && it.packSize !== undefined ? it.packSize : (p ? p.packSize : null),
          gst: it.gst !== null && it.gst !== undefined ? it.gst : (p ? p.gst : null),
        });
      });
    });
  }
  return rows;
}

function PriceSheet({ party, quote, entity, headerStyle }) {
  const state = PLM.useStore();
  const rows = sheetRows(state, party, quote);
  let no = 0;
  return (
    <div className="sheet" data-screen-label="A4 Price List Sheet">
      {headerStyle === "charcoal" ? (
        <div className="sheet-band" style={{ position: "relative" }}>
          <svg className="band-fill" aria-hidden="true" focusable="false" preserveAspectRatio="none"
            style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", display: "block", zIndex: 0 }}>
            <rect width="100%" height="100%" fill="#222021"></rect>
          </svg>
          <img src="assets/logos/lockup-stacked-white-cropped.png" alt="Nathurmal Global Industries Pvt. Ltd."
            style={{ position: "relative", zIndex: 1 }} />
          <div className="co-block" style={{ position: "relative", zIndex: 1 }}>
            <div className="co-name">{entity.name}</div>
            <div>{entity.address}</div>
            <div>CIN {entity.cin} · FSSAI {entity.fssai}</div>
            <div>GST {entity.gst} · UDYAM {entity.udyam}</div>
            <div>{entity.phone} · {entity.email}</div>
          </div>
        </div>
      ) : (
        <React.Fragment>
          <div className="sheet-min-head">
            <img src="assets/logos/lockup-stacked-black-cropped.png" alt="Nathurmal Global Industries Pvt. Ltd." />
            <div className="co-block">
              <div className="co-name">{entity.name}</div>
              <div>{entity.address}</div>
              <div>CIN {entity.cin} · FSSAI {entity.fssai}</div>
              <div>GST {entity.gst} · UDYAM {entity.udyam}</div>
              <div>{entity.phone} · {entity.email}</div>
            </div>
          </div>
          <div className="sheet-rule"></div>
        </React.Fragment>
      )}

      <div className="sheet-titlerow">
        <div className="sheet-title">{quote ? "Quotation" : "Price List"}</div>
        <div className={quote ? "sheet-wef" : "sheet-wef sheet-wef--big"}>{quote ? "Date — " + quote.date : "W.E.F. " + state.settings.wef}</div>
      </div>
      {quote || party ? (
        <div className="sheet-subrow">
          <div className="sheet-for">
            {quote
              ? "Prepared for " + (quote.customer.trim() || "—")
              : "Prepared for " + party.name}
          </div>
          {quote ? (
            <div className="sheet-for" style={{ color: "var(--gray-500)" }}>Ref {quote.ref}</div>
          ) : null}
        </div>
      ) : (
        <div style={{ height: 8 }}></div>
      )}

      <div className="pt">
        <table>
          <thead>
            <tr>
              <th style={{ width: 26 }}>#</th>
              <th>Item</th>
              <th className="num" style={{ width: 58 }}>Rate ₹</th>
              <th style={{ width: 56 }}>Unit</th>
              <th className="num" style={{ width: 62 }}>Pack size</th>
              <th className="num" style={{ width: 36 }}>GST</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((r, i) => {
              if (r.kind === "cat") {
                return (
                  <tr className="s-cat" key={"c" + i}>
                    <td colSpan={6}>
                      <span className="cat-cell">
                        <CatIcon catId={r.cat.id} size={16}></CatIcon>
                        <span>{r.cat.name}</span>
                      </span>
                    </td>
                  </tr>
                );
              }
              if (r.kind === "sub") {
                return <tr className="s-sub" key={"s" + i}><td colSpan={6}>{r.name}</td></tr>;
              }
              no++;
              return (
                <tr key={"i" + i}>
                  <td className="s-no num">{no}</td>
                  <td>
                    {r.name}
                    {r.note ? <span className="s-note">— {r.note}</span> : null}
                  </td>
                  <td className="num s-rate tnum">{PLM.fmtRate(r.rate)}</td>
                  <td>{r.unit}</td>
                  <td className="num tnum">{PLM.fmtPack(r.pack)}</td>
                  <td className="num tnum">{PLM.fmtGst(r.gst).replace("%", "")}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      <div className="sheet-foot">
        <div className="fnote">
          {state.settings.priceNote}
          {quote && quote.note ? <div>{quote.note}</div> : null}
        </div>
        <div className="fmark">{quote ? "E. & O. E." : "Prices subject to change"}</div>
      </div>
      <div style={{ height: 12 }}></div>
    </div>
  );
}

Object.assign(window, { PrintView, PriceSheet });
