import { registerFeature } from '../registry';
import { featureModal, footerButtons } from '../common';
import { field, select, numberInput } from '../../ui/controls';
import { pickFiles } from '../../ui/dropzone';
import { readBytes } from '../../core/util';
import { celebrateExport, toast } from '../../ui/toast';
import { h } from '../../core/dom';
import { icon } from '../../ui/icons';

const SAMPLE_HTML = `<h1>Hello from YeetPDF</h1>
<p>This HTML was turned into a <strong>real, searchable PDF</strong> — entirely
in your browser. Edit this text, paste your own HTML, or load an .html file,
then click <em>Create PDF</em>.</p>
<ul>
  <li>Selectable, searchable text (not an image)</li>
  <li>Your page size and margins are respected</li>
  <li>Nothing is ever uploaded</li>
</ul>
<p>When the print dialog opens, choose <strong>“Save as PDF”</strong> as the
destination.</p>`;

type PageSize = 'A4' | 'Letter';

/** Escape a string for safe embedding inside a &lt;title&gt; element. */
function escapeText(s: string): string {
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

/** Build a complete, printable HTML document with @page rules for real-text PDF output. */
function buildPrintDoc(bodyHtml: string, size: PageSize, marginMm: number): string {
  const m = Number.isFinite(marginMm) && marginMm >= 0 ? marginMm : 20;
  return `<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>document</title>
<style>
  @page { size: ${size}; margin: ${m}mm; }
  html, body { background: #fff; }
  body {
    margin: 0;
    color: #111;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    font-size: 12pt;
    line-height: 1.5;
  }
  h1 { font-size: 22pt; margin: 0 0 0.5em; }
  h2 { font-size: 17pt; margin: 1em 0 0.4em; }
  h3 { font-size: 14pt; margin: 1em 0 0.4em; }
  p, ul, ol, table { margin: 0 0 0.8em; }
  img { max-width: 100%; }
  table { border-collapse: collapse; }
  th, td { border: 1px solid #999; padding: 4px 8px; text-align: left; }
  a { color: #0b57d0; }
</style>
</head>
<body>
${bodyHtml}
</body>
</html>`;
}

registerFeature({
  id: 'html-to-pdf',
  title: 'HTML to PDF',
  desc: 'Convert HTML into a real, searchable PDF.',
  icon: 'html',
  category: 'convert-in',
  run() {
    const m = featureModal('HTML to PDF', 'Turn HTML into a real, searchable PDF — all in your browser.', 'html', 620);

    let size: PageSize = 'A4';
    let margin = 20;

    const textarea = h('textarea.input', {
      rows: 12,
      spellcheck: false,
      value: SAMPLE_HTML,
    }) as HTMLTextAreaElement;
    textarea.value = SAMPLE_HTML;

    const loadBtn = h(
      'button.btn btn-soft btn-sm',
      {
        onclick: async () => {
          const files = await pickFiles('.html,text/html', false);
          if (!files.length) return;
          try {
            const bytes = await readBytes(files[0]);
            textarea.value = new TextDecoder().decode(bytes);
          } catch (e) {
            toast('Could not read that .html file.', { type: 'error' });
            console.error(e);
          }
        },
      },
      icon('upload', 16),
      'Load .html file',
    );

    const sizeSelect = select({
      options: [
        { value: 'A4', label: 'A4' },
        { value: 'Letter', label: 'Letter' },
      ],
      value: size,
      onchange: (v) => { size = v as PageSize; },
    });

    const marginInput = numberInput({
      value: margin,
      min: 0,
      max: 60,
      step: 1,
      onchange: (v) => { margin = v; },
    });

    m.body.append(
      field('HTML', textarea, 'Paste HTML, edit the sample, or load a file below.'),
      h('div.row', { style: { display: 'flex', gap: '12px', flexWrap: 'wrap', margin: '4px 0 12px' } },
        loadBtn,
      ),
      h('div.row', { style: { display: 'flex', gap: '16px', flexWrap: 'wrap' } },
        field('Page size', sizeSelect),
        field('Margin (mm)', marginInput),
      ),
      h('p.hint',
        'This opens your browser’s print dialog to produce a real PDF with selectable text. ' +
        'Choose “Save as PDF” as the destination, then Save.'),
    );

    footerButtons(m, 'Create PDF', () => {
      const body = textarea.value.trim();
      if (!body) {
        toast('Add some HTML first.', { type: 'error' });
        return;
      }

      const win = window.open('', '_blank');
      if (!win) {
        toast('Your browser blocked the print window. Please allow pop-ups and try again.', { type: 'error' });
        return;
      }

      const doc = buildPrintDoc(body, size, margin);
      win.document.open();
      win.document.write(doc);
      win.document.close();
      win.document.title = escapeText('document');

      // Give the new window a moment to lay out (and load any inline images) before printing.
      const triggerPrint = () => {
        try {
          win.focus();
          win.print();
        } catch (e) {
          console.error(e);
        }
      };
      if (win.document.readyState === 'complete') {
        setTimeout(triggerPrint, 150);
      } else {
        win.addEventListener('load', () => setTimeout(triggerPrint, 150), { once: true });
        // Fallback in case the load event already fired or never fires.
        setTimeout(triggerPrint, 600);
      }

      m.close();
      celebrateExport('document.pdf');
    }, 'html');
  },
});
