// SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
//
// SPDX-License-Identifier: GPL-2.0-or-later

export type AuthRole = "rx" | "control";

export interface AuthSession {
  authenticated: boolean;
  role?: AuthRole;
  auth_disabled?: boolean;
}

function decodeAuthSession(value: unknown): AuthSession {
  if (typeof value !== "object" || value === null) {
    throw new TypeError("The authentication response is malformed");
  }
  const session = value as Record<string, unknown>;
  if (typeof session.authenticated !== "boolean") {
    throw new TypeError("The authentication response has no authenticated flag");
  }
  if (session.role !== undefined && session.role !== "rx" && session.role !== "control") {
    throw new TypeError("The authentication response has an invalid role");
  }
  if (session.auth_disabled !== undefined && typeof session.auth_disabled !== "boolean") {
    throw new TypeError("The authentication response has an invalid auth_disabled flag");
  }
  const decoded: AuthSession = { authenticated: session.authenticated };
  if (session.role !== undefined) decoded.role = session.role;
  if (session.auth_disabled !== undefined) decoded.auth_disabled = session.auth_disabled;
  return decoded;
}

const authDisabledSession: AuthSession = {
  authenticated: true,
  role: "control",
  auth_disabled: true,
};

export async function fetchAuthSession(): Promise<AuthSession> {
  try {
    const response = await fetch("/auth/session");
    if (response.status === 404) return authDisabledSession;
    if (!response.ok) return { authenticated: false };
    return decodeAuthSession(await response.json());
  } catch (error: unknown) {
    console.error("Auth check failed:", error);
    return { authenticated: false };
  }
}

export async function login(passphrase: string): Promise<AuthSession> {
  const response = await fetch("/auth/login", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ passphrase }),
  });
  if (response.status === 404) return authDisabledSession;
  if (!response.ok) {
    const message = await response.text();
    throw new Error(message || "Login failed");
  }
  return decodeAuthSession(await response.json());
}

export async function logout(): Promise<void> {
  const response = await fetch("/auth/logout", { method: "POST" });
  if (response.status !== 404 && !response.ok) throw new Error("Logout failed");
}
