import { registerFeature } from '../registry';
import { featureModal, pdfSource, footerButtons, type LoadedFile } from '../common';
import { loadPdf, getPageText } from '../../core/pdf';
import { download, baseName } from '../../core/util';
import { toast, celebrateExport } from '../../ui/toast';
import { field, segmented } from '../../ui/controls';
import { h } from '../../core/dom';

registerFeature({
  id: 'pdf-to-text',
  title: 'PDF to text',
  desc: 'Extract the text as plain text or Markdown.',
  icon: 'convert',
  category: 'convert-out',
  run(ctx) {
    let file: LoadedFile | null = null;
    let format: 'txt' | 'md' = 'txt';

    const m = featureModal('PDF to text', 'Extract the text layer — nothing is uploaded.', 'convert', 540);

    m.body.append(
      pdfSource(ctx, { multiple: false, onChange: (f) => { file = f[0] ?? null; primary.disabled = !file; } }),
      field(
        'Output format',
        segmented({
          options: [
            { value: 'txt', label: 'Plain text' },
            { value: 'md', label: 'Markdown' },
          ],
          value: format,
          onchange: (v) => { format = v as 'txt' | 'md'; },
        }),
      ),
      h('p.hint', 'Scanned PDFs with no text layer will come out empty — try the OCR tool first to make them searchable.'),
    );

    const { primary } = footerButtons(m, 'Extract & download', async () => {
      if (!file) return;
      const src = file;
      const isMd = format === 'md';
      const t = toast('Loading PDF…', { type: 'progress' });
      try {
        const doc = await loadPdf(src.bytes);
        const total = doc.numPages;
        const parts: string[] = [];
        for (let i = 0; i < total; i++) {
          t.update(`Extracting text — page ${i + 1} of ${total}…`);
          t.progress((i + 1) / total);
          const page = await doc.getPage(i + 1);
          const text = await getPageText(page);
          if (isMd) {
            parts.push(`## Page ${i + 1}\n\n${text}`);
          } else {
            parts.push(text);
          }
        }
        const out = isMd
          ? parts.join('\n\n')
          : parts
              .map((text, i) => (i === 0 ? text : `----- Page ${i + 1} -----\n\n${text}`))
              .join('\n\n');
        const encoder = new TextEncoder();
        const bytes = encoder.encode(out);
        const filename = baseName(src.name) + (isMd ? '.md' : '.txt');
        t.close();
        m.close();
        download(bytes, filename, isMd ? 'text/markdown' : 'text/plain');
        celebrateExport(filename);
      } catch (e) {
        t.close();
        toast('Text extraction failed — the file may be damaged or encrypted.', { type: 'error' });
        console.error(e);
      }
    }, 'download');
    primary.disabled = true;
  },
});
