const fileInput = document.getElementById('file');
const formatSel = document.getElementById('format');
const convertBtn = document.getElementById('convert');
const saveBtn = document.getElementById('save');
const resultEl = document.getElementById('result');
const statusEl = document.getElementById('status');

let lastOutput = null;
let lastBaseName = 'output';

const updateSaveState = () => {
  saveBtn.disabled = (lastOutput === null);
};

const enableButtonsFromInput = () => {
  const hasFile = !!(fileInput.files && fileInput.files.length);
  convertBtn.disabled = !hasFile;
  // reset output when selecting a new file
  lastOutput = null;
  updateSaveState();
};

fileInput.addEventListener('change', () => {
  enableButtonsFromInput();
  resultEl.textContent = 'Fichier chargé. Cliquez sur « Convertir ».';
  resultEl.classList.remove('muted');
  status('');
});

formatSel.addEventListener('change', () => {
  // Changing the format should not clear the output; just keep Save enabled if we have something.
  updateSaveState();
});

convertBtn.addEventListener('click', async () => {
  const file = fileInput.files?.[0];
  if (!file) return;

  lastBaseName = (file.name || 'output').replace(/\.[^.]+$/, '');
  convertBtn.disabled = true;
  lastOutput = null;
  updateSaveState();
  resultEl.textContent = '';
  status('Conversion en cours…', 'progress');

  try {
    const ext = (file.name.split('.').pop() || '').toLowerCase();
    let data;
    if (ext === 'pdf') {
      const buf = await file.arrayBuffer();
      data = await extractTextFromPDF(buf);
    } else if (ext === 'eml') {
      const text = await file.text();
      data = extractTextFromEML(text);
    } else {
      throw new Error('Type de fichier non supporté. Sélectionnez un .pdf ou .eml');
    }

    const mode = formatSel.value;
    if (mode === 'json') {
      lastOutput = JSON.stringify(data, null, 2);
    } else {
      if (Array.isArray(data.pages)) {
        lastOutput = data.pages.join('\\n\\n');
      } else if (data.text) {
        lastOutput = data.text;
      } else {
        lastOutput = String(data);
      }
    }

    resultEl.textContent = lastOutput || '';
    status('Terminé.', 'ok');
  } catch (err) {
    console.error(err);
    status('Erreur : ' + (err?.message || String(err)), 'err');
    resultEl.textContent = '—';
    lastOutput = null;
  } finally {
    convertBtn.disabled = false;
    updateSaveState();
  }
});

saveBtn.addEventListener('click', async () => {
  if (lastOutput === null) {
    status('Rien à enregistrer : lancez la conversion.', 'err');
    return;
  }
  const asJson = formatSel.value === 'json';
  const filename = `${lastBaseName}.${asJson ? 'json' : 'txt'}`;
  const mime = asJson ? 'application/json;charset=utf-8' : 'text/plain;charset=utf-8';
  const blob = new Blob([lastOutput], { type: mime });
  const url = URL.createObjectURL(blob);

  try {
    const anyWin = window;
    const dl = (anyWin.browser && anyWin.browser.downloads) || (anyWin.chrome && anyWin.chrome.downloads);
    if (dl && typeof dl.download === 'function') {
      await new Promise((resolve, reject) => {
        if (anyWin.chrome && anyWin.chrome.downloads) {
          anyWin.chrome.downloads.download({ url, filename, saveAs: true }, (id) => {
            if (anyWin.chrome.runtime.lastError) reject(anyWin.chrome.runtime.lastError);
            else resolve(id);
          });
        } else {
          anyWin.browser.downloads.download({ url, filename, saveAs: true }).then(resolve, reject);
        }
      });
      status('Fichier enregistré.', 'ok');
    } else {
      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      document.body.appendChild(a);
      a.click();
      a.remove();
      status('Fichier enregistré (fallback).', 'ok');
    }
  } catch (e) {
    console.error(e);
    status('Erreur enregistrement : ' + (e?.message || String(e)), 'err');
  } finally {
    setTimeout(() => URL.revokeObjectURL(url), 5000);
  }
});

function status(msg, cls) {
  statusEl.className = 'small';
  if (cls) statusEl.classList.add(cls);
  statusEl.textContent = msg || '';
}

// --- PDF text extraction (pagination + line preservation) ---
async function extractTextFromPDF(arrayBuffer) {
  let pdfjsLib;
  try {
    pdfjsLib = await import('./lib/pdfjs/pdf.mjs');
  } catch (e) {
    throw new Error("PDF.js introuvable. Déposez 'pdf.mjs' et 'pdf.worker.mjs' dans lib/pdfjs/");
  }
  pdfjsLib.GlobalWorkerOptions.workerSrc = './lib/pdfjs/pdf.worker.mjs';

  const loadingTask = pdfjsLib.getDocument({ data: arrayBuffer });
  const pdf = await loadingTask.promise;
  const pagesOut = [];

  for (let p = 1; p <= pdf.numPages; p++) {
    const page = await pdf.getPage(p);
    const content = await page.getTextContent();
    const lines = [];
    let currentLine = [];

    const flush = () => {
      if (currentLine.length) {
        lines.push(currentLine.join(' ').replace(/[ \t]{2,}/g, ' ').trim());
        currentLine = [];
      }
    };

    for (const item of content.items) {
      const s = typeof item.str === 'string' ? item.str : '';
      if (!s) continue;
      currentLine.push(s);
      if (item.hasEOL) flush();
    }
    flush();

    const pageHeader = `----------- Page ${p}`;
    const pageText = [pageHeader, ...lines].join('\\n');
    pagesOut.push(pageText);
  }

  return { type: 'pdf', pages: pagesOut, pageCount: pagesOut.length };
}

// --- EML parsing with heading preservation ---
function extractTextFromEML(raw) {
  const sep = /\r?\n\r?\n/;
  const parts = raw.split(sep);
  let headersRaw = '', bodyRaw = '';
  if (parts.length > 1) { headersRaw = parts.shift(); bodyRaw = parts.join('\\n\\n'); } else { bodyRaw = raw; }
  const headers = parseHeaders(headersRaw);
  const subject = headers['subject'] || '';
  const ct = (headers['content-type'] || '').toLowerCase();
  let textBody = ''; let htmlBody = '';

  if (ct.startsWith('multipart/')) {
    const boundaryMatch = ct.match(/boundary="?([^";]+)"?/i);
    const boundary = boundaryMatch ? boundaryMatch[1] : null;
    if (boundary) {
      const segments = bodyRaw.split(new RegExp(`--${escapeRegExp(boundary)}`));
      for (const seg of segments) {
        const s = seg.replace(/^\\r?\\n/, '');
        if (!s.trim() || s.startsWith('--')) continue;
        const [segHeadersRaw, ...segBodyArr] = s.split(sep);
        const segHeaders = parseHeaders(segHeadersRaw || '');
        const segBody = segBodyArr.join('\\n\\n');
        const segCT = (segHeaders['content-type'] || '').toLowerCase();
        const disp = (segHeaders['content-disposition'] || '').toLowerCase();

        if (disp.includes('attachment') || /name=|filename=/.test(segHeaders['content-disposition'] || '')) continue;

        const cte = (segHeaders['content-transfer-encoding'] || '').toLowerCase().trim();
        let payload = segBody.trim();

        if (cte === 'base64') {
          if (segCT.startsWith('text/')) {
            try { payload = decodeBase64ToUtf8(payload.replace(/\\s+/g, '')); } catch (e) { continue; }
          } else { continue; }
        } else if (cte === 'quoted-printable') {
          payload = decodeQuotedPrintable(payload);
        }

        if (segCT.startsWith('text/plain'))      textBody += extractWithCharset(payload, segCT) + '\\n';
        else if (segCT.startsWith('text/html'))  htmlBody  += extractWithCharset(payload, segCT) + '\\n';
      }
    } else {
      textBody = bodyRaw;
    }
  } else {
    const cte = (headers['content-transfer-encoding'] || '').toLowerCase().trim();
    let payload = bodyRaw.trim();
    if (cte === 'base64') {
      if ((headers['content-type'] || '').toLowerCase().startsWith('text/')) {
        try { payload = decodeBase64ToUtf8(payload.replace(/\\s+/g, '')); } catch (e) { payload = ''; }
      } else { payload = ''; }
    } else if (cte === 'quoted-printable') {
      payload = decodeQuotedPrintable(payload);
    }
    if ((headers['content-type'] || '').toLowerCase().startsWith('text/html')) htmlBody = extractWithCharset(payload, headers['content-type'] || '');
    else textBody = extractWithCharset(payload, headers['content-type'] || '');
  }

  let bodyText = textBody || (htmlBody ? htmlToTextWithHeadings(htmlBody) : '');
  bodyText = bodyText.trim();
  const titleLine = subject ? `== ${subject} ==` : '';
  const withTitle = titleLine ? `${titleLine}\\n\\n${bodyText}` : bodyText;
  const firstPage = `----------- Page 1\\n${withTitle}`;
  return { type: 'eml', headers, text: firstPage };
}

function parseHeaders(s) {
  const lines = (s || '').split(/\\r?\\n/);
  const headers = {}; let current = '';
  for (let line of lines) {
    if (/^\\s/.test(line) && current) { headers[current] += ' ' + line.trim(); continue; }
    const idx = line.indexOf(':');
    if (idx > -1) { current = line.slice(0, idx).trim().toLowerCase(); headers[current] = line.slice(idx + 1).trim(); }
  }
  return headers;
}

function htmlToTextWithHeadings(html) {
  let s = html;
  s = s.replace(/<style[\s\S]*?<\/style>/gi, '');
  s = s.replace(/<script[\s\S]*?<\/script>/gi, '');
  s = s.replace(/<!--[\s\S]*?-->/g, '');
  for (let i = 1; i <= 6; i++) {
    const re = new RegExp(`<h${i}[^>]*>([\\s\\S]*?)<\\/h${i}>`, 'gi');
    s = s.replace(re, (_, inner) => `\\n\\n${inner.replace(/<[^>]+>/g, '').trim().toUpperCase()}\\n\\n`);
  }
  s = s.replace(/<p[^>]*>/gi, '\\n');
  s = s.replace(/<br\s*\/?>/gi, '\\n');
  s = s.replace(/<\/?[^>]+>/g, '');
  s = s.replace(/[ \t]{2,}/g, ' ');
  s = s.replace(/\s+\n/g, '\\n');
  s = s.replace(/\n{3,}/g, '\\n\\n');
  return s.trim();
}

function decodeQuotedPrintable(str) {
  let s = str.replace(/=\\r?\\n/g, '');
  s = s.replace(/=([A-Fa-f0-9]{2})/g, (_, h) => String.fromCharCode(parseInt(h, 16)));
  try { return new TextDecoder('utf-8', { fatal: false }).decode(new TextEncoder().encode(s)); } catch { return s; }
}

function decodeBase64ToUtf8(b64) {
  const bin = atob(b64);
  const bytes = Uint8Array.from(bin, c => c.charCodeAt(0));
  return new TextDecoder('utf-8', { fatal: false }).decode(bytes);
}

function extractWithCharset(payload, contentType) {
  const m = /charset="?([^";]+)"?/i.exec(contentType || '');
  if (!m) return payload;
  const cs = m[1].toLowerCase();
  if (cs === 'utf-8' || cs === 'utf8') return payload;
  try { return new TextDecoder(cs, { fatal: false }).decode(new TextEncoder().encode(payload)); } catch { return payload; }
}

function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); }
