const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
const require_utils_ensureMongoDocumentToObject = require('../utils/ensureMongoDocumentToObject.cjs');
const require_utils_errors_ErrorsClass = require('../utils/errors/ErrorsClass.cjs');
const require_services_organization_service = require('./organization.service.cjs');
const require_models_project_model = require('../models/project.model.cjs');
const require_services_user_service = require('./user.service.cjs');
const require_utils_mapper_user = require('../utils/mapper/user.cjs');
const require_utils_mapper_organization = require('../utils/mapper/organization.cjs');
const require_utils_mapper_project = require('../utils/mapper/project.cjs');
const require_models_oAuth2_model = require('../models/oAuth2.model.cjs');
const require_utils_oAuth2 = require('../utils/oAuth2.cjs');
let node_crypto = require("node:crypto");
node_crypto = require_rolldown_runtime.__toESM(node_crypto);

//#region src/services/oAuth2.service.ts
/**
* Function to generate client credentials
*
* @returns The client id and client secret
*/
const generateClientCredentials = () => {
	return {
		clientId: (0, node_crypto.randomBytes)(16).toString("hex"),
		clientSecret: (0, node_crypto.randomBytes)(32).toString("hex")
	};
};
/**
* Method to get the client and the project
*
* @param clientId - The client id
* @param clientSecret - The client secret
* @returns The an object containing the client, the rights and the project or false if not found
*/
const getClientAndProjectByClientId = async (clientId) => {
	const project = await require_models_project_model.ProjectModel.findOne({ "oAuth2Access.clientId": clientId });
	if (!project) return false;
	const oAuth2Access = project.oAuth2Access.find((access) => access.clientId === clientId);
	if (!oAuth2Access) return false;
	return {
		client: {
			id: oAuth2Access.clientId,
			clientId,
			clientSecret: oAuth2Access.clientSecret,
			grants: ["client_credentials"]
		},
		oAuth2Access,
		grants: oAuth2Access.grants,
		project
	};
};
/**
* Get the client and verify that the client secret is correct
*
* @param clientId - The client id
* @param clientSecret - The client secret
* @returns The client or false if not found
*/
const getClient = async (clientId, clientSecret) => {
	const result = await getClientAndProjectByClientId(clientId);
	if (!result) return false;
	const { client } = result;
	if (!client || client.clientSecret !== clientSecret) return false;
	return client;
};
/**
* Format an OAuth2Token
*
* @param token - The token to format
* @param client - The client
* @param user - The user
* @param project - The project
* @param organization - The organization
* @param grants - The grants
* @returns The formatted token
*/
const formatOAuth2Token = (token, client, user, project, organization, grants) => {
	const { clientId, userId,...restToken } = token;
	if (String(userId) !== String(user.id)) throw new require_utils_errors_ErrorsClass.GenericError("USER_ID_MISMATCH");
	return {
		...restToken,
		client,
		user: require_utils_mapper_user.mapUserToAPI(user),
		organization: require_utils_mapper_organization.mapOrganizationToAPI(organization),
		project: require_utils_mapper_project.mapProjectToAPI(project),
		accessToken: token.accessToken,
		accessTokenExpiresAt: token.accessTokenExpiresAt ?? /* @__PURE__ */ new Date("999-99-99"),
		grants
	};
};
/**
* Format a auth token for the database
*
* @param token - The oAuth2 token to format
* @param clientId - The client ID
* @param userId - The user ID
* @returns
*/
const formatDBToken = (token, clientId, userId) => {
	return {
		id: token.id,
		clientId,
		userId,
		accessToken: token.accessToken,
		expiresIn: token.accessTokenExpiresAt ?? require_utils_oAuth2.getTokenExpireAt()
	};
};
/**
* Method to save the token
*
* @param token - The token
* @param client - The client
* @param user - The user
* @returns The saved token or false if not saved
*/
const saveToken = async (token, client, user) => {
	const formattedAccessToken = formatDBToken(token, client.id, user.id);
	const result = await require_models_oAuth2_model.OAuth2AccessTokenModel.create(formattedAccessToken);
	if (!result) return false;
	const result2 = await getClientAndProjectByClientId(result.clientId);
	if (!result2) return false;
	const { project } = result2;
	const organization = await require_services_organization_service.getOrganizationById(project.organizationId);
	if (!organization) return false;
	return formatOAuth2Token(formattedAccessToken, client, user, project, organization, token.rights);
};
/**
* Method to get the access token
*
* @param accessToken - The access token
* @returns The access token or false if not found
*/
const getAccessToken = async (accessToken) => {
	const token = await require_models_oAuth2_model.OAuth2AccessTokenModel.findOne({ accessToken });
	if (!token) return false;
	const { userId, clientId } = token;
	const user = await require_services_user_service.getUserById(userId);
	if (!user) return false;
	const result = await getClientAndProjectByClientId(clientId);
	if (!result) return false;
	const { client, project, grants } = result;
	const organization = await require_services_organization_service.getOrganizationById(project.organizationId);
	if (!organization) return false;
	return formatOAuth2Token(token, client, user, project, organization, grants);
};
/**
* Method to get the user from the client
*
* @param client - The client
* @returns The user or false if not found
*/
const getUserFromClient = async (client) => {
	const response = await getClientAndProjectByClientId(client.id);
	if (!response) return false;
	const { userId } = response.oAuth2Access;
	if (!userId) return false;
	return await require_services_user_service.getUserById(userId) ?? false;
};
/**
* Method to verify the permissions (grants)
*
* @param token - The token
* @param scope - The scope
* @returns True if the token has the required scope, false otherwise
*/
const verifyScope = async (_token, _scope, _callback) => {
	return true;
};
/**
* Validate OAuth2 access token and return user context
*/
const validateOAuth2AccessToken = async (accessToken) => {
	try {
		const token = await require_models_oAuth2_model.OAuth2AccessTokenModel.findOne({ accessToken });
		if (!token) throw new require_utils_errors_ErrorsClass.GenericError("INVALID_ACCESS_TOKEN");
		if (/* @__PURE__ */ new Date() > new Date(token.expiresIn)) throw new require_utils_errors_ErrorsClass.GenericError("EXPIRED_ACCESS_TOKEN");
		return require_utils_ensureMongoDocumentToObject.ensureMongoDocumentToObject(token);
	} catch (_error) {
		throw new require_utils_errors_ErrorsClass.GenericError("INVALID_ACCESS_TOKEN");
	}
};
/**
* Validate OAuth2 access token and return user context
*/
const getOAuth2AccessTokenContext = async (token) => {
	const { userId, clientId } = token;
	const user = await require_services_user_service.getUserById(String(userId));
	const result = await getClientAndProjectByClientId(clientId);
	if (!result) throw new require_utils_errors_ErrorsClass.GenericError("INVALID_ACCESS_TOKEN");
	const { project, grants } = result;
	const organization = await require_services_organization_service.getOrganizationById(project.organizationId);
	return {
		accessToken: token.accessToken,
		user: user ? require_utils_mapper_user.mapUserToAPI(user) : void 0,
		project: project ? require_utils_mapper_project.mapProjectToAPI(project) : void 0,
		organization: organization ? require_utils_mapper_organization.mapOrganizationToAPI(organization) : void 0,
		grants
	};
};

//#endregion
exports.formatDBToken = formatDBToken;
exports.formatOAuth2Token = formatOAuth2Token;
exports.generateClientCredentials = generateClientCredentials;
exports.getAccessToken = getAccessToken;
exports.getClient = getClient;
exports.getClientAndProjectByClientId = getClientAndProjectByClientId;
exports.getOAuth2AccessTokenContext = getOAuth2AccessTokenContext;
exports.getUserFromClient = getUserFromClient;
exports.saveToken = saveToken;
exports.validateOAuth2AccessToken = validateOAuth2AccessToken;
exports.verifyScope = verifyScope;
//# sourceMappingURL=oAuth2.service.cjs.map