/* ════════════════════════════════════════════════════════════════════
   tab-merge.js — fusion rapide de plusieurs PDF entiers.
   Chaque fichier apparaît comme une ligne (vignette de première page,
   nombre de pages, taille) que l'on glisse pour définir l'ordre final.
   Pour un assemblage page à page, utiliser l'onglet « Organiser ».
   ════════════════════════════════════════════════════════════════════ */
(() => {
  'use strict';
  const { byId, uid, esc, toast, readFile, downloadBlob, formatSize } = Utils;

  const state = {
    /** @type {{id:string,name:string,bytes:Uint8Array,password:string|null,pageCount:number}[]} */
    files: [],
    busy: false,
  };

  const els = {};
  let prog;

  function init() {
    ['drop', 'file', 'workspace', 'list', 'add', 'total', 'reset', 'download', 'progress']
      .forEach((k) => { els[k] = byId(`merge-${k}`); });
    prog = Utils.progress(els.progress);

    Utils.setupDropzone(els.drop, els.file, addFiles);
    els.add.addEventListener('click', () => els.file.click());
    els.reset.addEventListener('click', resetAll);
    els.download.addEventListener('click', merge);

    Sortable.create(els.list, {
      animation: 150,
      ghostClass: 'drag-ghost',
      chosenClass: 'drag-chosen',
      filter: '.row-remove',
      preventOnFilter: false,
      onEnd: syncOrderFromDom,
    });

    App.registerTab('merge', () => state.files.length > 0);
  }

  /* ── Import ────────────────────────────────────────────────────── */
  async function addFiles(files) {
    const pdfs = files.filter(Utils.isPdf);
    if (!pdfs.length) { toast('Déposez des fichiers PDF.', 'error'); return; }
    if (pdfs.length < files.length) toast('Les fichiers qui ne sont pas des PDF ont été ignorés.');

    for (const file of pdfs) {
      try {
        const bytes = await readFile(file);
        // PDF.js sert ici à compter les pages, produire la vignette et,
        // au besoin, demander le mot de passe (conservé pour la fusion).
        const opened = await PdfEngine.openPdfJsInteractive(bytes, file.name);
        if (!opened) { toast(`« ${file.name} » ignoré : mot de passe non fourni.`); continue; }

        const entry = {
          id: uid(),
          name: file.name,
          bytes,
          password: opened.password,
          pageCount: opened.doc.numPages,
        };
        state.files.push(entry);
        const row = rowEl(entry, file.size);
        els.list.appendChild(row);

        // Vignette de première page, puis libération du document PDF.js
        try {
          const canvas = await PdfEngine.renderThumb(opened.doc, 0, 44);
          row.querySelector('.row-thumb').replaceChildren(canvas);
        } catch (_) { /* la vignette reste vide, sans gravité */ }
        opened.doc.destroy();
      } catch (e) {
        console.error(e);
        toast(`« ${file.name} » : ${e.message || 'ouverture impossible.'}`, 'error');
      }
    }
    updateAll();
  }

  function rowEl(entry, sizeBytes) {
    const li = document.createElement('li');
    li.className = 'file-row';
    li.dataset.id = entry.id;
    li.innerHTML =
      `<span class="row-order" aria-hidden="true"></span>` +
      `<span class="row-drag" aria-hidden="true"><svg class="icon"><use href="#i-drag"/></svg></span>` +
      `<span class="row-thumb"><svg class="icon" style="color:var(--line-strong)"><use href="#i-file"/></svg></span>` +
      `<span class="row-body">` +
        `<span class="row-name">${esc(entry.name)}</span>` +
        `<span class="row-meta">${entry.pageCount} page${entry.pageCount > 1 ? 's' : ''} · ${formatSize(sizeBytes)}` +
        `${entry.password !== null ? ' · protégé (mot de passe fourni)' : ''}</span>` +
      `</span>` +
      `<button type="button" class="btn-icon row-remove" aria-label="Retirer ${esc(entry.name)}"><svg class="icon"><use href="#i-x"/></svg></button>`;
    li.querySelector('.row-remove').addEventListener('click', () => removeFile(entry.id));
    return li;
  }

  /* ── Gestion de la liste ───────────────────────────────────────── */
  function removeFile(id) {
    state.files = state.files.filter((f) => f.id !== id);
    const row = els.list.querySelector(`[data-id="${id}"]`);
    if (row) row.remove();
    updateAll();
  }

  function syncOrderFromDom() {
    const order = new Map(
      [...els.list.children].map((el, i) => [el.dataset.id, i]),
    );
    state.files.sort((a, b) => order.get(a.id) - order.get(b.id));
  }

  function updateAll() {
    const empty = state.files.length === 0;
    els.drop.hidden = !empty;
    els.workspace.hidden = empty;
    const totalPages = state.files.reduce((n, f) => n + f.pageCount, 0);
    els.total.textContent = empty ? '' :
      state.files.length < 2
        ? 'Ajoutez au moins un deuxième fichier pour fusionner.'
        : `${state.files.length} fichiers · ${totalPages} pages au total`;
    els.download.disabled = state.busy || state.files.length < 2;
    els.add.disabled = state.busy;
    els.reset.disabled = state.busy;
  }

  function resetAll() {
    if (state.files.length && !confirm('Retirer tous les fichiers de la fusion ?')) return;
    state.files = [];
    els.list.replaceChildren();
    updateAll();
  }

  /* ── Fusion ────────────────────────────────────────────────────── */
  async function merge() {
    if (state.files.length < 2 || state.busy) return;
    state.busy = true;
    updateAll();
    prog.start('Préparation…', true);
    try {
      const out = await PDFLib.PDFDocument.create();
      for (let i = 0; i < state.files.length; i++) {
        const f = state.files[i];
        prog.set(i, state.files.length, `${i + 1} / ${state.files.length} — ${f.name}`);
        const lib = await PdfEngine.openPdfLib(f.bytes, f.password);
        const pages = await out.copyPages(lib, lib.getPageIndices());
        for (const p of pages) out.addPage(p);
      }
      prog.start('Assemblage du fichier…', true);
      const bytes = await out.save();
      downloadBlob(bytes, 'fusion.pdf', 'application/pdf');
      toast(`« fusion.pdf » téléchargé (${out.getPageCount()} pages, ${formatSize(bytes.length)}).`, 'success');
    } catch (e) {
      console.error(e);
      toast(`Échec de la fusion : ${e.message}`, 'error');
    } finally {
      prog.done();
      state.busy = false;
      updateAll();
    }
  }

  document.addEventListener('DOMContentLoaded', init);
})();
