// ---- Configuracao ----
// Troque pelos enderecos reais antes de publicar.
const AGENT_URL = "http://127.0.0.1:8765";
const PUBLIC_API_URL = "https://api.seudominio.com/v1/public";
const INSTALLER_URL = "";

// ---- Elementos ----
const sections = {
  checking: document.getElementById("state-checking"),
  disconnected: document.getElementById("state-disconnected"),
  ready: document.getElementById("state-ready"),
  done: document.getElementById("state-done"),
};

const machineLabel = document.getElementById("machine-label");
const greeting = document.getElementById("greeting");
const certPickerWrap = document.getElementById("cert-picker-wrap");
const certPicker = document.getElementById("cert-picker");
const dropzone = document.getElementById("dropzone");
const fileInput = document.getElementById("file-input");
const fileList = document.getElementById("file-list");
const signControls = document.getElementById("sign-controls");
const pinInput = document.getElementById("pin-input");
const signButton = document.getElementById("sign-button");
const formError = document.getElementById("form-error");
const retryButton = document.getElementById("retry-connection");
const downloadInstallerLink = document.getElementById("download-installer-link");
const doneHeading = document.getElementById("done-heading");
const doneSub = document.getElementById("done-sub");
const resultList = document.getElementById("result-list");
const signMoreButton = document.getElementById("sign-more");

downloadInstallerLink.href = INSTALLER_URL;

// ---- Estado ----
let pendingFiles = []; // [{ id, file }]
let certificates = [];

function showState(name) {
  Object.entries(sections).forEach(([key, el]) => {
    el.hidden = key !== name;
  });
}

function setFormError(message) {
  formError.textContent = message || "";
  formError.hidden = !message;
}

// ---- Conexao com o agente ----

async function checkConnection() {
  showState("checking");
  try {
    const identity = await fetchJSON(`${AGENT_URL}/identity`);
    const certsResult = await fetchJSON(`${AGENT_URL}/certificates`);

    certificates = certsResult.certificates || [];
    if (certificates.length === 0) {
      throw new Error("Nenhum certificado encontrado no token conectado.");
    }

    await setupClientGreeting(identity.client_id, identity.machine_id);
    setupCertificatePicker();
    showState("ready");
  } catch (err) {
    console.warn("Nao foi possivel conectar ao assinador:", err.message);
    showState("disconnected");
  }
}

async function setupClientGreeting(clientId, machineId) {
  machineLabel.textContent = `Máquina ${machineId.slice(0, 8)}`;
  greeting.textContent = "Bem-vindo.";

  if (!clientId) return;

  try {
    const { name } = await fetchJSON(`${PUBLIC_API_URL}/clients/${clientId}`);
    if (name) greeting.textContent = `Bem-vindo, ${name}.`;
  } catch (err) {
    // Se a API publica falhar, a saudacao generica ja esta no lugar -
    // isso nao deve impedir o cliente de assinar.
    console.warn("Nao foi possivel buscar o nome do cliente:", err.message);
  }
}

function setupCertificatePicker() {
  if (certificates.length <= 1) {
    certPickerWrap.hidden = true;
    return;
  }
  certPicker.innerHTML = "";
  certificates.forEach((cert) => {
    const option = document.createElement("option");
    option.value = cert.id;
    option.textContent = cert.label;
    certPicker.appendChild(option);
  });
  certPickerWrap.hidden = false;
}

function selectedCertId() {
  return certificates.length <= 1 ? certificates[0].id : certPicker.value;
}

async function fetchJSON(url, options) {
  const res = await fetch(url, options);
  const body = await res.json().catch(() => ({}));
  if (!res.ok) {
    throw new Error(body.error || `Erro ${res.status} ao chamar ${url}`);
  }
  return body;
}

// ---- Selecao de arquivos ----

let fileIdCounter = 0;

function addFiles(fileArray) {
  const pdfFiles = fileArray.filter((f) => f.type === "application/pdf" || f.name.toLowerCase().endsWith(".pdf"));
  pdfFiles.forEach((file) => {
    pendingFiles.push({ id: `f${fileIdCounter++}`, file, status: "pendente" });
  });
  renderFileList();
}

function removeFile(id) {
  pendingFiles = pendingFiles.filter((f) => f.id !== id);
  renderFileList();
}

function renderFileList() {
  fileList.hidden = pendingFiles.length === 0;
  signControls.hidden = pendingFiles.length === 0;
  fileList.innerHTML = "";

  pendingFiles.forEach(({ id, file, status }) => {
    const li = document.createElement("li");
    li.className = "file-row";
    li.dataset.fileId = id;

    const name = document.createElement("span");
    name.className = "file-name";
    name.textContent = file.name;

    const statusEl = document.createElement("span");
    statusEl.className = "file-status";
    statusEl.textContent = status;

    const removeBtn = document.createElement("button");
    removeBtn.className = "file-remove";
    removeBtn.setAttribute("aria-label", `Remover ${file.name}`);
    removeBtn.textContent = "×";
    removeBtn.addEventListener("click", () => removeFile(id));

    li.append(name, statusEl, removeBtn);
    fileList.appendChild(li);
  });
}

dropzone.addEventListener("click", () => fileInput.click());
dropzone.addEventListener("keydown", (e) => {
  if (e.key === "Enter" || e.key === " ") {
    e.preventDefault();
    fileInput.click();
  }
});
fileInput.addEventListener("change", (e) => {
  addFiles(Array.from(e.target.files));
  fileInput.value = "";
});

["dragenter", "dragover"].forEach((evt) =>
  dropzone.addEventListener(evt, (e) => {
    e.preventDefault();
    dropzone.classList.add("is-dragover");
  })
);
["dragleave", "drop"].forEach((evt) =>
  dropzone.addEventListener(evt, (e) => {
    e.preventDefault();
    dropzone.classList.remove("is-dragover");
  })
);
dropzone.addEventListener("drop", (e) => {
  addFiles(Array.from(e.dataTransfer.files));
});

// ---- Assinatura ----

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result.split(",")[1]);
    reader.onerror = () => reject(new Error(`Falha ao ler ${file.name}`));
    reader.readAsDataURL(file);
  });
}

function updateFileStatus(id, status, className) {
  const row = fileList.querySelector(`[data-file-id="${id}"] .file-status`);
  if (!row) return;
  row.textContent = status;
  row.className = `file-status ${className || ""}`.trim();
}

function triggerDownload(blob, filename) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  setTimeout(() => URL.revokeObjectURL(url), 10000);
}

function signedFilename(originalName) {
  return originalName.replace(/\.pdf$/i, "") + "-assinado.pdf";
}

signButton.addEventListener("click", async () => {
  setFormError(null);
  const pin = pinInput.value;
  if (!pin) {
    setFormError("Informe o PIN do certificado.");
    return;
  }
  if (pendingFiles.length === 0) return;

  signButton.disabled = true;
  const results = [];

  for (const entry of pendingFiles) {
    updateFileStatus(entry.id, "assinando", "is-signing");
    try {
      const pdfBase64 = await fileToBase64(entry.file);
      const response = await fetchJSON(`${AGENT_URL}/sign-pdf`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          cert_id: selectedCertId(),
          pin,
          pdf_base64: pdfBase64,
          reason: "Assinatura digital",
        }),
      });

      const signedBytes = Uint8Array.from(atob(response.pdf_base64), (c) => c.charCodeAt(0));
      const blob = new Blob([signedBytes], { type: "application/pdf" });
      const filename = signedFilename(entry.file.name);

      triggerDownload(blob, filename);
      updateFileStatus(entry.id, "concluído", "is-done");
      results.push({ name: entry.file.name, filename, blob, ok: true });
    } catch (err) {
      updateFileStatus(entry.id, "erro", "is-error");
      results.push({ name: entry.file.name, ok: false, error: err.message });
    }
  }

  signButton.disabled = false;
  pinInput.value = "";
  showResults(results);
});

function showResults(results) {
  const successCount = results.filter((r) => r.ok).length;
  doneHeading.textContent = successCount === results.length
    ? "Documentos assinados."
    : `${successCount} de ${results.length} documentos assinados.`;
  doneSub.textContent = successCount === results.length
    ? "O download começou automaticamente. Use os links abaixo se precisar baixar de novo."
    : "Alguns documentos não puderam ser assinados. Veja os detalhes abaixo.";

  resultList.innerHTML = "";
  results.forEach((r) => {
    const li = document.createElement("li");
    li.className = "file-row";

    const name = document.createElement("span");
    name.className = "file-name";
    name.textContent = r.name;

    if (r.ok) {
      const link = document.createElement("a");
      link.className = "file-download";
      link.textContent = "Baixar novamente";
      link.href = "#";
      link.addEventListener("click", (e) => {
        e.preventDefault();
        triggerDownload(r.blob, r.filename);
      });
      li.append(name, link);
    } else {
      const status = document.createElement("span");
      status.className = "file-status is-error";
      status.textContent = r.error;
      li.append(name, status);
    }

    resultList.appendChild(li);
  });

  showState("done");
}

signMoreButton.addEventListener("click", () => {
  pendingFiles = [];
  renderFileList();
  setFormError(null);
  showState("ready");
});

retryButton.addEventListener("click", checkConnection);

// ---- Inicializacao ----
checkConnection();
