// Compress PDF — render each page via pdf.js, re-encode as a JPEG at the chosen
// quality, then assemble a fresh PDF with pdf-lib. This is lossy but drastically
// shrinks image-heavy PDFs (scans, brochures). Text-only PDFs won't benefit much
// and may even grow, so we warn the user when the output is larger.

const COMPRESS_PDF_PDFJS        = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.11.174/build/pdf.min.js';
const COMPRESS_PDF_PDFJS_WORKER = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@3.11.174/build/pdf.worker.min.js';
const COMPRESS_PDF_PDFLIB       = 'https://cdn.jsdelivr.net/npm/pdf-lib@1.17.1/dist/pdf-lib.min.js';

const COMPRESS_PDF_PRESETS = [
  { id: 'high',   label: 'High quality',  quality: 0.85, scale: 2.0, desc: 'Mild compression, preserves detail' },
  { id: 'medium', label: 'Balanced',      quality: 0.70, scale: 1.6, desc: 'Good for most PDFs' },
  { id: 'low',    label: 'Maximum',       quality: 0.55, scale: 1.2, desc: 'Smallest file, visible loss' },
];

window.TOOL_HANDLERS['compress-pdf'] = function CompressPdfTool() {
  const [file, setFile] = React.useState(null);
  const [preset, setPreset] = React.useState('medium');
  const [busy, setBusy] = React.useState(false);
  const [status, setStatus] = React.useState('');
  const [progress, setProgress] = React.useState(0);
  const [outBlob, setOutBlob] = React.useState(null);
  const [outSize, setOutSize] = React.useState(0);
  const [err, setErr] = React.useState('');

  const run = async (f, presetId) => {
    setBusy(true); setErr(''); setOutBlob(null); setOutSize(0); setProgress(0);
    const cfg = COMPRESS_PDF_PRESETS.find((p) => p.id === presetId) || COMPRESS_PDF_PRESETS[1];
    try {
      setStatus('Loading pdf.js…');
      await window.loadScript(COMPRESS_PDF_PDFJS);
      window.pdfjsLib.GlobalWorkerOptions.workerSrc = COMPRESS_PDF_PDFJS_WORKER;

      setStatus('Loading pdf-lib…');
      await window.loadScript(COMPRESS_PDF_PDFLIB);
      const { PDFDocument } = window.PDFLib;

      setStatus('Reading PDF…');
      const bytes = new Uint8Array(await f.arrayBuffer());
      const src = await window.pdfjsLib.getDocument({ data: bytes }).promise;
      const total = src.numPages;

      const out = await PDFDocument.create();
      for (let i = 1; i <= total; i++) {
        setStatus(`Page ${i} / ${total}…`);
        const page = await src.getPage(i);
        const viewport = page.getViewport({ scale: cfg.scale });
        const canvas = document.createElement('canvas');
        canvas.width = Math.floor(viewport.width);
        canvas.height = Math.floor(viewport.height);
        const ctx = canvas.getContext('2d');
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        await page.render({ canvasContext: ctx, viewport }).promise;

        const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/jpeg', cfg.quality));
        const jpegBytes = new Uint8Array(await blob.arrayBuffer());
        const jpeg = await out.embedJpg(jpegBytes);
        // Preserve the page's intrinsic size at 72 DPI so scale doesn't inflate dimensions.
        const pageView = page.getViewport({ scale: 1 });
        const p = out.addPage([pageView.width, pageView.height]);
        p.drawImage(jpeg, { x: 0, y: 0, width: pageView.width, height: pageView.height });
        setProgress(Math.round((i / total) * 100));
      }

      setStatus('Saving…');
      const saved = await out.save({ useObjectStreams: true });
      const blob = new Blob([saved], { type: 'application/pdf' });
      setOutBlob(blob);
      setOutSize(blob.size);
      setStatus('Done');
    } catch (e) {
      setErr(e.message || String(e));
      setStatus('');
    } finally {
      setBusy(false);
    }
  };

  const handleFile = (f) => { setFile(f); run(f, preset); };
  const changePreset = (id) => { setPreset(id); if (file) run(file, id); };
  const download = () => {
    if (!outBlob) return;
    const base = (file?.name || 'document').replace(/\.pdf$/i, '');
    window.downloadBlob(outBlob, base + '-compressed.pdf');
  };
  const reset = () => { setFile(null); setOutBlob(null); setOutSize(0); setErr(''); setStatus(''); setProgress(0); };

  if (!file) return (
    <div>
      <window.Dropzone onFile={handleFile} title="Drop a PDF here" hint="pages are re-encoded as JPEGs to shrink size" accept="application/pdf,.pdf" />
      <div className="cmp-meta" style={{ textAlign: 'center', marginTop: 14 }}>
        Best on image-heavy PDFs (scans, brochures). Text-only PDFs won't compress much.
      </div>
    </div>
  );

  const origSize = file.size;
  const ratio = outSize > 0 ? Math.round(((origSize - outSize) / origSize) * 100) : 0;
  const grew = outSize > origSize;

  return (
    <div className="mini-tool">
      <div className="mini-label">Compression preset</div>
      <div className="filter-row" style={{ marginBottom: 14 }}>
        {COMPRESS_PDF_PRESETS.map((p) => (
          <button
            key={p.id}
            className={`filter-pill ${preset === p.id ? 'active' : ''}`}
            onClick={() => changePreset(p.id)}
            disabled={busy}
            title={p.desc}>
            {p.label}
          </button>
        ))}
      </div>

      <div className="mini-row">
        <div className="mini-field" style={{ flex: 1 }}>
          <label className="mini-label">Original</label>
          <div className="cmp-meta" style={{ fontSize: 16, color: 'var(--id-text)' }}>{window.fmtBytes(origSize)}</div>
        </div>
        <div className="mini-field" style={{ flex: 1 }}>
          <label className="mini-label">Compressed</label>
          <div className="cmp-meta" style={{ fontSize: 16, color: 'var(--id-text)' }}>
            {outSize ? window.fmtBytes(outSize) : '…'}
            {outSize > 0 && (
              <span style={{ marginLeft: 8, color: grew ? '#c8321f' : 'var(--id-brand-blue)', fontWeight: 700 }}>
                {grew ? `+${-ratio}%` : `−${ratio}%`}
              </span>
            )}
          </div>
        </div>
      </div>

      <div className="pw-bar" style={{ marginTop: 12 }}><div className="pw-fill" style={{ width: progress + '%', background: 'var(--id-brand-blue)' }} /></div>
      <div className="cmp-meta" style={{ marginTop: 6 }}>{status}</div>

      {err && <div style={{ marginTop: 10 }}><window.ToolError error={err} onRetry={() => file && run(file, preset)} /></div>}
      {grew && !busy && (
        <div style={{ color: '#b45309', fontSize: 13, marginTop: 10 }}>
          This PDF got bigger — it's probably text-only. Try a lower preset or keep the original.
        </div>
      )}

      <div className="cmp-actions">
        <button className="btn btn-secondary" onClick={reset} disabled={busy}>
          <window.Icon name="upload" size={16} /> Another PDF
        </button>
        <button className="btn btn-primary" onClick={download} disabled={!outBlob || busy}>
          <window.Icon name="download" size={16} /> Download
        </button>
      </div>
    </div>
  );
};
