import { registerFeature } from '../registry';
import { featureModal, footerButtons, deliver, type LoadedFile } from '../common';
import { repairPdf } from '../../core/qpdf';
import { loadPdf } from '../../core/pdf';
import { baseName, readBytes, formatBytes } from '../../core/util';
import { dropzone } from '../../ui/dropzone';
import { icon } from '../../ui/icons';
import { toast } from '../../ui/toast';
import { h } from '../../core/dom';

registerFeature({
  id: 'repair',
  title: 'Repair PDF',
  desc: 'Rebuild a damaged or unreadable PDF.',
  icon: 'repair',
  category: 'optimize',
  run(ctx) {
    let file: LoadedFile | null = null;
    const m = featureModal('Repair PDF', 'Rebuild a broken file — nothing is uploaded.', 'repair', 560);

    const list = h('div.source-list');
    const renderList = () => {
      list.replaceChildren();
      if (!file) return;
      list.appendChild(
        h('div.source-file',
          h('span.source-file-icon', icon('file', 16)),
          h('span.source-file-name', file.name),
          h('span.source-file-size', formatBytes(file.bytes.length)),
          h('button.source-file-x', {
            title: 'Remove',
            onclick: () => { file = null; renderList(); primary.disabled = true; },
          }, '×'),
        ),
      );
    };

    // Repair is for broken files, so accept any file (don't filter on the PDF magic bytes).
    const dz = dropzone({
      accept: '',
      multiple: false,
      compact: true,
      label: 'Drop the damaged PDF or click to browse',
      hint: 'Even files that won’t open elsewhere are worth a try.',
      onFiles: async (fs) => {
        const f = fs[0];
        if (!f) return;
        const bytes = await readBytes(f);
        if (!bytes.length) { toast(`${f.name} is empty — nothing to repair.`, { type: 'error' }); return; }
        file = { name: f.name, bytes };
        renderList();
        primary.disabled = false;
      },
    });

    // Offer the open editor document as a quick source, if any.
    const current = ctx.currentBytes?.();
    if (current && current.length) {
      m.body.appendChild(
        h('button.source-current', {
          onclick: () => {
            file = { name: ctx.currentName?.() ?? 'document.pdf', bytes: current };
            renderList();
            primary.disabled = false;
          },
        }, icon('file', 16), `Use the open document (${ctx.currentName?.() ?? 'current PDF'})`),
      );
    }

    m.body.append(
      dz,
      list,
      h('p.hint', 'qpdf rebuilds the cross-reference table and stream structure. Truncated or password-protected files may be unrecoverable.'),
    );

    const { primary } = footerButtons(m, 'Repair & download', async () => {
      if (!file) return;
      const src = file;
      const t = toast('Rebuilding the PDF…', { type: 'progress' });
      t.progress(0.15);
      try {
        const res = await repairPdf(src.bytes);
        t.progress(0.7);
        if (!res.ok || !res.output) {
          t.close();
          const summary = (res.log || '').trim().split('\n').slice(0, 3).join(' ').slice(0, 300);
          m.body.appendChild(
            h('p.hint', { style: { color: 'var(--danger)' } },
              summary
                ? `Couldn’t repair this file: ${summary}`
                : 'Couldn’t repair this file.',
            ),
          );
          toast('Repair failed. Truncated or encrypted files may be unrecoverable.', { type: 'error', duration: 6000 });
          return;
        }

        // Verify the rebuilt file actually opens/renders before handing it over.
        try {
          const doc = await loadPdf(res.output);
          void doc.numPages;
        } catch (verifyErr) {
          t.close();
          console.error(verifyErr);
          toast('Rebuilt the structure, but the result still won’t render — this file may be too damaged.', {
            type: 'error',
            duration: 6000,
          });
          return;
        }

        t.progress(1);
        t.close();
        m.close();
        deliver(res.output, baseName(src.name) + '-repaired.pdf');
        toast('Repaired — saved to your device.', { type: 'success' });
      } catch (e) {
        t.close();
        console.error(e);
        toast('Repair failed unexpectedly. The file may be unrecoverable.', { type: 'error', duration: 6000 });
      }
    }, 'repair');
    primary.disabled = true;
  },
});
