import { defineStore } from "pinia";
import { computed, ref } from "vue";

import { api, ApiError } from "../api/client";

export type AccountIdentity = {
  id: number;
  username: string;
  is_admin: boolean;
  membership_status: string;
  membership_active: boolean;
  smart_access: boolean;
  badges: string[];
};

type AuthResponse = {
  account: AccountIdentity;
  csrf_token: string;
};

export const useSessionStore = defineStore("session", () => {
  const account = ref<AccountIdentity | null>(null);
  const initialized = ref(false);
  const busy = ref(false);

  const isAdmin = computed(() => account.value?.is_admin === true);
  const isMember = computed(() => account.value?.membership_active === true);

  async function restore(): Promise<void> {
    try {
      account.value = await api.get<AccountIdentity>("/auth/session");
    } catch (error) {
      if (!(error instanceof ApiError) || error.status !== 401) {
        throw error;
      }
      account.value = null;
    } finally {
      initialized.value = true;
    }
  }

  async function authenticate(mode: "login" | "register", username: string, password: string) {
    busy.value = true;
    try {
      const response = await api.post<AuthResponse>(`/auth/${mode}`, { username, password });
      account.value = response.account;
    } finally {
      busy.value = false;
    }
  }

  async function endSession(action: "logout" | "switch-account"): Promise<void> {
    await api.post(`/auth/${action}`);
    account.value = null;
  }

  async function refreshIdentity(): Promise<void> {
    account.value = await api.get<AccountIdentity>("/auth/session");
  }

  return {
    account,
    initialized,
    busy,
    isAdmin,
    isMember,
    restore,
    authenticate,
    endSession,
    refreshIdentity,
  };
});
