import { logger } from "../logger/index.mjs";
import { formatPaginatedResponse, formatResponse } from "../utils/responseData.mjs";
import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
import { hasPermission } from "../utils/permissions.mjs";
import { countUsers, createUser as createUser$1, deleteUser as deleteUser$1, findUsers, getUserByEmail as getUserByEmail$1, getUserById as getUserById$1, updateUserById } from "../services/user.service.mjs";
import { mapUserToAPI, mapUsersToAPI } from "../utils/mapper/user.mjs";
import { sendEmail } from "../services/email.service.mjs";
import { getUserFiltersAndPagination } from "../utils/filtersAndPagination/getUserFiltersAndPagination.mjs";
import { t } from "fastify-intlayer";

//#region src/controllers/user.controller.ts
/**
* Creates a new user.
*/
const createUser = async (request, reply) => {
	const user = request.body;
	if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
	try {
		const newUser = await createUser$1(user);
		await sendEmail({
			type: "welcome",
			to: newUser.email,
			username: newUser.name,
			loginLink: `${process.env.APP_URL}/auth/login`
		});
		const formattedUser = mapUserToAPI(newUser);
		const responseData = formatResponse({
			message: t({
				en: "User created",
				fr: "Utilisateur créé",
				es: "Usuario creado"
			}),
			description: t({
				en: "User created successfully",
				fr: "Utilisateur créé avec succès",
				es: "Usuario creado con éxito"
			}),
			data: formattedUser
		});
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of users based on filters and pagination.
*/
const getUsers = async (request, reply) => {
	const { user, roles } = request.locals || {};
	if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
	const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } = getUserFiltersAndPagination(request);
	try {
		const users = await findUsers(filters, skip, pageSize, sortOptions);
		if (!hasPermission(roles || [], "user:read")({
			...request.locals,
			targetUsers: users
		})) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
		const totalItems = await countUsers(filters);
		const responseData = formatPaginatedResponse({
			data: mapUsersToAPI(users),
			page,
			pageSize,
			totalPages: getNumberOfPages(totalItems),
			totalItems
		});
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
const getUserById = async (request, reply) => {
	const { userId } = request.params;
	try {
		const user = await getUserById$1(userId);
		if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
		const responseData = formatResponse({ data: mapUserToAPI(user) });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
const getUserByEmail = async (request, reply) => {
	const { email } = request.params;
	const { roles } = request.locals || {};
	try {
		const user = await getUserByEmail$1(email);
		if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
		if (!hasPermission(roles || [], "user:read")({
			...request.locals,
			targetUsers: [user]
		})) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
		const responseData = formatResponse({ data: mapUserToAPI(user) });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Updates user information (phone number, date of birth).
*/
const updateUser = async (request, reply) => {
	const userData = request.body;
	const { user, roles } = request.locals || {};
	if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
	if (typeof userData !== "object") return ErrorHandler.handleGenericErrorResponse(reply, "USER_DATA_NOT_FOUND");
	if (!userData.id) return ErrorHandler.handleGenericErrorResponse(reply, "USER_INVALID_FIELDS");
	const userDB = await getUserById$1(userData.id);
	if (!userDB) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_FOUND");
	if (!hasPermission(roles || [], "user:write")({
		...request.locals,
		targetUsers: [userDB]
	})) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
	try {
		const updatedUser = await updateUserById(userDB.id, userData);
		logger.info(`User updated: Name: ${updatedUser.name}, id: ${String(updatedUser.id)}`);
		const formattedUser = mapUserToAPI(updatedUser);
		const responseData = formatResponse({
			message: t({
				en: "User updated",
				fr: "Utilisateur mis à jour",
				es: "Usuario actualizado"
			}),
			description: t({
				en: "User updated successfully",
				fr: "Utilisateur mis à jour avec succès",
				es: "Usuario actualizado con éxito"
			}),
			data: formattedUser
		});
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Deletes a user based on the provided ID.
*/
const deleteUser = async (request, reply) => {
	const { userId } = request.params;
	const { roles } = request.locals || {};
	try {
		const user = await getUserById$1(userId);
		if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_FOUND");
		if (!hasPermission(roles || [], "user:admin")({
			...request.locals,
			targetUsers: [user]
		})) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
		await deleteUser$1(userId);
		const formattedUser = mapUserToAPI(user);
		const responseData = formatResponse({
			message: t({
				en: "User deleted",
				fr: "Utilisateur supprimé",
				es: "Usuario eliminado"
			}),
			description: t({
				en: "User deleted successfully",
				fr: "Utilisateur supprimé avec succès",
				es: "Usuario eliminado con éxito"
			}),
			data: formattedUser
		});
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
let clients = [];
const sendVerificationUpdate = (user) => {
	const filteredClients = clients.filter((client) => String(client.userId) === String(user.id));
	for (const client of filteredClients) if (user.emailVerified) client.res.raw.write(`data: ${JSON.stringify({
		userId: user.id,
		status: "verified"
	})}\n\n`);
};
/**
* SSE to check the email verification status
*/
const verifyEmailStatusSSE = async (request, reply) => {
	reply.raw.setHeader("Content-Type", "text/event-stream;charset=utf-8");
	reply.raw.setHeader("Cache-Control", "no-cache, no-transform");
	reply.raw.setHeader("Connection", "keep-alive");
	reply.raw.setHeader("X-Accel-Buffering", "no");
	reply.raw.write(":\n\n");
	reply.raw.flushHeaders?.();
	const { userId } = request.params;
	const clientId = Date.now();
	const user = await getUserById$1(userId);
	if (!user) {
		logger.error(`User not found - User ID: ${userId}`);
		reply.raw.write(`data: ${JSON.stringify({
			userId,
			status: "error"
		})}\n\n`);
		reply.raw.end();
		return;
	}
	const newClient = {
		id: clientId,
		userId,
		res: { raw: reply.raw }
	};
	clients.push(newClient);
	sendVerificationUpdate(user);
	request.raw.on("close", () => {
		clients = clients.filter((client) => client.id !== clientId);
	});
};

//#endregion
export { createUser, deleteUser, getUserByEmail, getUserById, getUsers, sendVerificationUpdate, updateUser, verifyEmailStatusSSE };
//# sourceMappingURL=user.controller.mjs.map