/**
 * Content script do Gmail.
 * Detecta a tela de Configurações → Geral → Assinatura e injeta um botão
 * "Instalar assinatura AssinaPro" que preenche o editor rich-text com o
 * HTML vindo da API AssinaPro.
 */
(function () {
  const BTN_ID = "ap-install-btn";
  const STATUS_ID = "ap-install-status";
  const SIGNATURE_NAME = "AssinaPro";

  function log(...args) {
    // eslint-disable-next-line no-console
    console.log("[AssinaPro]", ...args);
  }

  function isVisible(el) {
    if (!el) return false;
    const r = el.getBoundingClientRect();
    return r.width > 20 && r.height > 20;
  }

  function normalizeText(value) {
    return (value || "").replace(/\s+/g, " ").trim().toLowerCase();
  }

  function isSignatureLabelText(value) {
    const text = normalizeText(value);
    return (
      text === "assinatura" ||
      text === "assinatura:" ||
      text.startsWith("assinatura: ") ||
      text === "signature" ||
      text === "signature:" ||
      text.startsWith("signature: ")
    );
  }

  function isVacationSectionText(value) {
    const text = normalizeText(value);
    return (
      text.includes("resposta automática de férias") ||
      text.includes("resposta automatica de ferias") ||
      text.includes("vacation responder") ||
      text.includes("out of office") ||
      text.includes("out-of-office")
    );
  }

  /** Localiza a linha (tr) da seção "Assinatura:" nas configurações do Gmail. */
  function findSignatureRow() {
    const rows = document.querySelectorAll("tr");
    for (const row of rows) {
      const rowText = normalizeText(row.textContent);
      if (!rowText || isVacationSectionText(rowText)) continue;

      const cells = Array.from(row.children).filter((child) => /^(td|th)$/i.test(child.tagName));
      const labelText = normalizeText(cells[0]?.textContent || "");

      if (isSignatureLabelText(labelText) || labelText.startsWith("assinatura ") || labelText.startsWith("signature ")) {
        return row;
      }

      // Alguns layouts do Gmail colocam o título em um nó interno do primeiro td.
      const labelCandidates = cells[0]?.querySelectorAll("div, span, label, b, strong") || [];
      for (const el of labelCandidates) {
        if (isSignatureLabelText(el.textContent)) return row;
      }
    }

    const cells = document.querySelectorAll("td, th");
    for (const el of cells) {
      const txt = normalizeText(el.textContent);
      if (isVacationSectionText(txt)) continue;
      if (isSignatureLabelText(txt) || txt.startsWith("assinatura ") || txt.startsWith("signature ")) {
        return el.closest("tr") || el.parentElement;
      }
    }

    return null;
  }

  function getSignatureMainCell(row) {
    if (!row) return null;
    const cells = Array.from(row.children).filter((child) => /^(td|th)$/i.test(child.tagName));
    return cells[1] || row;
  }

  /**
   * Localiza o iframe contenteditable do editor de assinatura, escopado
   * à linha "Assinatura:" — evita confundir com o editor de "Resposta
   * automática" (aviso de férias), que também usa iframe contenteditable.
   */
  function findSignatureEditor() {
    const row = findSignatureRow();
    if (!row) return null;

    const scope = row;
    const iframes = scope.querySelectorAll("iframe");
    for (const f of iframes) {
      try {
        const doc = f.contentDocument;
        const body = doc?.body;
        const editable = body?.isContentEditable ? body : body?.querySelector?.("[contenteditable='true']");
        if (editable && isVisible(f)) {
          return { kind: "iframe", body: editable, iframe: f };
        }
      } catch { /* cross-origin */ }
    }
    // Fallback: div contenteditable visível dentro da linha da assinatura.
    const boxes = scope.querySelectorAll("[contenteditable='true']");
    for (const b of boxes) {
      if (isVisible(b)) return { kind: "inline", body: b };
    }
    return null;
  }

  /**
   * Se nenhum editor está aberto, tenta clicar na primeira assinatura da lista
   * (à esquerda) OU no botão "Criar novo" para forçar o Gmail a renderizar o
   * iframe do editor. A busca é sempre limitada à linha "Assinatura" para não
   * tocar no editor de "Resposta automática de férias".
   */
  async function ensureEditorOpen() {
    if (findSignatureEditor()) return true;

    const row = findSignatureRow();
    if (!row) return false;
    const scope = getSignatureMainCell(row) || row;

    // Tenta clicar em um item de assinatura já existente.
    const items = scope.querySelectorAll("div[role='button'], button, [jsaction], [tabindex='0']");
    for (const el of items) {
      const t = normalizeText(`${el.getAttribute("aria-label") || ""} ${el.textContent || ""}`);
      // Pula o "Criar novo" nesta primeira passada.
      if (!t || /criar novo|create new|sem assinaturas|no signatures/i.test(t)) continue;
      if (t.length > 60) continue;
      // Filtra itens claramente irrelevantes.
      if (/salvar|cancelar|save|cancel|excluir|delete|editar|edit/i.test(t)) continue;
      const rect = el.getBoundingClientRect();
      if (rect.width < 40 || rect.height < 16) continue;
      el.click();
      await waitForEditor(1200);
      if (findSignatureEditor()) return "clicked-item";
    }

    // Se a conta ainda está em "Sem assinaturas", cria uma assinatura nova.
    const createButton = findCreateSignatureButton(scope);
    if (createButton) {
      createButton.click();
      await waitForDialogAndConfirmName();
      await waitForEditor(2500);
      if (findSignatureEditor()) return "created-signature";
    }

    return false;
  }

  function findCreateSignatureButton(scope) {
    const controls = scope.querySelectorAll("div[role='button'], button, [jsaction], [tabindex='0']");
    for (const el of controls) {
      const text = normalizeText(`${el.getAttribute("aria-label") || ""} ${el.textContent || ""}`);
      if (/criar novo|create new/.test(text) && isVisible(el)) return el;
    }
    return null;
  }

  function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }

  async function waitForEditor(timeoutMs) {
    const started = Date.now();
    while (Date.now() - started < timeoutMs) {
      if (findSignatureEditor()) return true;
      await sleep(150);
    }
    return false;
  }

  function findVisibleDialog() {
    const dialogs = document.querySelectorAll("[role='dialog'], [aria-modal='true']");
    for (const dialog of dialogs) {
      if (isVisible(dialog)) return dialog;
    }
    return null;
  }

  async function waitForDialogAndConfirmName() {
    const started = Date.now();
    while (Date.now() - started < 2500) {
      const dialog = findVisibleDialog();
      if (dialog) {
        const input = dialog.querySelector("input[type='text'], input:not([type]), textarea");
        if (input) {
          input.focus();
          input.value = SIGNATURE_NAME;
          input.dispatchEvent(new Event("input", { bubbles: true }));
          input.dispatchEvent(new Event("change", { bubbles: true }));
        }

        const buttons = dialog.querySelectorAll("div[role='button'], button");
        for (const button of buttons) {
          const text = normalizeText(button.textContent || button.getAttribute("aria-label") || "");
          if (/^(criar|create|ok|confirmar|done)$/.test(text) || /criar|create/.test(text)) {
            button.click();
            return true;
          }
        }
      }
      await sleep(150);
    }
    return false;
  }

  function findAnchor() {
    // Procura pelo cabeçalho "Assinatura" na página de configurações.
    const row = findSignatureRow();
    if (row) return row;

    const candidates = document.querySelectorAll("td, div, h2, h3, label");
    for (const el of candidates) {
      const txt = normalizeText(el.textContent);
      if (!isVacationSectionText(txt) && isSignatureLabelText(txt)) {
        return el;
      }
    }
    return null;
  }

  function ensureButton() {
    if (document.getElementById(BTN_ID)) return;
    const row = findSignatureRow();
    const anchor = row || findAnchor();
    const editor = findSignatureEditor();
    if (!row && !editor) return;

    const container = document.createElement("div");
    container.style.cssText = "margin:8px 0;padding:10px 12px;border:1px dashed #C43AAF;border-radius:10px;background:linear-gradient(135deg,#fdf2fa,#f5f3ff);font-family:'Google Sans',Roboto,Arial,sans-serif;display:flex;align-items:center;gap:10px;max-width:640px";

    const label = document.createElement("div");
    label.innerHTML = `<div style="font-size:13px;font-weight:600;color:#6B21A8">AssinaPro</div><div id="${STATUS_ID}" style="font-size:12px;color:#4b5563">Preencher automaticamente com sua assinatura ativa.</div>`;
    label.style.flex = "1";

    const btn = document.createElement("button");
    btn.id = BTN_ID;
    btn.type = "button";
    btn.textContent = "Instalar assinatura";
    btn.style.cssText = "background:linear-gradient(135deg,#C43AAF,#6B21A8);color:#fff;border:0;border-radius:8px;padding:8px 14px;font-size:13px;font-weight:600;cursor:pointer;box-shadow:0 2px 8px rgba(107,33,168,.25)";
    btn.addEventListener("click", installFlow);

    container.appendChild(label);
    container.appendChild(btn);

    const target = getSignatureMainCell(row) || anchor?.parentElement;
    if (target) {
      target.insertBefore(container, target.firstChild);
    } else {
      document.body.appendChild(container);
    }
  }

  function setStatus(text, color) {
    const el = document.getElementById(STATUS_ID);
    if (el) {
      el.textContent = text;
      if (color) el.style.color = color;
    }
  }

  function pickSignature(signatures) {
    // MVP: se houver mais de uma, mostra prompt nativo com nomes numerados.
    if (signatures.length === 1) return signatures[0];
    const list = signatures.map((s, i) => `${i + 1}. ${s.name}`).join("\n");
    const choice = window.prompt(
      `Qual assinatura instalar?\n\n${list}\n\nDigite o número:`,
      "1"
    );
    const idx = Number(choice) - 1;
    if (Number.isFinite(idx) && signatures[idx]) return signatures[idx];
    return null;
  }

  function applyHtmlToEditor(editor, html) {
    if (!editor) return false;
    const body = editor.body;
    // Limpa antes.
    body.innerHTML = "";
    // Executa via execCommand para o Gmail perceber a alteração.
    body.focus();
    try {
      // insertHTML aciona os handlers internos do editor.
      const doc = editor.kind === "iframe" ? editor.body.ownerDocument : document;
      doc.execCommand("selectAll", false);
      doc.execCommand("insertHTML", false, html);
    } catch {
      body.innerHTML = html;
    }
    // Dispara evento de input para o Gmail marcar como sujo.
    body.dispatchEvent(new Event("input", { bubbles: true }));
    return true;
  }

  async function installFlow() {
    setStatus("Buscando sua assinatura ativa…", "#4b5563");
    chrome.runtime.sendMessage({ type: "AP_GET_SIGNATURES" }, (res) => {
      if (!res?.ok) {
        if (res?.error === "unauthorized") {
          setStatus("Faça login na extensão (clique no ícone AssinaPro).", "#b91c1c");
        } else {
          setStatus(`Erro: ${res?.error || "falha ao buscar"}`, "#b91c1c");
        }
        return;
      }
      const signatures = res.signatures || [];
      if (signatures.length === 0) {
        setStatus("Nenhuma assinatura encontrada na sua conta.", "#b91c1c");
        return;
      }
      const picked = pickSignature(signatures);
      if (!picked) {
        setStatus("Instalação cancelada.", "#4b5563");
        return;
      }
      (async () => {
        let editor = findSignatureEditor();
        if (!editor) {
          setStatus("Abrindo/criando a assinatura no Gmail…", "#4b5563");
          await ensureEditorOpen();
          editor = findSignatureEditor();
        }
        if (!editor) {
          setStatus("Não encontrei o editor de assinatura. Fique na seção Assinatura, clique em Criar novo e tente novamente.", "#b45309");
          return;
        }
        const ok = applyHtmlToEditor(editor, picked.html);
        if (ok) {
          setStatus(`Instalada: ${picked.name}. Role até o final e clique em "Salvar alterações".`, "#047857");
        } else {
          setStatus("Não consegui preencher o editor. Tente rolar até a área de assinatura e clique novamente.", "#b45309");
        }
      })();
    });
  }

  // Observa mudanças no DOM porque o Gmail carrega a página de configurações
  // como SPA (não recarrega).
  // Escuta pedidos de instalação vindos do popup.
  chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
    if (msg?.type !== "AP_INSTALL_NOW") return false;
    const html = msg.signature?.html || "";
    const name = msg.signature?.name || "assinatura";

    const tryInstall = async (attempt) => {
      let editor = findSignatureEditor();
      if (!editor) {
        // Tenta abrir uma assinatura existente ou criar uma nova, sempre dentro
        // da seção Assinatura — nunca no aviso de férias.
        await ensureEditorOpen();
        if (attempt < 12) {
          setTimeout(() => { void tryInstall(attempt + 1); }, 250);
          return;
        }
        sendResponse({
          ok: false,
          message: "Não achei o editor de Assinatura. Na seção Assinatura, clique em 'Criar novo' e tente instalar novamente.",
        });
        return;
      }
      const ok = applyHtmlToEditor(editor, html);
      sendResponse(ok
        ? { ok: true, provider: "Gmail", name }
        : { ok: false, message: "Não consegui preencher o editor do Gmail." });
    };

    // sendResponse assíncrono — devolve true para manter o canal aberto.
    void tryInstall(0);
    return true;
  });

  const observer = new MutationObserver(() => {
    try { ensureButton(); } catch (e) { log("ensureButton falhou", e); }
  });
  observer.observe(document.body, { childList: true, subtree: true });
  ensureButton();
})();
