const { useState, useMemo, useRef, useEffect } = React;

// ---------- Inputs ----------
function NumberField({ label, value, onChange, suffix, prefix, hint, step = 1, min = 0, error }) {
  return (
    <label className={"field " + (error ? "field--error" : "")}>
      <span className="field__label">{label}</span>
      <div className="field__row">
        {prefix && <span className="field__prefix">{prefix}</span>}
        <input
          type="number"
          inputMode="decimal"
          value={value}
          step={step}
          min={min}
          onChange={(e) => onChange(e.target.value)}
        />
        {suffix && <span className="field__suffix">{suffix}</span>}
      </div>
      {hint && <span className="field__hint">{hint}</span>}
    </label>
  );
}

// Slider compacto para porcentajes (0-100)
function PctRow({ label, value, onChange, derivedAmount, accent }) {
  const { fmtMXN } = window.CalcLogic;
  return (
    <div className="pctrow">
      <div className="pctrow__head">
        <span className="pctrow__label">{label}</span>
        <span className="pctrow__amount">{fmtMXN(derivedAmount)}</span>
      </div>
      <div className="pctrow__controls">
        <input
          type="range"
          min="0"
          max="100"
          step="0.5"
          value={value}
          onChange={(e) => onChange(+e.target.value)}
          className="pctrow__slider"
          style={accent ? { "--track": accent } : undefined}
        />
        <div className="pctrow__inputwrap">
          <input
            type="number"
            value={value}
            step="0.5"
            min="0"
            max="100"
            onChange={(e) => onChange(+e.target.value)}
            className="pctrow__input"
          />
          <span className="pctrow__pct">%</span>
        </div>
      </div>
    </div>
  );
}

// ---------- KPI cards ----------
function KPI({ label, sublabel, value, sub, tone = "neutral", big = false }) {
  return (
    <div className={"kpi kpi--" + tone + (big ? " kpi--big" : "")}>
      <div className="kpi__label">{label}</div>
      {sublabel && <div className="kpi__sublabel">{sublabel}</div>}
      <div className="kpi__value">{value}</div>
      {sub && <div className="kpi__sub">{sub}</div>}
    </div>
  );
}

// ---------- Donut de distribución ----------
function DistributionDonut({ enganche, mensualidades, entrega, precio }) {
  const { fmtPct } = window.CalcLogic;
  const total = enganche + mensualidades + entrega || 1;
  const segs = [
    { v: enganche, color: "#2B6CB0", label: "Enganche" },
    { v: mensualidades, color: "#2F855A", label: "Mensualidades" },
    { v: entrega, color: "#C05621", label: "Contra entrega" },
  ];
  const r = 56, c = 70;
  let acc = 0;
  const circ = 2 * Math.PI * r;

  return (
    <div className="donut">
      <svg viewBox="0 0 140 140" className="donut__svg">
        <circle cx={c} cy={c} r={r} fill="none" stroke="var(--line)" strokeWidth="14" />
        {segs.map((s, i) => {
          const frac = s.v / total;
          const dash = frac * circ;
          const offset = -acc * circ;
          acc += frac;
          return (
            <circle key={i}
              cx={c} cy={c} r={r}
              fill="none"
              stroke={s.color}
              strokeWidth="14"
              strokeDasharray={`${dash} ${circ - dash}`}
              strokeDashoffset={offset}
              transform={`rotate(-90 ${c} ${c})`}
            />
          );
        })}
      </svg>
      <div className="donut__legend">
        {segs.map((s, i) => (
          <div key={i} className="donut__row">
            <span className="donut__sw" style={{ background: s.color }}></span>
            <span className="donut__lab">{s.label}</span>
            <span className="donut__val">{fmtPct(precio > 0 ? (s.v / precio) * 100 : 0, 1)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ---------- Inline styles (production-safe; do not depend on styles.css) ----------
// These rules are injected directly into <head> by the component, so they ship
// with the JS bundle and survive when the component is mounted in production
// without the external stylesheet.
const INLINE_STYLES = `
/* === KPI hover animations (Proyección a 10 años) === */
.kpis--4 .kpi {
  transition:
    transform 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    box-shadow 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    border-color 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    background-color 380ms cubic-bezier(0.2, 0.8, 0.2, 1);
  border: 1px solid var(--line, #e5e1d8);
  will-change: transform;
  cursor: default;
}
.kpis--4 .kpi:hover {
  transform: translateY(-2px) scale(1.015);
  box-shadow:
    0 1px 2px rgba(20, 16, 10, 0.04),
    0 18px 40px -18px rgba(20, 16, 10, 0.18),
    0 8px 16px -12px rgba(20, 16, 10, 0.10);
  border-color: var(--accent, #8a6a3a);
  background: var(--bg, #fbfaf7);
}
.kpis--4 .kpi:hover .kpi__value { color: var(--accent, #8a6a3a); }
.kpis--4 .kpi--accent:hover .kpi__value   { color: var(--accent, #8a6a3a); }
.kpis--4 .kpi--positive:hover .kpi__value { color: var(--pos, #2f7a4f); }
.kpis--4 .kpi--negative:hover .kpi__value { color: var(--neg, #b04545); }

@media (prefers-reduced-motion: reduce) {
  .kpis--4 .kpi { transition: none; }
  .kpis--4 .kpi:hover { transform: none; }
}

/* === PDF download button === */
.pdf-btn-wrap {
  display: flex;
  justify-content: center;
  margin: 24px 32px 8px;
}
.pdf-btn {
  appearance: none;
  border: 1px solid var(--line, #e5e1d8);
  background: var(--bg-elev, #fff);
  color: var(--ink, #1a1612);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 11px 22px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  transition:
    transform 200ms cubic-bezier(0.2, 0.8, 0.2, 1),
    background-color 200ms,
    border-color 200ms,
    color 200ms,
    box-shadow 200ms;
  box-shadow: 0 1px 2px rgba(20, 16, 10, 0.04);
}
.pdf-btn:hover {
  background: var(--ink, #1a1612);
  color: var(--bg, #fbfaf7);
  border-color: var(--ink, #1a1612);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px -8px rgba(20, 16, 10, 0.35);
}
.pdf-btn:active { transform: translateY(0); }
.pdf-btn:disabled {
  opacity: 0.6;
  cursor: progress;
  transform: none;
}
.pdf-btn__icon {
  width: 16px; height: 16px;
  stroke: currentColor; fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* === Print styles === */
@media print {
  @page {
    size: Letter;
    margin: 14mm 12mm;
  }
  html, body {
    background: #fff !important;
    color: #000 !important;
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  * {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }
  /* Hide non-report chrome */
  .header__actions,
  .pdf-btn-wrap,
  .balance__fix,
  .panel--inputs,
  .roi-inputs,
  [data-no-print],
  /* Tweaks panel and its host */
  .tweaks-panel,
  .tweaks-fab,
  [class*="tweaks"] {
    display: none !important;
  }
  body > div:last-of-type:empty { display: none !important; }
  .layout {
    display: block !important;
    grid-template-columns: none !important;
    gap: 0 !important;
  }
  .panel--results { box-shadow: none !important; border: none !important; padding: 0 !important; }
  .header {
    border-bottom: 1px solid #999 !important;
    padding: 0 0 10px !important;
    margin-bottom: 14px !important;
    page-break-after: avoid;
  }
  .results__headline,
  .roi-results__headline { page-break-after: avoid; }
  .kpis, .kpis--4 {
    page-break-inside: avoid;
  }
  .kpi {
    border: 1px solid #ccc !important;
    background: #fafaf7 !important;
    box-shadow: none !important;
    transform: none !important;
    page-break-inside: avoid;
  }
  /* Force major sections onto new pages */
  .roi-results { page-break-before: always; }
  .schedule, .chart, .compare, .selfpay, .report {
    page-break-inside: avoid;
    margin-top: 14px !important;
  }
  .schedule__scroll { overflow: visible !important; }
  .schedule__table, .report__table {
    width: 100% !important;
    font-size: 11px !important;
  }
  .disclaimer {
    page-break-inside: avoid;
    margin: 18px 0 0 !important;
  }
  /* Ensure legible base type */
  body, .results__lead, .compare__note, .form__note, .field__hint,
  .kpi__sub, .kpi__sublabel, .roi-inputs__sub {
    font-size: 11px !important;
  }
  .kpi__value { font-size: 22px !important; }
  /* Solid colors instead of OKLCH for old print pipelines */
  .accent { color: #8a6a3a !important; }
}
`;

function InlineStyles() {
  React.useEffect(() => {
    const id = "az-calc-inline-styles";
    if (document.getElementById(id)) return;
    const el = document.createElement("style");
    el.id = id;
    el.textContent = INLINE_STYLES;
    document.head.appendChild(el);
    return () => { /* keep on unmount; safe for SSR/hydration cycles */ };
  }, []);
  return null;
}

// ---------- PDF download (jsPDF + html2canvas via CDN, lazy-loaded) ----------
const PDF_DEPS = {
  html2canvas: "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js",
  jspdf:       "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",
};

function loadScript(src) {
  return new Promise((resolve, reject) => {
    const existing = document.querySelector(`script[data-src="${src}"]`);
    if (existing) {
      if (existing.dataset.loaded === "1") return resolve();
      existing.addEventListener("load", () => resolve());
      existing.addEventListener("error", () => reject(new Error("Failed to load " + src)));
      return;
    }
    const s = document.createElement("script");
    s.src = src;
    s.async = true;
    s.dataset.src = src;
    s.addEventListener("load", () => { s.dataset.loaded = "1"; resolve(); });
    s.addEventListener("error", () => reject(new Error("Failed to load " + src)));
    document.head.appendChild(s);
  });
}

async function ensurePdfLibs() {
  if (!window.html2canvas) await loadScript(PDF_DEPS.html2canvas);
  if (!(window.jspdf && window.jspdf.jsPDF) && !window.jsPDF) await loadScript(PDF_DEPS.jspdf);
}

async function downloadReportPDF(targetSelector = ".panel--results", filename = "reporte-inversion.pdf") {
  await ensurePdfLibs();
  const target = document.querySelector(targetSelector);
  if (!target) throw new Error("No se encontró el reporte para exportar");

  // Hide elements marked no-print before capture
  const hidden = [];
  document.querySelectorAll(".pdf-btn-wrap, [data-no-print]").forEach((el) => {
    hidden.push([el, el.style.display]);
    el.style.display = "none";
  });

  const canvas = await window.html2canvas(target, {
    scale: 2,
    useCORS: true,
    backgroundColor: "#ffffff",
    windowWidth: target.scrollWidth,
  });

  hidden.forEach(([el, prev]) => { el.style.display = prev; });

  const jsPDFCtor = (window.jspdf && window.jspdf.jsPDF) || window.jsPDF;
  const pdf = new jsPDFCtor({ orientation: "portrait", unit: "pt", format: "letter" });

  const pageW = pdf.internal.pageSize.getWidth();
  const pageH = pdf.internal.pageSize.getHeight();
  const margin = 24;
  const usableW = pageW - margin * 2;

  const imgW = usableW;
  const imgH = (canvas.height * imgW) / canvas.width;

  // Slice the tall canvas into page-sized chunks
  const pageContentH = pageH - margin * 2;
  const pageHeightInCanvas = (pageContentH * canvas.width) / imgW; // px of source per page

  let renderedH = 0;
  let pageIdx = 0;

  while (renderedH < canvas.height) {
    const sliceH = Math.min(pageHeightInCanvas, canvas.height - renderedH);
    const slice = document.createElement("canvas");
    slice.width = canvas.width;
    slice.height = sliceH;
    const ctx = slice.getContext("2d");
    ctx.fillStyle = "#ffffff";
    ctx.fillRect(0, 0, slice.width, slice.height);
    ctx.drawImage(canvas, 0, renderedH, canvas.width, sliceH, 0, 0, canvas.width, sliceH);
    const imgData = slice.toDataURL("image/jpeg", 0.92);
    if (pageIdx > 0) pdf.addPage();
    const sliceImgH = (sliceH * imgW) / canvas.width;
    pdf.addImage(imgData, "JPEG", margin, margin, imgW, sliceImgH, undefined, "FAST");
    renderedH += sliceH;
    pageIdx += 1;
  }

  pdf.save(filename);
}

function PdfDownloadButton({ targetSelector = ".panel--results", filename = "reporte-inversion.pdf", label = "Descargar reporte PDF" }) {
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const onClick = async () => {
    setErr(null);
    setBusy(true);
    try {
      await downloadReportPDF(targetSelector, filename);
    } catch (e) {
      console.error(e);
      setErr("No se pudo generar el PDF. Revisa la consola.");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="pdf-btn-wrap" data-no-print>
      <button className="pdf-btn" onClick={onClick} disabled={busy} type="button">
        <svg className="pdf-btn__icon" viewBox="0 0 24 24" aria-hidden="true">
          <path d="M12 3v12m0 0l-4-4m4 4l4-4" />
          <path d="M5 21h14" />
        </svg>
        {busy ? "Generando PDF…" : label}
      </button>
      {err && <span style={{ marginLeft: 12, color: "var(--neg, #b04545)", fontSize: 12 }}>{err}</span>}
    </div>
  );
}

Object.assign(window, { NumberField, PctRow, KPI, DistributionDonut, InlineStyles, PdfDownloadButton, downloadReportPDF });
