// ─── print/print-viewer.jsx — visor único de impresión/preview de documentos ───
// Overlay a pantalla completa (lienzo oscuro, barra superior, zoom Ctrl+rueda,
// Esc para cerrar) para TODOS los documentos imprimibles del ERP. Se abre por el
// evento global `micos:print-doc` (detail = { data, mod, title, subtitle, realUrl?,
// realKind? }) para no pasar callbacks por toda la jerarquía. Dos modos, cada uno
// con su lienzo propio: _PVDocCanvas (documento SVG de un doc-*.js vía job.mod) y
// _PVFileCanvas (archivo REAL subido: imagen, o PDF rasterizado con pdf.js).
// Expone: DocumentPrintViewer (montado 1 vez en core/app.jsx — renombrado en P11
// desde el legacy "PresupuestoPrintViewer": es 100% genérico, no solo presupuesto)
// y openPrintDoc(data, opts). Consume: window.MicosDoc* (renderers), window.pdfjsLib,
// IconDownload/IconPrinter/IconX (ui/icons.jsx).
const { useState: _usePV, useEffect: _useEffPV, useRef: _useRefPV } = React;

function _PVBtn({ icon: Icon, label, onClick, size = 18 }) {
  return (
    <button
      type="button"
      onClick={(e) => { onClick && onClick(e); e.currentTarget.blur(); }}
      title={label}
      aria-label={label}
      className="inline-flex items-center justify-center rounded-full cursor-pointer transition-colors"
      style={{ width: 40, height: 40, background: 'transparent', color: 'rgba(255,255,255,0.86)' }}
      onMouseEnter={(e) => { e.currentTarget.style.background = 'rgba(255,255,255,0.12)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
    >
      <Icon size={size} />
    </button>
  );
}

// ── Modo documento SVG propio: monta job.mod.buildSVG(job.data) en un A4 escalado ──
function _PVDocCanvas({ job, scale }) {
  const holderRef = _useRefPV(null);

  // Montar el SVG del documento al abrir (con la fuente cargada para medir bien).
  _useEffPV(() => {
    if (!holderRef.current) return;
    const holder = holderRef.current;
    holder.innerHTML = '';
    const mod = job.mod || window.MicosDocPresupuesto;
    const build = () => {
      if (!mod) return;
      const svg = mod.buildSVG(job.data);
      svg.style.display = 'block';
      svg.style.width = '595px';
      svg.style.height = '842px';
      holder.appendChild(svg);
    };
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(build);
    else build();
  }, [job]);

  return (
    <div className="flex-1 overflow-auto flex justify-center px-4 py-6" style={{ minHeight: 0 }}>
      <div className="animate-scale-in" style={{ width: 595 * scale, height: 842 * scale, flexShrink: 0, alignSelf: 'flex-start' }}>
        <div
          ref={holderRef}
          style={{ width: 595, height: 842, background: '#fff', borderRadius: 2, boxShadow: '0 18px 50px -12px rgba(0,0,0,0.6)', transform: `scale(${scale})`, transformOrigin: 'top left' }}
        />
      </div>
    </div>
  );
}

// ── Modo archivo REAL subido: imagen con zoom, o PDF rasterizado con pdf.js ──
// (el visor nativo de Chrome queda bloqueado dentro del iframe del preview →
// "Chrome bloqueó esta página"; rasterizamos cada página a un <canvas>).
// pdfErr vive en el padre porque también decide si se muestra la barra de zoom.
function _PVFileCanvas({ job, scale, pdfErr, setPdfErr, onDownload }) {
  const pdfHolderRef = _useRefPV(null);
  const scaleRef = _useRefPV(1);
  scaleRef.current = scale;
  const esPdf = job.realKind === 'pdf';

  _useEffPV(() => {
    if (!esPdf || !pdfHolderRef.current) return;
    let cancelled = false;
    let pdfDoc = null;
    const holder = pdfHolderRef.current;
    holder.innerHTML = '';
    setPdfErr(false);
    if (!window.pdfjsLib) { setPdfErr(true); return; }
    const RENDER_SCALE = 2; // resolución del raster; el zoom se aplica por CSS
    window.pdfjsLib.getDocument(job.realUrl).promise.then((pdf) => {
      if (cancelled) return;
      pdfDoc = pdf;
      let seq = Promise.resolve();
      for (let i = 1; i <= pdf.numPages; i++) {
        seq = seq.then(() => pdf.getPage(i)).then((pg) => {
          if (cancelled) return;
          const vp = pg.getViewport({ scale: RENDER_SCALE });
          const baseW = vp.width / RENDER_SCALE;
          const canvas = document.createElement('canvas');
          canvas.width = vp.width; canvas.height = vp.height;
          canvas.style.display = 'block';
          canvas.style.background = '#fff';
          canvas.style.borderRadius = '2px';
          canvas.style.boxShadow = '0 18px 50px -12px rgba(0,0,0,0.6)';
          canvas.style.width = (baseW * scaleRef.current) + 'px';
          canvas.style.height = 'auto';
          canvas.dataset.baseW = String(baseW);
          holder.appendChild(canvas);
          return pg.render({ canvasContext: canvas.getContext('2d'), viewport: vp }).promise;
        });
      }
      return seq;
    }).catch(() => { if (!cancelled) setPdfErr(true); });
    return () => { cancelled = true; if (pdfDoc) { try { pdfDoc.destroy(); } catch (e) {} } };
  }, [job]);

  // Reaplica el zoom a los canvases del PDF sin re-renderizar.
  _useEffPV(() => {
    const holder = pdfHolderRef.current;
    if (!holder) return;
    holder.querySelectorAll('canvas').forEach((c) => {
      const baseW = Number(c.dataset.baseW) || 595;
      c.style.width = (baseW * scale) + 'px';
    });
  }, [scale, job]);

  if (esPdf) {
    if (pdfErr) {
      return (
        <div className="flex-1 flex flex-col items-center justify-center gap-4 px-6 text-center" style={{ minHeight: 0 }}>
          <p className="text-[13.5px] max-w-[42ch]" style={{ color: 'rgba(255,255,255,0.7)' }}>
            No se pudo previsualizar el PDF en el visor. Descargá el archivo para abrirlo.
          </p>
          <button type="button" onClick={onDownload} className="btn btn-primary"><IconDownload size={15} />Descargar PDF</button>
        </div>
      );
    }
    return <div className="flex-1 overflow-auto flex flex-col items-center gap-5 px-4 py-6" style={{ minHeight: 0 }} ref={pdfHolderRef} />;
  }
  return (
    <div className="flex-1 overflow-auto flex items-center justify-center px-4 py-6" style={{ minHeight: 0 }}>
      <img src={job.realUrl} alt={job.title || 'Archivo'} className="animate-scale-in" style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain', transform: scale !== 1 ? `scale(${scale})` : undefined, transformOrigin: 'center', background: '#fff', borderRadius: 2, boxShadow: '0 18px 50px -12px rgba(0,0,0,0.6)' }} />
    </div>
  );
}

function DocumentPrintViewer() {
  const [job, setJob] = _usePV(null);   // { data, mod, title, subtitle, realUrl?, realKind? }
  const [scale, setScale] = _usePV(1);
  const [busy, setBusy] = _usePV(false); // generando PDF
  const [pdfErr, setPdfErr] = _usePV(false); // pdf.js no pudo renderizar
  const userZoomRef = _useRefPV(false);  // true cuando el usuario fijó un zoom manual

  const fitScale = () => {
    const availH = window.innerHeight - 64 - 48;
    const availW = window.innerWidth - 48;
    return Math.max(0.2, Math.min(availW / 595, availH / 842, 1.25));
  };
  const clampScale = (s) => Math.max(0.25, Math.min(s, 5));

  // Abrir/cerrar por evento global
  _useEffPV(() => {
    const onOpen = (e) => setJob(e.detail || null);
    window.addEventListener('micos:print-doc', onOpen);
    return () => window.removeEventListener('micos:print-doc', onOpen);
  }, []);

  // Ajuste inicial + Esc + zoom (Ctrl/⌘ + rueda) + bloquear scroll de fondo
  _useEffPV(() => {
    if (!job) return;
    userZoomRef.current = false;
    setScale(fitScale());
    const onResize = () => { if (!userZoomRef.current) setScale(fitScale()); };
    const onKey = (e) => { if (e.key === 'Escape') setJob(null); };
    const onWheel = (e) => {
      if (!(e.ctrlKey || e.metaKey)) return;
      e.preventDefault();
      userZoomRef.current = true;
      setScale((s) => clampScale(s * (e.deltaY < 0 ? 1.1 : 1 / 1.1)));
    };
    window.addEventListener('resize', onResize);
    window.addEventListener('keydown', onKey);
    window.addEventListener('wheel', onWheel, { passive: false });
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      window.removeEventListener('resize', onResize);
      window.removeEventListener('keydown', onKey);
      window.removeEventListener('wheel', onWheel);
      document.body.style.overflow = prev;
    };
  }, [job]);

  if (!job) return null;

  const zoomIn = () => { userZoomRef.current = true; setScale((s) => clampScale(s * 1.25)); };
  const zoomOut = () => { userZoomRef.current = true; setScale((s) => clampScale(s / 1.25)); };
  const zoomFit = () => { userZoomRef.current = false; setScale(fitScale()); };
  const zoomReset = () => { userZoomRef.current = true; setScale(1); };
  const pvZBtn = { appearance: 'none', border: 0, background: 'transparent', color: '#e9e9ec', font: 'inherit', fontSize: 15, lineHeight: 1, width: 30, height: 30, borderRadius: 7, cursor: 'pointer' };

  const docMod = job.mod || window.MicosDocPresupuesto;
  const esArchivoReal = !!job.realUrl;
  const esPdfReal = esArchivoReal && job.realKind === 'pdf';
  const doPrint = () => { if (!esArchivoReal && docMod) docMod.print(job.data); };
  const doDownloadReal = () => {
    try { const a = document.createElement('a'); a.href = job.realUrl; a.download = job.title || 'archivo'; document.body.appendChild(a); a.click(); a.remove(); } catch (e) {}
  };
  // "Guardar como PDF": descarga directa de un .pdf (rasteriza el documento con
  // la fuente embebida; abre la ventana de “guardar archivo”, sin diálogo de impresión).
  const doSavePdf = () => {
    if (busy || !docMod) return;
    setBusy(true);
    Promise.resolve(docMod.downloadPDF(job.data, (job.title || 'Documento') + '.pdf'))
      .catch(() => {})
      .then(() => setBusy(false));
  };

  return (
    <div className="fixed inset-0 z-50 flex flex-col animate-fade-in" style={{ background: 'rgba(11,12,14,0.97)' }}>
      {/* Barra superior — título a la izquierda; acciones y CERRAR a la derecha
          (consistente con los modales del ERP: se cierra desde la derecha) */}
      <div className="flex items-center gap-2 px-4 flex-shrink-0" style={{ height: 64, color: '#fff', borderBottom: '1px solid rgba(255,255,255,0.10)' }}>
        <div className="min-w-0 flex-1">
          <p className="text-[14px] font-semibold truncate" style={{ color: '#fff' }}>{job.title || 'Presupuesto'}</p>
          <p className="text-[11.5px] truncate" style={{ color: 'rgba(255,255,255,0.55)' }}>{job.subtitle || 'Documento · A4'}</p>
        </div>
        <div className="flex items-center gap-0.5 flex-shrink-0">
          {esArchivoReal ? (
            <_PVBtn icon={IconDownload} label="Descargar" onClick={doDownloadReal} size={19} />
          ) : (
            <>
              <_PVBtn icon={IconPrinter} label="Imprimir" onClick={doPrint} size={18} />
              <_PVBtn icon={IconDownload} label={busy ? 'Generando PDF…' : 'Guardar como PDF'} onClick={doSavePdf} size={19} />
            </>
          )}
        </div>
        <div style={{ width: 1, height: 26, background: 'rgba(255,255,255,0.14)', margin: '0 4px', flexShrink: 0 }} />
        <_PVBtn icon={IconX} label="Cerrar" onClick={() => setJob(null)} size={20} />
      </div>

      {/* Lienzo — un componente por modo (SVG propio vs archivo real) */}
      {esArchivoReal ? (
        <_PVFileCanvas job={job} scale={scale} pdfErr={pdfErr} setPdfErr={setPdfErr} onDownload={doDownloadReal} />
      ) : (
        <_PVDocCanvas job={job} scale={scale} />
      )}

      {/* Barra de zoom (abajo a la derecha) */}
      {!(esPdfReal && pdfErr) && (
      <div style={{ position: 'absolute', right: 16, bottom: 16, zIndex: 10, display: 'flex', alignItems: 'center', gap: 2, padding: 4, background: '#2b2b30', border: '1px solid rgba(255,255,255,.12)', borderRadius: 10, boxShadow: '0 8px 24px rgba(0,0,0,.4)', userSelect: 'none' }}>
        <button onClick={zoomOut} title="Alejar" style={pvZBtn}>&minus;</button>
        <span onClick={zoomReset} title="Restablecer (100%)" style={{ minWidth: 48, textAlign: 'center', fontSize: 12, color: '#e9e9ec', fontVariantNumeric: 'tabular-nums', cursor: 'pointer', padding: '0 4px' }}>{Math.round(scale * 100)}%</span>
        <button onClick={zoomIn} title="Acercar" style={pvZBtn}>+</button>
        <button onClick={zoomFit} title="Ajustar a la ventana" style={{ ...pvZBtn, width: 'auto', padding: '0 10px', fontSize: 12 }}>Ajustar</button>
      </div>
      )}
    </div>
  );
}

// Helper global para abrir el visor desde cualquier pantalla
function openPrintDoc(data, opts) {
  window.dispatchEvent(new CustomEvent('micos:print-doc', { detail: Object.assign({ data }, opts || {}) }));
}

Object.assign(window, { DocumentPrintViewer, openPrintDoc });
