import { GenericError } from "../utils/errors/ErrorsClass.mjs";
import { validateOrganization } from "../utils/validation/validateOrganization.mjs";
import { OrganizationModel } from "../models/organization.model.mjs";

//#region src/services/organization.service.ts
/**
* Finds organizations 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.
* @returns List of organizations matching the filters.
*/
const findOrganizations = async (filters, skip, limit, sortOptions) => {
	let query = OrganizationModel.find(filters).skip(skip).limit(limit);
	if (sortOptions && Object.keys(sortOptions).length > 0) query = query.sort(sortOptions);
	return await query;
};
/**
* Finds an organization by its ID.
* @param organizationId - The ID of the organization to find.
* @returns The organization matching the ID.
*/
const getOrganizationById = async (organizationId) => {
	const organization = await OrganizationModel.findById(organizationId);
	if (!organization) throw new GenericError("ORGANIZATION_NOT_FOUND", { organizationId });
	return organization;
};
/**
* Counts the total number of organizations that match the filters.
* @param filters - MongoDB filter query.
* @returns Total number of organizations.
*/
const countOrganizations = async (filters) => {
	const result = await OrganizationModel.countDocuments(filters);
	if (typeof result === "undefined") throw new GenericError("ORGANIZATION_COUNT_FAILED", { filters });
	return result;
};
/**
* Creates a new organization in the database.
* @param organization - The organization data to create.
* @returns The created organization.
*/
const createOrganization = async (organization, userId) => {
	const errors = validateOrganization(organization, ["name"]);
	if (Object.keys(errors).length > 0) throw new GenericError("ORGANIZATION_INVALID_FIELDS", { errors });
	try {
		return await OrganizationModel.create({
			creatorId: userId,
			membersIds: [userId],
			adminsIds: [userId],
			...organization
		});
	} catch (error) {
		throw new GenericError("ORGANIZATION_CREATION_FAILED", { error: error.message });
	}
};
/**
* Updates an existing organization in the database by its ID.
* @param organizationId - The ID of the organization to update.
* @param organization - The updated organization data.
* @returns The updated organization.
*/
const updateOrganizationById = async (organizationId, organization) => {
	const errors = validateOrganization(organization, Object.keys(organization));
	if (Object.keys(errors).length > 0) throw new GenericError("ORGANIZATION_INVALID_FIELDS", {
		organizationId,
		errors
	});
	if ((await OrganizationModel.updateOne({ _id: organizationId }, organization)).matchedCount === 0) throw new GenericError("ORGANIZATION_UPDATE_FAILED", { organizationId });
	return await getOrganizationById(organizationId);
};
/**
* Deletes an organization from the database by its ID.
* @param organizationId - The ID of the organization to delete.
* @returns The result of the deletion operation.
*/
const deleteOrganizationById = async (organizationId) => {
	const organization = await OrganizationModel.findByIdAndDelete(organizationId);
	if (!organization) throw new GenericError("ORGANIZATION_NOT_FOUND", { organizationId });
	return organization;
};
/**
* Updates an existing plan in the database by its ID.
* @param planId - The ID of the plan to update.
* @param plan - The updated plan data.
* @returns The updated plan.
*/
const updatePlan = async (organization, plan) => {
	let prevPlan = organization.plan ?? {};
	if (typeof prevPlan?.toObject === "function") prevPlan = prevPlan.toObject();
	if ((await OrganizationModel.updateOne({ _id: organization.id }, { $set: { plan: {
		...prevPlan,
		...plan
	} } })).matchedCount === 0) throw new GenericError("ORGANIZATION_UPDATE_FAILED", { organizationId: organization.id });
	return await getOrganizationById(organization.id);
};

//#endregion
export { countOrganizations, createOrganization, deleteOrganizationById, findOrganizations, getOrganizationById, updateOrganizationById, updatePlan };
//# sourceMappingURL=organization.service.mjs.map