import { create } from "zustand";
import { authApi } from "../../shared/api/endpoints";
import { tokenStorage } from "../../shared/api/client";

const roleMap = {
  admin: "admin",
  administrator: "admin",
  user: "user",
  editor: "editor",
  moderator: "moderator",
  manager: "moderator",
  администратор: "admin",
  редактор: "editor",
  менеджер: "moderator",
  пользователь: "user",
};

function pickRole(user = {}) {
  const roles = Array.isArray(user.roles) ? user.roles : [user.role].filter(Boolean);
  const normalizedRoles = roles.map((role) => roleMap[String(role).toLowerCase()] ?? role);

  if (normalizedRoles.includes("admin")) return "admin";
  if (normalizedRoles.includes("moderator")) return "moderator";
  if (normalizedRoles.includes("editor")) return "editor";
  return "user";
}

function normalizeUser(user) {
  if (!user) return null;

  const roles = Array.isArray(user.roles) ? user.roles : [user.role].filter(Boolean);
  const role = pickRole(user);
  const login = user.login ?? user.username ?? "";

  return {
    ...user,
    login,
    email: user.email ?? (login && login.includes("@") ? login : ""),
    roles,
    role,
  };
}

function readStoredUser() {
  try {
    return normalizeUser(JSON.parse(sessionStorage.getItem("user") ?? "null"));
  } catch {
    return null;
  }
}

function persistUser(user) {
  const normalizedUser = normalizeUser(user);
  if (normalizedUser) sessionStorage.setItem("user", JSON.stringify(normalizedUser));
  else sessionStorage.removeItem("user");
}

function getToken(payload) {
  return payload?.accessToken ?? payload?.token ?? payload?.jwt;
}

function getUser(payload) {
  return normalizeUser(payload?.user ?? payload?.profile ?? payload);
}

export const useSession = create((set, get) => ({
  user: readStoredUser(),
  initializing: false,

  register: async (payload) => {
    const response = await authApi.register(payload);
    const token = getToken(response);
    const user = getUser(response);
    tokenStorage.set(token);
    set({ user });
    persistUser(user);
    return user;
  },

  login: async ({ identifier, email, login, password }) => {
    const credential = identifier ?? login ?? email;
    const response = await authApi.login({ login: credential, email: credential, password });
    const token = getToken(response);
    tokenStorage.set(token);

    const user = normalizeUser(response.user ?? (await authApi.me()));
    set({ user });
    persistUser(user);
    return user;
  },

  loadMe: async () => {
    if (!tokenStorage.get()) return get().user;

    set({ initializing: true });
    try {
      const user = normalizeUser(await authApi.me());
      set({ user, initializing: false });
      persistUser(user);
      return user;
    } catch (error) {
      set({ user: null, initializing: false });
      persistUser(null);
      throw error;
    }
  },

  logout: async () => {
    if (tokenStorage.get()) {
      try {
        await authApi.logout();
      } catch {
        // The local session still must be cleared if backend logout fails.
      }
    }

    tokenStorage.clear();
    persistUser(null);
    set({ user: null });
  },

  changePassword: (payload) => authApi.changePassword(payload),

  updateUser: (patch) => {
    const user = { ...get().user, ...patch };
    set({ user });
    persistUser(user);
    return user;
  },

  switchRole: (nextRole) => {
    const current = get().user;
    if (!current) return null;

    const user = normalizeUser({ ...current, role: nextRole });
    set({ user });
    persistUser(user);
    return user;
  },
}));

if (typeof window !== "undefined") {
  window.addEventListener("auth:unauthorized", () => {
    persistUser(null);
    useSession.setState({ user: null });
  });
}
