import { commandAcknowledgement } from "./interaction.js";
const toastRegion = (): HTMLElement | null => document.querySelector<HTMLElement>(".toast-region");

function announce(message: string): void {
  const region = toastRegion();
  if (!region) return;
  region.textContent = message;
  region.classList.add("visible");
  window.setTimeout(() => region.classList.remove("visible"), 3200);
}

function currentUrlWith(params: Record<string, string | undefined>): string {
  const url = new URL(window.location.href);
  Object.entries(params).forEach(([key, value]) => {
    if (value) url.searchParams.set(key, value);
    else url.searchParams.delete(key);
  });
  return `${url.pathname}${url.search}`;
}

async function handleCommand(control: HTMLElement): Promise<void> {
  const command = control.dataset.command;
  if (!command) return;
  if (control.getAttribute("aria-disabled") === "true") {
    announce("Action unavailable while data is stale, disconnected, or permission-limited.");
    return;
  }
  if (command === "refresh") {
    const url = new URL(window.location.href);
    url.searchParams.delete("fixture");
    window.location.assign(`${url.pathname}${url.search}`);
    return;
  }
  if (command === "new-plan") {
    window.location.assign(`${currentUrlWith({ tab: "plans" })}#new-plan`);
    return;
  }
  if (command === "move-up" || command === "move-down") {
    announce(
      "Movement preview only. The application Queue command remains authoritative for legality.",
    );
    return;
  }
  announce(commandAcknowledgement(command));
}

async function jsonRequest(path: string, init: RequestInit = {}): Promise<Record<string, unknown>> {
  const response = await fetch(path, {
    ...init,
    headers: { "content-type": "application/json", ...(init.headers ?? {}) },
  });
  const raw: unknown = await response.json().catch(() => ({}));
  const payload: Record<string, unknown> =
    typeof raw === "object" && raw !== null && !Array.isArray(raw)
      ? (raw as Record<string, unknown>)
      : {};
  if (!response.ok) {
    const message =
      typeof payload.message === "string"
        ? payload.message
        : typeof payload.error === "string"
          ? payload.error
          : `Request failed (${response.status})`;
    throw new Error(message);
  }
  return payload;
}

function formValues(form: HTMLFormElement): Record<string, string | string[]> {
  const result: Record<string, string | string[]> = {};
  for (const control of Array.from(form.elements)) {
    if (
      (control instanceof HTMLInputElement ||
        control instanceof HTMLTextAreaElement ||
        control instanceof HTMLSelectElement) &&
      control.name
    ) {
      result[control.name] = control.value;
    }
  }
  for (const key of ["successCriteria", "taskTitles"]) {
    const value = result[key];
    if (typeof value === "string") {
      result[key] = value
        .split(/\n+/u)
        .map((item) => item.trim())
        .filter(Boolean);
    }
  }
  return result;
}

function installLiveForms(root: ParentNode = document): void {
  root.querySelectorAll<HTMLFormElement>("[data-live-form]").forEach((form) => {
    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const error = form.querySelector<HTMLElement>("[data-form-error]");
      const button = form.querySelector<HTMLButtonElement>("button[type=submit]");
      if (error) error.textContent = "";
      if (button) button.disabled = true;
      try {
        const action = form.getAttribute("action");
        if (!action?.startsWith("/internal/")) throw new Error("Invalid live form action");
        const payload = await jsonRequest(`/api${action}`, {
          method: "POST",
          body: JSON.stringify(formValues(form)),
        });
        const project = payload.project;
        if (
          action === "/internal/projects" &&
          typeof project === "object" &&
          project !== null &&
          !Array.isArray(project) &&
          typeof (project as Record<string, unknown>).id === "string"
        ) {
          window.location.assign(
            `/projects/${encodeURIComponent(String((project as Record<string, unknown>).id))}`,
          );
          return;
        }
        window.location.reload();
      } catch (cause) {
        const message = cause instanceof Error ? cause.message : "Project mutation failed";
        if (error) error.textContent = message;
        announce(message);
        if (button) button.disabled = false;
      }
    });
  });
}

async function installAccountLogin(): Promise<void> {
  const button = document.querySelector<HTMLButtonElement>("[data-account-login]");
  const output = document.querySelector<HTMLElement>("[data-login-output]");
  const error = document.querySelector<HTMLElement>("[data-login-error]");
  if (!button || !output) return;
  button.addEventListener("click", async () => {
    button.disabled = true;
    if (error) error.textContent = "";
    output.hidden = false;
    output.textContent = "Starting fresh device login…";
    try {
      const started = await jsonRequest("/api/internal/providers/accounts/login", {
        method: "POST",
        body: JSON.stringify({ provider: button.dataset.provider ?? "codex" }),
      });
      const sessionId = String(started.id);
      while (true) {
        const status = await jsonRequest(
          `/api/internal/providers/accounts/login/${encodeURIComponent(sessionId)}`,
        );
        output.textContent = String(status.output ?? "");
        if (status.state === "complete") {
          announce(`Account ${String(status.account ?? "")} added to K3s Subrouter.`);
          window.setTimeout(() => window.location.reload(), 600);
          return;
        }
        if (status.state === "failed") {
          throw new Error(String(status.error ?? "Account login failed"));
        }
        await new Promise((resolve) => window.setTimeout(resolve, 1000));
      }
    } catch (cause) {
      const message = cause instanceof Error ? cause.message : "Account login failed";
      if (error) error.textContent = message;
      announce(message);
      button.disabled = false;
    }
  });
}

function installPlanLaunch(root: ParentNode = document): void {
  root.querySelectorAll<HTMLFormElement>("[data-plan-launch]").forEach((form) => {
    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      const submit = form.querySelector<HTMLButtonElement>("button[type=submit]");
      const error = form.querySelector<HTMLElement>("[data-plan-launch-error]");
      const projectId = form.dataset.projectId;
      const planId = form.dataset.planId;
      const account = form.querySelector<HTMLSelectElement>("[name=accountId]")?.value;
      const model = form.querySelector<HTMLInputElement>("[name=model]")?.value.trim();
      if (!projectId || !planId || !account) return;
      if (submit) submit.disabled = true;
      if (error) error.textContent = "";
      try {
        await jsonRequest(
          `/api/internal/projects/${encodeURIComponent(projectId)}/plans/${encodeURIComponent(planId)}/approve`,
          {
            method: "POST",
            body: JSON.stringify({ accountId: account, ...(model ? { model } : {}) }),
          },
        );
        window.location.assign(`/projects/${encodeURIComponent(projectId)}?tab=factory-runs`);
      } catch (cause) {
        const message = cause instanceof Error ? cause.message : "FactoryRun launch failed";
        if (error) error.textContent = message;
        announce(message);
        if (submit) submit.disabled = false;
      }
    });
  });
}
function installProjectControls(root: ParentNode): void {
  root.querySelectorAll<HTMLElement>("[data-command]").forEach((control) => {
    if (control.dataset.awpBound === "1") return;
    control.dataset.awpBound = "1";
    control.addEventListener("click", (event) => {
      event.preventDefault();
      void handleCommand(control);
    });
  });
  const select = root.querySelector<HTMLSelectElement>("[data-graph-select]");
  if (select && select.dataset.awpBound !== "1") {
    select.dataset.awpBound = "1";
    select.addEventListener("change", () =>
      window.location.assign(currentUrlWith({ task: select.value || undefined, view: "graph" })),
    );
  }
  installLiveForms(root);
  installPlanLaunch(root);
}

let liveRefreshRunning = false;
async function refreshApprovedProject(): Promise<void> {
  if (
    liveRefreshRunning ||
    !location.pathname.startsWith("/projects/") ||
    document.querySelector("[data-live-form] button:disabled,[data-plan-launch] button:disabled")
  ) {
    return;
  }
  const active = document.activeElement;
  if (
    active instanceof HTMLInputElement ||
    active instanceof HTMLTextAreaElement ||
    active instanceof HTMLSelectElement
  ) {
    return;
  }
  liveRefreshRunning = true;
  try {
    const response = await fetch(location.href, {
      headers: { accept: "text/html", "x-awp-live-refresh": "1" },
      cache: "no-store",
    });
    if (!response.ok) throw new Error(`Live refresh returned ${response.status}`);
    const nextDocument = new DOMParser().parseFromString(await response.text(), "text/html");
    const currentMain = document.querySelector<HTMLElement>("#main-content");
    const nextMain = nextDocument.querySelector<HTMLElement>("#main-content");
    if (currentMain && nextMain && currentMain.innerHTML !== nextMain.innerHTML) {
      currentMain.replaceWith(nextMain);
      installProjectControls(nextMain);
    }
  } catch {
    // Preserve the last authoritative projection while the control plane reconnects.
  } finally {
    liveRefreshRunning = false;
  }
}

function install(): void {
  installProjectControls(document);
  void installAccountLogin();
  document.addEventListener("keydown", (event) => {
    if (event.key === "Escape") toastRegion()?.classList.remove("visible");
  });
  window.setInterval(() => void refreshApprovedProject(), 1_000);
}
install();
