import { GenericError } from "../utils/errors/ErrorsClass.mjs";
import { validateUser } from "../utils/validation/validateUser.mjs";
import { UserModel } from "../models/user.model.mjs";

//#region src/services/user.service.ts
/**
* Creates a new user with password in the database and hashes the password.
* @param user - User object with password not hashed.
* @returns Created user object.
*/
const createUser = async (user) => {
	const errors = validateUser(user, ["email"]);
	if (Object.keys(errors).length > 0) throw new GenericError("USER_INVALID_FIELDS", {
		userEmail: user.email,
		errors
	});
	const newUser = await UserModel.create(user);
	if (!newUser) throw new GenericError("USER_CREATION_FAILED", { userEmail: user.email });
	return newUser;
};
/**
* Retrieves a user by email.
* @param email - User's email.
* @returns User object or null if no user was found.
*/
const getUserByEmail = async (email) => {
	return await UserModel.findOne({ email });
};
/**
* Retrieves users list by email.
* @param emails - Users email.
* @returns User object or null if no user was found.
*/
const getUsersByEmails = async (emails) => {
	return await UserModel.find({ email: { $in: emails } });
};
/**
* Checks if a user exists by email.
* @param email - User's email.
* @returns True if the user exists, false otherwise.
*/
const checkUserExists = async (email) => {
	return await UserModel.exists({ email }) !== null;
};
/**
* Retrieves a user by ID.
* @param userId - User's ID.
* @returns User object or null if no user was found.
*/
const getUserById = async (userId) => await UserModel.findById(userId);
/**
* Retrieves a user by ID.
* @param userId - User's ID.
* @returns User object or null if no user was found.
*/
const getUsersByIds = async (userIds) => await UserModel.find({ _id: { $in: userIds } });
/**
* Finds users based on filters and pagination options.
* @param filters - MongoDB filter query.
* @param skip - Number of documents to skip.
* @param limit - Number of documents to limit.
* @param sortOptions - Sorting options.
* @returns List of users matching the filters.
*/
const findUsers = async (filters, skip, limit, sortOptions) => {
	let query = UserModel.find(filters).skip(skip).limit(limit);
	if (sortOptions && Object.keys(sortOptions).length > 0) query = query.sort(sortOptions);
	return await query;
};
/**
* Counts the total number of users that match the filters.
* @param filters - MongoDB filter query.
* @returns Total number of users.
*/
const countUsers = async (filters) => {
	const count = await UserModel.countDocuments(filters);
	if (typeof count === "undefined") throw new GenericError("USER_COUNT_FAILED");
	return count;
};
/**
* Updates a user's information.
* @param user - The user object.
* @param updates - The updates to apply to the user.
* @returns The updated user.
*/
const updateUserById = async (userId, updates) => {
	const errors = validateUser(updates, Object.keys(updates));
	if (Object.keys(errors).length > 0) throw new GenericError("USER_INVALID_FIELDS", {
		userId,
		errors
	});
	if ((await UserModel.updateOne({ _id: userId }, { $set: updates })).matchedCount === 0) throw new GenericError("USER_UPDATE_FAILED", { userId });
	const updatedUser = await UserModel.findById(userId);
	if (!updatedUser) throw new GenericError("USER_UPDATED_USER_NOT_FOUND", { userId });
	return updatedUser;
};
/**
* Deletes a user from the database.
* @param userId - The user object.
* @returns
*/
const deleteUser = async (userId) => {
	await getUserById(userId);
	const user = await UserModel.findByIdAndDelete(userId);
	if (!user) throw new GenericError("USER_NOT_FOUND", { userId });
	return user;
};

//#endregion
export { checkUserExists, countUsers, createUser, deleteUser, findUsers, getUserByEmail, getUserById, getUsersByEmails, getUsersByIds, updateUserById };
//# sourceMappingURL=user.service.mjs.map