// ── Toolbar button: open settings page ──

browser.browserAction.onClicked.addListener(() => {
  browser.runtime.openOptionsPage();
});

// ── "Erledigt" button in message display ──

async function executeErledigtAction(tab, actionConfig) {
  const message = await messenger.messageDisplay.getDisplayedMessage(tab.id);
  if (!message) {
    browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: 'Keine Nachricht ausgewählt.' });
    return;
  }

  const storage = await browser.storage.local.get(['gitea_config', 'schlagwoerter_cache']);
  const config = storage.gitea_config || {};
  const schlagwoerter = storage.schlagwoerter_cache;
  // "Als gelesen markieren" — pro Aktion konfigurierbar, standardmäßig an.
  const markRead = (actionConfig || {}).markRead !== false;

  // Apply user's tag
  let tagKey = null;
  if (Array.isArray(schlagwoerter) && config.authorName) {
    const match = schlagwoerter.find(u => u.name.toLowerCase() === config.authorName.toLowerCase());
    if (match) {
      tagKey = `$hps_${match.name.toLowerCase().replace(/\s+/g, '_')}`;
    }
  }

  if (tagKey) {
    const currentTags = message.tags || [];
    if (!currentTags.includes(tagKey)) {
      await messenger.messages.update(message.id, { tags: [...currentTags, tagKey] });
    }
  }

  // Mark as read (before the move, while the id is still valid in this folder)
  if (markRead && !message.read) {
    await messenger.messages.update(message.id, { read: true });
  }

  // Move to target folder
  if (actionConfig.targetFolder) {
    const folderInfo = JSON.parse(actionConfig.targetFolder);
    await messenger.messages.move([message.id], folderInfo);
  }

  // Feedback
  const parts = [];
  if (tagKey) parts.push('markiert');
  if (markRead && !message.read) parts.push('gelesen');
  if (actionConfig.targetFolder) parts.push('verschoben');
  const title = actionConfig.name || 'Erledigt';
  browser.notifications.create({
    type: 'basic',
    iconUrl: browser.runtime.getURL('icons/icon.png'),
    title,
    message: parts.length ? `Nachricht ${parts.join(' & ')}.` : 'Kein Schlagwort oder Zielordner konfiguriert.'
  });
}

// Single action: direct click without popup
messenger.messageDisplayAction.onClicked.addListener(async (tab) => {
  try {
    const result = await browser.storage.local.get('erledigt_config');
    const actions = (result.erledigt_config || {}).actions || [];
    await executeErledigtAction(tab, actions[0] || {});
  } catch (e) {
    console.error('Erledigt-Button Fehler:', e);
    browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: e.message });
  }
});

// Toggle popup vs direct click based on action count
async function updateErledigtPopup() {
  const result = await browser.storage.local.get('erledigt_config');
  const actions = (result.erledigt_config || {}).actions || [];
  const setLabel = (label) => {
    // setLabel ist Thunderbird-spezifisch — defensiv prüfen, damit der Start nie bricht.
    if (messenger.messageDisplayAction.setLabel) return messenger.messageDisplayAction.setLabel({ label });
  };
  if (actions.length > 1) {
    await messenger.messageDisplayAction.setPopup({ popup: 'message_popup.html' });
    await messenger.messageDisplayAction.setTitle({ title: 'Aktion wählen' });
    await setLabel('QuickMove');
  } else {
    const name = actions[0]?.name || 'QuickMove';
    await messenger.messageDisplayAction.setPopup({ popup: '' });
    await messenger.messageDisplayAction.setTitle({ title: name });
    await setLabel(name); // Button heißt wie die (einzige) Aktion
  }
}

// Update on config change
browser.storage.onChanged.addListener((changes, area) => {
  if (area === 'local' && changes.erledigt_config) updateErledigtPopup();
});
updateErledigtPopup();

// ── about:config-Prefs bei jedem Start erzwingen ──
//
// Manche Thunderbird-Einstellungen (Startseite, Ansicht, Layout, pro Konto das
// Signatur-/Antwort-Verhalten) „springen zurück" und müssen sonst von Hand
// nachgezogen werden. Wir setzen sie bei JEDEM Start neu über den privilegierten
// forcedPrefs-Experiment (Services.prefs). Die Liste liegt in
// lib/forced-prefs-list.js (globale FORCED_PREFS / FORCED_IDENTITY_PREFS).
// Pro Eintrag kann der Client im Options-Dialog opt-outen (forced_prefs_optout).
const FORCED_PREFS_OPTOUT_KEY = 'forced_prefs_optout';

async function enforceForcedPrefs() {
  const stored = await browser.storage.local.get(FORCED_PREFS_OPTOUT_KEY);
  const disabled = new Set(stored[FORCED_PREFS_OPTOUT_KEY] || []);

  // Globale Prefs
  for (const p of FORCED_PREFS) {
    if (disabled.has(p.id)) continue;
    try {
      await browser.forcedPrefs.setPref(p.name, p.type, p.value);
    } catch (e) {
      console.error('[forcedPrefs] konnte', p.name, 'nicht setzen:', e);
    }
  }

  // Pro-Identität-Prefs — über alle Konten/Identitäten iterieren
  const accounts = await browser.accounts.list();
  for (const acc of accounts) {
    for (const ident of (acc.identities || [])) {
      for (const p of FORCED_IDENTITY_PREFS) {
        if (disabled.has(p.id)) continue;
        const name = `mail.identity.${ident.id}.${p.suffix}`;
        try {
          await browser.forcedPrefs.setPref(name, p.type, p.value);
        } catch (e) {
          console.error('[forcedPrefs] konnte', name, 'nicht setzen:', e);
        }
      }
    }
  }
}

enforceForcedPrefs(); // Top-Level = läuft einmal pro TB-Start

// Wird eine Pref im Options-Dialog wieder AKTIVIERT, sofort anwenden
// (statt bis zum nächsten Neustart zu warten).
browser.storage.onChanged.addListener((changes, area) => {
  if (area === 'local' && changes[FORCED_PREFS_OPTOUT_KEY]) enforceForcedPrefs();
});

// ── Signatur in neuen Compose-Fenstern automatisch aktualisieren ──
//
// Thunderbird merkt sich die Signatur einer Identität pro Sitzung. Öffnet der
// Benutzer nach einem Hintergrund-Sync ein neues Verfassen-Fenster, steckt darin
// noch die ALTE Signatur (alter Footer) — `identities.update({signature})`
// schreibt zwar den Pref, aber das Compose-Fenster fügt die gecachte Fassung ein.
// Ein Event „neues Compose-Fenster" gibt es in der WebExtension-API nicht, daher
// hängen wir uns an tabs.onCreated und tauschen NUR den Footer-Teil (ab dem
// SIG_FOOTER_START-Marker) im eingefügten Signaturblock gegen den frisch
// gesyncten aus. Header, Trenner ("-- ") und Struktur bleiben unangetastet.
// Vollautomatisch, ohne jede Benutzeraktion.

const SIG_FOOTER_MARK = '<!-- SIG_FOOTER_START -->';
const sigSleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function getFreshFooter() {
  const c = await browser.storage.local.get('sig_footer_cache');
  return c.sig_footer_cache || '';
}

async function refreshComposeSignature(tabId, tabType) {
  // Nicht-Compose-Tabs sofort ignorieren, wenn der Typ bekannt ist.
  if (tabType && tabType !== 'messageCompose') return;

  const footer = await getFreshFooter();
  if (!footer) return;

  // Läuft IM Compose-Dokument: findet den Signaturblock, ersetzt nur den Footer.
  const code = `(function(){
    const editor = document.getElementById('messageEditor');
    const doc = editor ? editor.contentDocument : document;
    const sig = doc.querySelector('.moz-signature');
    if (!sig) return 'notready';
    const MARK = ${JSON.stringify(SIG_FOOTER_MARK)};
    const cur = sig.innerHTML;
    const i = cur.indexOf(MARK);
    if (i === -1) return 'unmanaged';            // keine vom Plugin verwaltete Signatur
    const before = cur.slice(0, i + MARK.length); // "-- <br>" + Header + Marker
    const curFooter = cur.slice(i + MARK.length).replace(/^\\s+/, '');
    const NEW = ${JSON.stringify(footer)};
    if (curFooter === NEW) return 'current';      // schon aktuell, nichts tun
    sig.innerHTML = before + '\\n' + NEW;
    return 'updated';
  })();`;

  // Thunderbird fügt die Signatur evtl. erst kurz nach dem Öffnen ein → kurz pollen.
  let throwCount = 0;
  for (let attempt = 0; attempt < 20; attempt++) {
    let details;
    try {
      details = await browser.compose.getComposeDetails(tabId);
    } catch (_) {
      // Kein Compose-Tab oder noch nicht bereit. Bei bekanntem Typ weiter pollen,
      // sonst nach ein paar Fehlversuchen aufgeben.
      if (tabType !== 'messageCompose' && ++throwCount > 3) return;
      await sigSleep(150);
      continue;
    }
    if (!details) { await sigSleep(150); continue; }
    if (details.isPlainText) return;      // Footer ist HTML — Plaintext nicht anfassen
    if (details.type === 'draft') return; // gespeicherte Entwürfe nicht überschreiben

    let res;
    try {
      const out = await browser.tabs.executeScript(tabId, { code });
      res = Array.isArray(out) ? out[0] : out;
    } catch (_) {
      return; // Fenster bereits geschlossen o. Ä.
    }
    if (res !== 'notready') return; // fertig: updated / current / unmanaged
    await sigSleep(150);
  }
}

browser.tabs.onCreated.addListener((tab) => {
  refreshComposeSignature(tab.id, tab && tab.type).catch((err) =>
    console.error('[Sig] Compose-Refresh fehlgeschlagen:', err));
});

// ── Template insertion ──

browser.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.action === 'erledigtAction') {
    (async () => {
      try {
        const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
        const result = await browser.storage.local.get('erledigt_config');
        const actions = (result.erledigt_config || {}).actions || [];
        const action = actions[msg.index] || {};
        await executeErledigtAction(tab, action);
        sendResponse({ success: true });
      } catch (e) {
        console.error('Erledigt-Action Fehler:', e);
        browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: e.message });
        sendResponse({ success: false, error: e.message });
      }
    })();
    return true;
  }
  if (msg.action !== 'insertTemplate') return;

  handleInsertTemplate(msg).then(() => sendResponse())
    .catch(err => sendResponse({ error: err.message }));
  return true; // keep channel open for async response
});

async function handleInsertTemplate(msg) {
  try {
    const [tab] = await browser.tabs.query({
      active: true,
      currentWindow: true,
      windowType: 'messageCompose',
    });
    if (!tab) throw new Error('Kein Compose-Fenster gefunden');

    const details = await browser.compose.getComposeDetails(tab.id);
    const isHtmlTemplate = msg.text.includes('<');

    // If compose is plain text but template is HTML, switch to HTML mode first
    if (details.isPlainText && isHtmlTemplate) {
      await browser.compose.setComposeDetails(tab.id, { isPlainText: false });
    }

    if (details.isPlainText && !isHtmlTemplate) {
      // Plain text template in plain text mode - use old method
      const old = details.plainTextBody || '';
      const newBody = msg.text + (old ? '\n' + old : '');
      await browser.compose.setComposeDetails(tab.id, { plainTextBody: newBody });
    } else {
      // HTML mode: wrap the template in a marker element (id=hps-vorlage) and
      // replace any previously inserted one — so durchswitchen ersetzt statt stapelt.
      const htmlContent = isHtmlTemplate ? msg.text : msg.text.replace(/\n/g, '<br>');

      // Directly manipulate the editor DOM: remove the old template block (if any),
      // then insert the new one at the top of the body. Returns true on success.
      const injected = await browser.tabs.executeScript(tab.id, {
        code: `
          (function () {
            const editor = document.getElementById('messageEditor');
            const editorDoc = editor ? editor.contentDocument : document;
            const body = editorDoc && editorDoc.body;
            if (!body) return false;

            // Remove a previously inserted template block, so switching replaces it
            const prev = editorDoc.getElementById('hps-vorlage');
            if (prev) prev.remove();

            // Wrap the new template in a marker element with a stable id
            const wrapper = editorDoc.createElement('div');
            wrapper.id = 'hps-vorlage';
            wrapper.innerHTML = ${JSON.stringify(htmlContent)};

            // Insert at the very top of the body (above quote/signature/typed text)
            body.insertBefore(wrapper, body.firstChild);

            // Place the cursor right after the inserted block
            const range = editorDoc.createRange();
            range.setStartAfter(wrapper);
            range.collapse(true);
            const sel = editorDoc.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
            return true;
          })();
        `
      }).then(r => (Array.isArray(r) ? r[0] : r)).catch(() => false);

      if (!injected) {
        // Fallback: editor DOM not reachable (TB version differences) — use the
        // insertText pipeline. Note: this variant cannot replace, only prepend.
        await browser.compose.insertText(tab.id, htmlContent + '<br>', { insertAsText: false });
      }
    }

  } catch (e) {
    console.error('background.js error:', e);

    // Fallback: if insertText fails, try setComposeDetails
    try {
      const [tab] = await browser.tabs.query({
        active: true, currentWindow: true, windowType: 'messageCompose',
      });
      if (tab) {
        const details = await browser.compose.getComposeDetails(tab.id);
        const old = details.body || '';
        const htmlTpl = msg.text.includes('<') ? msg.text : msg.text.replace(/\n/g, '<br>');
        const bodyIdx = old.indexOf('<body');
        let newBody;
        if (bodyIdx !== -1) {
          const insertAt = old.indexOf('>', bodyIdx) + 1;
          newBody = old.slice(0, insertAt) + '\n' + htmlTpl + '\n' + old.slice(insertAt);
        } else {
          newBody = htmlTpl + '<br>' + old;
        }
        await browser.compose.setComposeDetails(tab.id, { body: newBody });
      }
    } catch (e2) {
      console.error('background.js fallback error:', e2);
      browser.notifications.create({
        type: 'basic',
        iconUrl: browser.runtime.getURL('icons/icon.png'),
        title: 'Fehler beim Einfügen',
        message: e2.message,
      });
    }
  }
}
