import { logger } from "../logger/index.mjs";
import { formatPaginatedResponse, formatResponse } from "../utils/responseData.mjs";
import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
import { countTags, createTag, deleteTagById, findTags, getTagById, updateTagById } from "../services/tag.service.mjs";
import { hasPermission } from "../utils/permissions.mjs";
import { getTagFiltersAndPagination } from "../utils/filtersAndPagination/getTagFiltersAndPagination.mjs";
import { mapTagToAPI, mapTagsToAPI } from "../utils/mapper/tag.mjs";
import { t } from "express-intlayer";

//#region src/controllers/tag.controller.ts
/**
* Retrieves a list of tags based on filters and pagination.
*/
const getTags = async (req, res, _next) => {
	const { user, organization, roles } = res.locals;
	const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } = getTagFiltersAndPagination(req, res);
	if (!user) {
		ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
		return;
	}
	if (!organization) {
		ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
		return;
	}
	try {
		const tags = await findTags(filters, skip, pageSize, sortOptions);
		if (!hasPermission(roles, "tag:read")({
			...res.locals,
			targetTags: tags
		})) {
			ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
			return;
		}
		const totalItems = await countTags(filters);
		const responseData = formatPaginatedResponse({
			data: mapTagsToAPI(tags),
			page,
			pageSize,
			totalPages: getNumberOfPages(totalItems),
			totalItems
		});
		res.json(responseData);
		return;
	} catch (error) {
		ErrorHandler.handleAppErrorResponse(res, error);
		return;
	}
};
/**
* Adds a new tag to the database.
*/
const addTag = async (req, res, _next) => {
	const { organization, project, user, roles } = res.locals;
	const tagData = req.body;
	if (!user) {
		ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
		return;
	}
	if (!organization) {
		ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
		return;
	}
	if (!project) {
		ErrorHandler.handleGenericErrorResponse(res, "PROJECT_NOT_DEFINED");
		return;
	}
	if (!tagData) ErrorHandler.handleGenericErrorResponse(res, "PROJECT_DATA_NOT_FOUND");
	const tag = {
		creatorId: user.id,
		organizationId: organization.id,
		projectId: project.id,
		...tagData
	};
	if (!hasPermission(roles, "tag:admin")({
		...res.locals,
		targetTags: [tag]
	})) {
		ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
		return;
	}
	try {
		const formattedTag = mapTagToAPI(await createTag(tag));
		const responseData = formatResponse({
			message: t({
				en: "Tag created successfully",
				fr: "Tag créé avec succès",
				es: "Tag creado con éxito"
			}),
			description: t({
				en: "Your tag has been created successfully",
				fr: "Votre tag a été créé avec succès",
				es: "Su tag ha sido creado con éxito"
			}),
			data: formattedTag
		});
		res.json(responseData);
		return;
	} catch (error) {
		ErrorHandler.handleAppErrorResponse(res, error);
		return;
	}
};
/**
* Updates an existing tag in the database.
*/
const updateTag = async (req, res, _next) => {
	const { tagId } = req.params;
	const { organization, user, roles } = res.locals;
	if (!user) {
		ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
		return;
	}
	if (!organization) {
		ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
		return;
	}
	try {
		const tag = {
			_id: tagId,
			name: req.body.name,
			key: req.body.key,
			description: req.body.description,
			instructions: req.body.instructions
		};
		const tagToDelete = await getTagById(tagId);
		if (!hasPermission(roles, "tag:write")({
			...res.locals,
			targetTags: [tagToDelete]
		})) {
			ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
			return;
		}
		if (String(tagToDelete.organizationId) !== String(organization.id)) {
			ErrorHandler.handleGenericErrorResponse(res, "TAG_NOT_IN_ORGANIZATION");
			return;
		}
		const formattedTag = mapTagToAPI(await updateTagById(tag._id, tag));
		const responseData = formatResponse({
			message: t({
				en: "Tag updated successfully",
				fr: "Tag mis à jour avec succès",
				es: "Tag actualizado con éxito"
			}),
			description: t({
				en: "Your tag has been updated successfully",
				fr: "Votre tag a été mis à jour avec succès",
				es: "Su tag ha sido actualizado con éxito"
			}),
			data: formattedTag
		});
		res.json(responseData);
		return;
	} catch (error) {
		ErrorHandler.handleAppErrorResponse(res, error);
		return;
	}
};
/**
* Deletes a tag from the database by its ID.
* @param req - Express request object.
* @param  res - Express response object.
* @returns Response confirming the deletion.
*/
const deleteTag = async (req, res, _next) => {
	const { user, organization, roles } = res.locals;
	const { tagId } = req.params;
	if (!user) {
		ErrorHandler.handleGenericErrorResponse(res, "USER_NOT_DEFINED");
		return;
	}
	if (!organization) {
		ErrorHandler.handleGenericErrorResponse(res, "ORGANIZATION_NOT_DEFINED");
		return;
	}
	if (!tagId) {
		ErrorHandler.handleGenericErrorResponse(res, "TAG_ID_NOT_FOUND");
		return;
	}
	try {
		const tagToDelete = await getTagById(tagId);
		if (!hasPermission(roles, "tag:admin")({
			...res.locals,
			targetTags: [tagToDelete]
		})) {
			ErrorHandler.handleGenericErrorResponse(res, "PERMISSION_DENIED");
			return;
		}
		if (String(tagToDelete.organizationId) !== String(organization.id)) {
			ErrorHandler.handleGenericErrorResponse(res, "TAG_NOT_IN_ORGANIZATION");
			return;
		}
		const deletedTag = await deleteTagById(tagId);
		if (!deletedTag) {
			ErrorHandler.handleGenericErrorResponse(res, "TAG_NOT_FOUND", { tagId });
			return;
		}
		logger.info(`Tag deleted: ${String(deletedTag.id)}`);
		const formattedTag = mapTagToAPI(deletedTag);
		const responseData = formatResponse({
			message: t({
				en: "Tag deleted successfully",
				fr: "Tag supprimé avec succès",
				es: "Tag eliminado con éxito"
			}),
			description: t({
				en: "Your tag has been deleted successfully",
				fr: "Votre tag a été supprimé avec succès",
				es: "Su tag ha sido eliminado con éxito"
			}),
			data: formattedTag
		});
		res.json(responseData);
		return;
	} catch (error) {
		ErrorHandler.handleAppErrorResponse(res, error);
		return;
	}
};

//#endregion
export { addTag, deleteTag, getTags, updateTag };
//# sourceMappingURL=tag.controller.mjs.map