import { PDFDocument } from '@cantoo/pdf-lib';
import { registerFeature } from '../registry';
import { featureModal, pdfSource, footerButtons, deliver, type LoadedFile } from '../common';
import { bufferOf, baseName, parsePageRanges } from '../../core/util';
import { toast } from '../../ui/toast';
import { field, textInput } from '../../ui/controls';
import { h } from '../../core/dom';

registerFeature({
  id: 'extract-pages',
  title: 'Extract pages',
  desc: 'Pull selected pages into a new PDF.',
  icon: 'extract',
  category: 'organize',
  run(ctx) {
    let file: LoadedFile | null = null;
    let total = 0;
    let indices: number[] = [];

    const m = featureModal('Extract pages', 'Pull selected pages into a new PDF — nothing is uploaded.', 'extract', 540);

    const info = h('p.hint', 'Load a PDF to see how many pages it has.');
    const pagesInput = textInput({ placeholder: 'e.g. 1-3, 5', oninput: () => refresh() });
    const pagesField = field('Pages to extract', pagesInput, 'Use ranges and single pages, separated by commas.');
    pagesField.style.display = 'none';

    const refresh = () => {
      indices = total ? parsePageRanges(pagesInput.value, total) : [];
      primary.disabled = indices.length < 1;
    };

    const onChange = async (files: LoadedFile[]) => {
      file = files[0] ?? null;
      total = 0;
      pagesField.style.display = 'none';
      if (!file) { info.textContent = 'Load a PDF to see how many pages it has.'; refresh(); return; }
      try {
        const doc = await PDFDocument.load(bufferOf(file.bytes), { ignoreEncryption: true });
        total = doc.getPageCount();
        info.textContent = `This PDF has ${total} page${total === 1 ? '' : 's'}.`;
        pagesField.style.display = '';
      } catch (e) {
        info.textContent = 'Could not read that PDF — it may be damaged.';
        console.error(e);
      }
      refresh();
    };

    m.body.append(
      pdfSource(ctx, { multiple: false, onChange }),
      info,
      pagesField,
    );

    const { primary } = footerButtons(m, 'Extract & download', async () => {
      if (!file || indices.length < 1) return;
      m.setBusy(true, 'Extracting…');
      try {
        const src = await PDFDocument.load(bufferOf(file.bytes), { ignoreEncryption: true });
        const out = await PDFDocument.create();
        const pages = await out.copyPages(src, indices);
        pages.forEach((p) => out.addPage(p));
        const bytes = await out.save({ useObjectStreams: true });
        const name = baseName(file.name) + '-extracted.pdf';
        m.close();
        deliver(bytes, name);
      } catch (e) {
        m.setBusy(false);
        toast('Extract failed — the file may be damaged.', { type: 'error' });
        console.error(e);
      }
    }, 'extract');
    primary.disabled = true;
  },
});
