import { baseApi } from "@/store/api/baseApi";
import { User } from "@/store/models/User.model";
import { RiskEnum } from "@/constants/riskEnum";
import { TableSortDirection } from "@/constants/tableSortDirectionEnum";

export type UsersQueryParams = {
  page?: number;
  limit?: number;
  search?: string;
  risks?: RiskEnum[];
  sortBy?: "name" | "email" | "title" | "role" | "risk";
  sortDir?: TableSortDirection;
  roleType?: "user" | "admin";
};

export type PaginatedUsers = {
  items: User[];
  total: number;
  page: number;
  limit: number;
};

export type UserLoginLog = {
  id: string;
  name: string;
  email: string;
  lastLoginAt: string | Date;
  activity: string;
  status?: "SUCCESS" | "FAILURE";
  failureReason?:
    | "MISSING_CREDENTIALS"
    | "INVALID_CREDENTIALS"
    | "WRONG_PASSWORD"
    | "ACCOUNT_LOCKED"
    | "NOT_ACTIVATED"
    | "NOT_ALLOWED"
    | "UNKNOWN";
};

const normalizeSortDir = (dir?: TableSortDirection) => {
  return dir
    ? dir === TableSortDirection.DESCENDING
      ? "desc"
      : "asc"
    : undefined;
};

const buildUserParams = (params?: UsersQueryParams) => {
  if (!params) return {};

  const { page, limit, search, risks, sortBy, sortDir, roleType } = params;

  return {
    ...(page !== undefined && { page }),
    ...(limit !== undefined && { limit }),
    ...(search && { search }),
    ...(risks?.length && { risks: risks.join(",") }),
    ...(sortBy && { sortBy }),
    ...(sortDir && { sortDir: normalizeSortDir(sortDir) }),
    ...(roleType && { roleType }),
  };
};

const buildLogParams = (params?: {
  page?: number;
  limit?: number;
  search?: string;
}) => {
  if (!params) return {};

  const { page, limit, search } = params;

  return {
    ...(page !== undefined && { page }),
    ...(limit !== undefined && { limit }),
    ...(search && { search }),
  };
};

export const usersApi = baseApi.injectEndpoints({
  overrideExisting: true,
  endpoints: (builder) => ({
    getUserLogs: builder.query<
      { items: UserLoginLog[]; total: number; page: number; limit: number },
      { page?: number; limit?: number; search?: string } | undefined
    >({
      query: (params) => ({
        url: "/users/logs",
        params: buildLogParams(params),
      }),
      providesTags: ["UserLogs"],
    }),

    getUserLogsById: builder.query<
      { items: UserLoginLog[]; total: number; page: number; limit: number },
      { userId: string; page?: number; limit?: number }
    >({
      query: ({ userId, page, limit }) => ({
        url: `/users/${userId}/logs`,
        params: {
          ...(page !== undefined && { page }),
          ...(limit !== undefined && { limit }),
        },
      }),
      providesTags: (_res, _err, { userId }) => [
        "UserLogs",
        { type: "UserLogs", id: userId } as any,
      ],
    }),

    getUsers: builder.query<PaginatedUsers, UsersQueryParams | undefined>({
      query: (params) => ({ url: "/users", params: buildUserParams(params) }),
      providesTags: (result) => [
        "Users",
        ...(result?.items ?? []).map(
          ({ id }) => ({ type: "Users", id }) as const,
        ),
      ],
    }),

    getUserById: builder.query<User, string>({
      query: (id) => `/users/${id}`,
      providesTags: (_res, _err, id) => [{ type: "Users", id }],
    }),

    deleteUser: builder.mutation<void, string>({
      query: (id) => ({ url: `/users/${id}`, method: "DELETE" }),
      invalidatesTags: ["Users"],
    }),

    deleteUsers: builder.mutation<void, string[]>({
      query: (ids) => ({ url: "/users", method: "DELETE", body: { ids } }),
      invalidatesTags: ["Users"],
    }),

    lockUser: builder.mutation<void, string>({
      query: (id) => ({ url: `/users/${id}/lock`, method: "PUT" }),
      invalidatesTags: ["Users"],
    }),

    updateUser: builder.mutation<User, Partial<User>>({
      query: (user) => ({
        url: `/users/${user.id}`,
        method: "PUT",
        body: user,
      }),
      invalidatesTags: (_res, _err, { id }) => [
        "Users",
        { type: "Users", id },
        "Todos",
      ],
    }),

    createUser: builder.mutation<User, Partial<User>>({
      query: (user) => ({ url: "/users", method: "POST", body: user }),
      invalidatesTags: ["Users"],
    }),

    resendInvitation: builder.mutation<{ message: string }, string>({
      query: (id) => ({ url: `/users/${id}/invite`, method: "POST" }),
      invalidatesTags: (_res, _err, id) => ["Users", { type: "Users", id }],
    }),
  }),
});

export const {
  useGetUserLogsQuery,
  useGetUserLogsByIdQuery,
  useGetUsersQuery,
  useGetUserByIdQuery,
  useDeleteUserMutation,
  useDeleteUsersMutation,
  useLockUserMutation,
  useUpdateUserMutation,
  useCreateUserMutation,
  useResendInvitationMutation,
} = usersApi;
