const fragment = new URLSearchParams(window.location.hash.slice(1));
const token = fragment.get("token") || "";
const apiHeaders = { "X-PARS-Lab-Token": token };

const statusCard = document.querySelector("#status-card");
const runButton = document.querySelector("#run-button");
const cancelButton = document.querySelector("#cancel-button");
const acknowledge = document.querySelector("#acknowledge");
const formError = document.querySelector("#form-error");
const progressSection = document.querySelector("#progress-section");
const resultsSection = document.querySelector("#results-section");
const progressState = document.querySelector("#progress-state");
const progressBar = document.querySelector("#progress-bar");
const currentArm = document.querySelector("#current-arm");
const completedArms = document.querySelector("#completed-arms");
const resultsBody = document.querySelector("#results-body");
const outputFolder = document.querySelector("#output-folder");
const downloadButton = document.querySelector("#download-button");

let ready = false;
let activeRun = null;
let selectedCount = 4;

function selectedArms() {
  return [...document.querySelectorAll('#arm-grid input[type="checkbox"]:checked')].map((item) => item.value);
}

function updateRunButton() {
  selectedCount = selectedArms().length;
  runButton.disabled = !ready || !acknowledge.checked || selectedCount === 0 || Boolean(activeRun);
}

async function api(path, options = {}) {
  const response = await fetch(path, {
    ...options,
    headers: {
      ...apiHeaders,
      ...(options.body ? { "Content-Type": "application/json" } : {}),
      ...(options.headers || {}),
    },
  });
  if (!response.ok) {
    const message = (await response.text()).trim() || `Request failed (${response.status})`;
    throw new Error(message);
  }
  return response;
}

async function checkStatus() {
  if (!token) {
    statusCard.className = "status-card error";
    statusCard.innerHTML = `<span class="status-dot"></span><div><strong>Local capability missing</strong><p>Close this tab and restart the PARS Lab application.</p></div>`;
    return;
  }
  try {
    const response = await api("/api/status");
    const status = await response.json();
    document.querySelector("#task-hash").textContent = status.protocol.task_packet_sha256;
    document.querySelector("#skill-hash").textContent = status.protocol.pars_skill_sha256;
    document.querySelector("#upstream").textContent = status.protocol.pars_upstream_commit;
    ready = status.ready;
    if (status.ready) {
      statusCard.className = "status-card ready";
      statusCard.innerHTML = `<span class="status-dot"></span><div><strong>Ready — ChatGPT authenticated</strong><p>${escapeHTML(status.codex_version)} · no API key will be passed to experiment arms.</p></div>`;
    } else {
      statusCard.className = "status-card error";
      statusCard.innerHTML = `<span class="status-dot"></span><div><strong>Not ready</strong><p>${escapeHTML(status.reason || "ChatGPT-authenticated Codex is required.")}</p></div>`;
    }
  } catch (error) {
    statusCard.className = "status-card error";
    statusCard.innerHTML = `<span class="status-dot"></span><div><strong>Readiness check failed</strong><p>${escapeHTML(error.message)}</p></div>`;
  }
  updateRunButton();
}

runButton.addEventListener("click", async () => {
  formError.textContent = "";
  resultsSection.hidden = true;
  try {
    const response = await api("/api/run", {
      method: "POST",
      body: JSON.stringify({ arms: selectedArms(), acknowledge_usage: acknowledge.checked }),
    });
    const data = await response.json();
    activeRun = data.run_id;
    progressSection.hidden = false;
    cancelButton.hidden = false;
    runButton.disabled = true;
    progressState.textContent = "QUEUED";
    progressBar.style.width = "2%";
    currentArm.textContent = "Preparing fresh arm directories…";
    completedArms.textContent = "Completed: none";
    pollRun();
  } catch (error) {
    formError.textContent = error.message;
  }
});

cancelButton.addEventListener("click", async () => {
  if (!activeRun) return;
  cancelButton.disabled = true;
  try {
    await api(`/api/run/${activeRun}/cancel`, { method: "POST" });
    progressState.textContent = "CANCELLING";
  } catch (error) {
    formError.textContent = error.message;
    cancelButton.disabled = false;
  }
});

downloadButton.addEventListener("click", async () => {
  if (!activeRun) return;
  try {
    const response = await api(`/api/run/${activeRun}/receipt`);
    const blob = await response.blob();
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = `PARS-Lab-${activeRun}-receipt.json`;
    document.body.appendChild(link);
    link.click();
    link.remove();
    URL.revokeObjectURL(link.href);
  } catch (error) {
    formError.textContent = error.message;
  }
});

async function pollRun() {
  if (!activeRun) return;
  try {
    const response = await api(`/api/run/${activeRun}`);
    const state = await response.json();
    progressState.textContent = state.status.toUpperCase();
    const completed = state.completed_arms || [];
    const denominator = Math.max(selectedCount, 1);
    const partial = state.current_arm ? 0.42 : 0;
    progressBar.style.width = `${Math.min(100, ((completed.length + partial) / denominator) * 100)}%`;
    currentArm.textContent = state.current_arm ? `Running arm ${state.current_arm}…` : "Finalizing receipt…";
    completedArms.textContent = `Completed: ${completed.length ? completed.join(", ") : "none"}`;
    if (["complete", "partial", "cancelled", "failed"].includes(state.status)) {
      progressBar.style.width = "100%";
      cancelButton.hidden = true;
      cancelButton.disabled = false;
      renderResults(state);
      updateRunButton();
      return;
    }
    window.setTimeout(pollRun, 1800);
  } catch (error) {
    formError.textContent = error.message;
    window.setTimeout(pollRun, 3000);
  }
}

function renderResults(state) {
  resultsSection.hidden = false;
  resultsBody.innerHTML = "";
  const arms = [...(state.receipt?.arms || [])].sort((a, b) => a.arm.localeCompare(b.arm));
  for (const arm of arms) {
    const row = document.createElement("tr");
    row.innerHTML = `
      <td>${escapeHTML(arm.arm)}</td>
      <td>${escapeHTML(arm.label)}</td>
      <td>${arm.score.total_points}/11</td>
      <td>${arm.reported_tokens == null ? "not reported" : Number(arm.reported_tokens).toLocaleString()}</td>
      <td>${formatDuration(arm.duration_ms)}</td>
      <td>${escapeHTML(arm.status)}</td>
    `;
    resultsBody.appendChild(row);
  }
  outputFolder.textContent = state.output_folder ? `Saved locally: ${state.output_folder}` : "Receipt retained by the local runner.";
  resultsSection.scrollIntoView({ behavior: "smooth", block: "start" });
}

function formatDuration(milliseconds) {
  const seconds = Math.round(milliseconds / 1000);
  if (seconds < 60) return `${seconds}s`;
  return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
}

function escapeHTML(value) {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

acknowledge.addEventListener("change", updateRunButton);
document.querySelector("#arm-grid").addEventListener("change", updateRunButton);
checkStatus();
