import { computed, ref } from "vue";
import { defineStore } from "pinia";
import { authAPI, HWLAB_WEB_SESSION_COOKIE } from "@/api";
import type { AuthCapabilities, AuthCapabilityStatus, AuthSession, AuthState, AuthUser } from "@/types";
import { asRecord, nonEmptyString } from "@/utils";

export const useAuthStore = defineStore("auth", () => {
  const authState = ref<AuthState>("checking");
  const session = ref<AuthSession | null>(null);
  const error = ref<string | null>(null);
  const checked = ref(false);

  const isAuthenticated = computed(() => authState.value === "authenticated" && session.value?.authenticated === true);
  const user = computed(() => session.value?.user ?? session.value?.actor ?? null);
  const isAdmin = computed(() => session.value?.capabilities?.admin === "available" || user.value?.role === "admin");

  async function bootstrap(): Promise<void> {
    if (authState.value !== "checking") checked.value = true;
    const current = await authAPI.session();
    if (current.ok && current.data?.authenticated === true) {
      session.value = sessionFromPayload(current.data);
      authState.value = "authenticated";
      checked.value = true;
      document.body.dataset.authState = "authenticated";
      return;
    }
    const explicitUnauthenticated = current.status === 401 || current.status === 403 || (current.ok && current.data?.authenticated === false);
    if (!explicitUnauthenticated) {
      error.value = current.error || "认证状态暂时不可达，保持当前页面并稍后重试。";
      checked.value = authState.value === "authenticated";
      document.body.dataset.authState = authState.value === "authenticated" ? "authenticated" : "checking";
      return;
    }
    session.value = null;
    authState.value = "login";
    checked.value = true;
    document.body.dataset.authState = "login";
  }

  async function login(username: string, password: string): Promise<void> {
    error.value = null;
    const response = await authAPI.login(username.trim(), password);
    if (!response.ok || response.data?.authenticated !== true) {
      error.value = loginFailureMessage(response);
      authState.value = "login";
      return;
    }
    session.value = sessionFromPayload(response.data);
    authState.value = "authenticated";
    checked.value = true;
    document.body.dataset.authState = "authenticated";
  }

  async function register(payload: { email: string; username: string; displayName?: string; password: string }): Promise<void> {
    error.value = null;
    const response = await authAPI.register({
      email: payload.email.trim(),
      username: payload.username.trim(),
      displayName: payload.displayName?.trim() ?? "",
      password: payload.password
    });
    if (!response.ok || response.data?.authenticated !== true) {
      error.value = response.error || "注册失败，请检查邮箱、用户名和密码。";
      authState.value = "login";
      return;
    }
    session.value = sessionFromPayload(response.data);
    authState.value = "authenticated";
    checked.value = true;
    document.body.dataset.authState = "authenticated";
  }

  async function logout(): Promise<void> {
    await authAPI.logout();
    session.value = null;
    authState.value = "login";
    document.body.dataset.authState = "login";
  }

  return { authState, checked, session, error, isAuthenticated, user, isAdmin, bootstrap, login, register, logout, cookieName: HWLAB_WEB_SESSION_COOKIE };
});

function sessionFromPayload(payload: { authenticated?: boolean; authMethod?: unknown; identityAuthority?: unknown; sessionKind?: unknown; user?: unknown; actor?: unknown; capabilities?: unknown; expiresAt?: string | null; sessionExpiresAt?: string | null; valuesRedacted?: unknown }): AuthSession {
  return {
    authenticated: payload.authenticated === true,
    mode: "server",
    authMethod: nonEmptyString(payload.authMethod) ?? null,
    identityAuthority: nonEmptyString(payload.identityAuthority) ?? null,
    sessionKind: nonEmptyString(payload.sessionKind) ?? null,
    user: userFromUnknown(payload.user),
    actor: userFromUnknown(payload.actor),
    capabilities: capabilitiesFromUnknown(payload.capabilities),
    expiresAt: nonEmptyString(payload.expiresAt) ?? nonEmptyString(payload.sessionExpiresAt),
    valuesRedacted: payload.valuesRedacted === true
  };
}

function userFromUnknown(value: unknown): AuthUser | undefined {
  const record = asRecord(value);
  if (!record) return undefined;
  return { id: nonEmptyString(record.id) ?? undefined, username: nonEmptyString(record.username) ?? undefined, name: nonEmptyString(record.name) ?? undefined, displayName: nonEmptyString(record.displayName) ?? undefined, role: nonEmptyString(record.role) ?? undefined, status: nonEmptyString(record.status) ?? undefined };
}

function capabilitiesFromUnknown(value: unknown): AuthCapabilities | undefined {
  const record = asRecord(value);
  if (!record) return undefined;
  const output: AuthCapabilities = {};
  for (const [key, item] of Object.entries(record)) {
    const status = nonEmptyString(item) as AuthCapabilityStatus | undefined;
    if (status) output[key] = status;
  }
  return Object.keys(output).length > 0 ? output : undefined;
}

function loginFailureMessage(response: Awaited<ReturnType<typeof authAPI.login>>): string {
  const code = loginErrorCode(response.data) ?? nonEmptyString(response.error);
  const normalizedCode = code?.trim().toLowerCase().replace(/_/gu, "-") ?? "";
  if (response.status === 401 || response.status === 403 || ["invalid-credentials", "unauthorized", "forbidden"].includes(normalizedCode)) {
    return "账号或密码不正确，请重新输入。";
  }
  if (response.status === 0) {
    return "登录服务暂时不可达，请稍后重试。";
  }
  if (response.status >= 500 || /(?:upstream|unavailable|timeout|proxy|bad-gateway)/u.test(normalizedCode)) {
    return code ? `登录服务暂时不可用，请稍后重试。错误码：${code}` : "登录服务暂时不可用，请稍后重试。";
  }
  return response.error ? `登录失败：${response.error}` : "登录失败，请稍后重试。";
}

function loginErrorCode(payload: unknown): string | null {
  const record = asRecord(payload);
  const error = asRecord(record?.error);
  return nonEmptyString(error?.code) ?? nonEmptyString(record?.code);
}
