import { logger } from "../logger/index.mjs";
import { formatPaginatedResponse, formatResponse } from "../utils/responseData.mjs";
import { ErrorHandler } from "../utils/errors/ErrorHandler.mjs";
import { getDictionariesByTags } from "../services/dictionary.service.mjs";
import { findTags, getTagsByKeys } from "../services/tag.service.mjs";
import { askDocQuestion as askDocQuestion$1 } from "../utils/AI/askDocQuestion/askDocQuestion.mjs";
import { aiDefaultOptions, auditDictionary } from "../utils/AI/auditDictionary/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$1, auditDictionaryField } from "../utils/AI/auditDictionaryField/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$2, auditDictionaryMetadata as auditDictionaryMetadata$1 } from "../utils/AI/auditDictionaryMetadata/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$3, auditTag as auditTag$1 } from "../utils/AI/auditTag/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$4, autocomplete as autocomplete$1 } from "../utils/AI/autocomplete/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$5, customQuery as customQuery$2 } from "../utils/AI/customQuery/index.mjs";
import { aiDefaultOptions as aiDefaultOptions$6, translateJSON as translateJSON$2 } from "../utils/AI/translateJSON/index.mjs";
import { getDiscussionFiltersAndPagination } from "../utils/filtersAndPagination/getDiscussionFiltersAndPagination.mjs";
import { DiscussionModel } from "../models/discussion.model.mjs";
import { getAIConfig } from "@intlayer/ai";

//#region src/controllers/ai.controller.ts
const customQuery = async (request, reply) => {
	const { aiOptions, tagsKeys, ...rest } = request.body;
	const { user, project } = request.locals || {};
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			projectOptions: projectAIOptions,
			defaultOptions: aiDefaultOptions$5,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		const auditResponse = await customQuery$2({
			...rest,
			aiConfig
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "QUERY_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
const translateJSON = async (request, reply) => {
	const { project, user } = request.locals || {};
	const { aiOptions, tagsKeys, ...rest } = request.body;
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			projectOptions: projectAIOptions,
			defaultOptions: aiDefaultOptions$6,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		let tags = [];
		if (project?.organizationId && tagsKeys) tags = await getTagsByKeys(tagsKeys, project.organizationId);
		const auditResponse = await translateJSON$2({
			...rest,
			aiConfig,
			applicationContext: aiOptions?.applicationContext,
			tags
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "AUDIT_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of dictionaries based on filters and pagination.
*/
const auditContentDeclaration = async (request, reply) => {
	const { project, user } = request.locals || {};
	const { fileContent, filePath, aiOptions, locales, defaultLocale, tagsKeys } = request.body;
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			projectOptions: projectAIOptions,
			defaultOptions: aiDefaultOptions,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		let tags = [];
		if (project?.organizationId) tags = await getTagsByKeys(tagsKeys ?? [], project.organizationId);
		const auditResponse = await auditDictionary({
			fileContent,
			filePath,
			aiConfig,
			applicationContext: aiOptions?.applicationContext,
			locales,
			defaultLocale,
			tags
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "AUDIT_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of dictionaries based on filters and pagination.
*/
const auditContentDeclarationField = async (request, reply) => {
	const { project, user } = request.locals || {};
	const { fileContent, aiOptions, locales, tagsKeys, keyPath } = request.body;
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			projectOptions: projectAIOptions,
			defaultOptions: aiDefaultOptions$1,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		let tags = [];
		if (project?.organizationId) tags = await getTagsByKeys(tagsKeys ?? [], project.organizationId);
		const auditResponse = await auditDictionaryField({
			fileContent,
			aiConfig,
			applicationContext: aiOptions?.applicationContext,
			locales,
			tags,
			keyPath
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "AUDIT_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of dictionaries based on filters and pagination.
*/
const auditContentDeclarationMetadata = async (request, reply) => {
	const { organization, user } = request.locals || {};
	const { fileContent, aiOptions } = request.body;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			defaultOptions: aiDefaultOptions$2,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		const tags = await findTags({ organizationId: organization?.id }, 0, 1e3);
		const auditResponse = await auditDictionaryMetadata$1({
			fileContent,
			aiConfig,
			applicationContext: aiOptions?.applicationContext,
			tags
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "AUDIT_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of dictionaries based on filters and pagination.
*/
const auditTag = async (request, reply) => {
	const { project, user } = request.locals || {};
	const { aiOptions, tag } = request.body;
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		aiConfig = await getAIConfig({
			userOptions: aiOptions,
			projectOptions: projectAIOptions,
			defaultOptions: aiDefaultOptions$3,
			accessType: ["registered_user", "apiKey"]
		}, !!user);
	} catch (_error) {
		return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
	}
	try {
		let dictionaries = [];
		if (project?.organizationId) dictionaries = await getDictionariesByTags([tag.key], project.id);
		const auditResponse = await auditTag$1({
			aiConfig,
			dictionaries,
			tag,
			applicationContext: aiOptions?.applicationContext
		});
		if (!auditResponse) return ErrorHandler.handleGenericErrorResponse(reply, "AUDIT_FAILED");
		const responseData = formatResponse({ data: auditResponse });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
const askDocQuestion = async (request, reply) => {
	const { messages = [], discussionId } = request.body;
	const { user, project, organization } = request.locals || {};
	reply.hijack();
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	let aiConfig;
	try {
		try {
			aiConfig = await getAIConfig({
				userOptions: {},
				projectOptions: projectAIOptions,
				accessType: ["public"]
			}, !!user);
		} catch (_error) {
			reply.raw.write(`event: error\ndata: ${JSON.stringify({
				code: "AI_ACCESS_DENIED",
				title: "Access Denied",
				message: "Unable to configure AI access."
			})}\n\n`);
			reply.raw.end();
			return;
		}
		const headers = reply.getHeaders();
		for (const [key, value] of Object.entries(headers)) if (value !== void 0) reply.raw.setHeader(key, value);
		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");
		if (reply.raw.flushHeaders) reply.raw.flushHeaders();
		reply.raw.write(": connected\n\n");
		const fullResponse = await askDocQuestion$1(messages, aiConfig, { onMessage: (chunk) => {
			if (!reply.raw.writableEnded) reply.raw.write(`data: ${JSON.stringify({ chunk })}\n\n`);
		} });
		const lastUserMessageContent = messages.findLast((m) => m.role === "user")?.content;
		if ((lastUserMessageContent ? lastUserMessageContent.split(" ").length : 0) > 2) await DiscussionModel.findOneAndUpdate({ discussionId }, { $set: {
			discussionId,
			userId: user?.id,
			projectId: project?.id,
			organizationId: organization?.id,
			messages: [...messages.map((msg) => ({
				role: msg.role,
				content: msg.content,
				timestamp: msg.timestamp
			})), {
				role: "assistant",
				content: fullResponse.response,
				relatedFiles: fullResponse.relatedFiles,
				timestamp: /* @__PURE__ */ new Date()
			}]
		} }, {
			upsert: true,
			new: true
		});
		if (!reply.raw.writableEnded) {
			reply.raw.write(`data: ${JSON.stringify({
				done: true,
				response: fullResponse
			})}\n\n`);
			reply.raw.end();
		}
	} catch (err) {
		const errorMessage = err instanceof Error ? err.message : String(err);
		const errorStack = err instanceof Error ? err.stack : void 0;
		logger.error("AI Stream Error Caught:", {
			message: errorMessage,
			stack: errorStack
		});
		const isAuthError = errorMessage.includes("401") || errorMessage.includes("Incorrect API key");
		const errorPayload = {
			code: isAuthError ? "AI_AUTH_ERROR" : "AI_STREAM_ERROR",
			title: isAuthError ? "AI Configuration Error" : "Generation Failed",
			message: errorMessage
		};
		if (!reply.raw.writableEnded) {
			reply.raw.write(`event: error\ndata: ${JSON.stringify(errorPayload)}\n\n`);
			reply.raw.end();
		}
	}
};
const autocomplete = async (request, reply) => {
	const { user, project } = request.locals || {};
	const projectAIOptions = project?.configuration?.ai ? project.configuration.ai : void 0;
	try {
		const { text, aiOptions, contextBefore, currentLine, contextAfter } = request.body;
		let aiConfig;
		try {
			aiConfig = await getAIConfig({
				userOptions: aiOptions,
				projectOptions: projectAIOptions,
				defaultOptions: aiDefaultOptions$4,
				accessType: ["public"]
			}, !!user);
		} catch (_error) {
			return ErrorHandler.handleGenericErrorResponse(reply, "AI_ACCESS_DENIED");
		}
		const responseData = formatResponse({ data: await autocomplete$1({
			text,
			aiConfig,
			applicationContext: aiOptions?.applicationContext,
			contextBefore,
			currentLine,
			contextAfter
		}) ?? {
			autocompletion: "",
			tokenUsed: 0
		} });
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};
/**
* Retrieves a list of discussions with filters and pagination.
* Only the owner or admins can access. By default, users only see their own.
*/
const getDiscussions = async (request, reply) => {
	const { user, roles } = request.locals || {};
	const { filters, sortOptions, pageSize, skip, page, getNumberOfPages } = getDiscussionFiltersAndPagination(request);
	const includeMessages = request.query?.includeMessages !== "false";
	if (!user) return ErrorHandler.handleGenericErrorResponse(reply, "USER_NOT_DEFINED");
	try {
		const projection = includeMessages ? {} : { messages: 0 };
		const discussions = await DiscussionModel.find(filters, projection).sort(sortOptions).skip(skip).limit(pageSize).lean();
		const numberOfMessagesById = {};
		if (!includeMessages && discussions.length > 0) {
			const ids = discussions.map((d) => d._id);
			const counts = await DiscussionModel.aggregate([{ $match: { _id: { $in: ids } } }, { $project: { numberOfMessages: { $size: { $ifNull: ["$messages", []] } } } }]);
			for (const c of counts) numberOfMessagesById[String(c._id)] = c.numberOfMessages ?? 0;
		}
		const allOwnedByUser = discussions.every((d) => String(d.userId) === String(user.id));
		if (!(roles?.includes("admin") || allOwnedByUser)) return ErrorHandler.handleGenericErrorResponse(reply, "PERMISSION_DENIED");
		const totalItems = await DiscussionModel.countDocuments(filters);
		const responseData = formatPaginatedResponse({
			data: discussions.map((d) => ({
				...d,
				id: String(d._id ?? d.id),
				numberOfMessages: includeMessages ? Array.isArray(d.messages) ? d.messages.length : 0 : numberOfMessagesById[String(d._id ?? d.id)] ?? 0
			})),
			page,
			pageSize,
			totalPages: getNumberOfPages(totalItems),
			totalItems
		});
		return reply.send(responseData);
	} catch (error) {
		return ErrorHandler.handleAppErrorResponse(reply, error);
	}
};

//#endregion
export { askDocQuestion, auditContentDeclaration, auditContentDeclarationField, auditContentDeclarationMetadata, auditTag, autocomplete, customQuery, getDiscussions, translateJSON };
//# sourceMappingURL=ai.controller.mjs.map