import { create } from "zustand";
import { persist } from "zustand/middleware";
import { useAlertStore } from "./useAlertStore";
import { logout } from "@/_lib/api/auth";

type Role = "candidate" | "manager";
type AuthType = "entra" | "local" | null;

type AuthState = {
  username: string | null;
  id: number | null;
  email: string | null;
  role: Role;
  authType: AuthType;
  access_token: string | null;
  setRole: (data: Role) => void;
  setAuth: (data: string) => void;
  setAuthState: (data: {
    role: Role;
    username: string;
    email: string;
    id: number;
  }) => void;
  login: (userData: {
    username: string | null;
    id: number | null;
    email: string | null;
    password: string | null;
    authType: string;
  }) => Promise<{
    username: string;
    role: Role;
    authType: "entra" | "local";
  } | null>;
  logout: () => Promise<void>;
  hasHydrated: boolean;
  setHasHydrated: (value: boolean) => void;
};

export const useAuthStore = create<AuthState>()(
  persist(
    (set, get) => ({
      username: null,
      email: null,
      id: null,
      role: "candidate",
      authType: null,
      access_token: null,
      setAuth: (data) => {
        set({
          access_token: data,
        });
      },
      setRole: (data) => {
        set({
          role: data as Role,
        });
      },
      setAuthState: (data) => {
        set({
          role: data.role as Role,
          id: data.id,
          username: data.username,
          email: data.email,
          authType: "entra",
        });
      },
      login: async ({ username, password, authType }) => {
        try {
          const res = await fetch(
            `${process.env.NEXT_PUBLIC_API_URL}/api/auth/login`,
            {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              credentials: "include",
              body: JSON.stringify({
                username,
                password,
                role: get().role,
                authType,
              }),
            }
          );

          if (!res.ok) {
            useAlertStore.getState().showAlert("Invalid credentials", "error");
            return;
          }

          const data = await res.json();

          const { user } = data;

          set({
            username: user.displayName,
            role: user.role as Role,
            authType: user.authType as "local" | "entra",
          });
          return user;
        } catch (error) {
          console.error(error);
          useAlertStore
            .getState()
            .showAlert("An error occurred during login.", "error");
        }
      },
      logout: async () => {
        try {
          await logout();
          set({
            username: null,
            email: null,
            id: null,
            role: "candidate",
            access_token: null,
            authType: null,
          });
          window.location.href = "/login";
          useAlertStore.getState().showAlert("Logout successful", "success");
        } catch (error) {
          console.error("Logout error:", error);
          useAlertStore
            .getState()
            .showAlert("An error occurred during logout.", "error");
        }
      },
      hasHydrated: false,
      setHasHydrated: (value) => set({ hasHydrated: value }),
    }),
    {
      name: "auth-storage",
      partialize: (state) => ({
        username: state.username,
        email: state.email,
        id: state.id,
        role: state.role,
        authType: state.authType,
        access_token: state.access_token,
        hasHydrated: state.hasHydrated,
      }),
      onRehydrateStorage: () => (state) => {
        state?.setHasHydrated(true);
      },
    }
  )
);
