"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
var TriggerMcpClientSubscriberDatabase_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TriggerMcpClientSubscriberDatabase = void 0;
const common_1 = require("@nestjs/common");
const model_metadata_service_1 = require("../../services/model-metadata.service");
const solid_registry_1 = require("../../helpers/solid-registry");
const dashboard_repository_1 = require("../../repository/dashboard.repository");
const ai_interaction_service_1 = require("../../services/ai-interaction.service");
const module_metadata_service_1 = require("../../services/module-metadata.service");
const poller_service_1 = require("../../services/poller.service");
const database_subscriber_service_1 = require("../../services/queues/database-subscriber.service");
const typeorm_1 = require("typeorm");
const mq_message_queue_service_1 = require("../../services/mq-message-queue.service");
const mq_message_service_1 = require("../../services/mq-message.service");
const trigger_mcp_client_queue_options_1 = __importDefault(require("./trigger-mcp-client-queue-options"));
let TriggerMcpClientSubscriberDatabase = TriggerMcpClientSubscriberDatabase_1 = class TriggerMcpClientSubscriberDatabase extends database_subscriber_service_1.DatabaseSubscriber {
    constructor(mqMessageService, mqMessageQueueService, poller, aiInteractionService, moduleMetadataService, modelMetadataService, solidRegistry, dashboardRepository) {
        super(mqMessageService, mqMessageQueueService, poller);
        this.mqMessageService = mqMessageService;
        this.mqMessageQueueService = mqMessageQueueService;
        this.poller = poller;
        this.aiInteractionService = aiInteractionService;
        this.moduleMetadataService = moduleMetadataService;
        this.modelMetadataService = modelMetadataService;
        this.solidRegistry = solidRegistry;
        this.dashboardRepository = dashboardRepository;
        this.triggerMcpClientSubscriberLogger = new common_1.Logger(TriggerMcpClientSubscriberDatabase_1.name);
    }
    options() {
        return {
            ...trigger_mcp_client_queue_options_1.default
        };
    }
    cleanNestedResponse(aiResponse) {
        let nestedResponse;
        try {
            let raw = aiResponse.response;
            if (typeof raw === "string") {
                raw = raw.trim();
                try {
                    nestedResponse = JSON.parse(raw);
                }
                catch {
                    nestedResponse = raw;
                }
            }
            else if (typeof raw === "object" && raw !== null) {
                nestedResponse = raw;
            }
            else {
                nestedResponse = String(raw);
            }
        }
        catch (err) {
            this.triggerMcpClientSubscriberLogger.error("Error processing AI response:", err);
            nestedResponse = `Error handling response: ${err?.message || String(err)}`;
        }
        return nestedResponse;
    }
    async subscribe(message) {
        this.triggerMcpClientSubscriberLogger.debug(`Received message: ${JSON.stringify(message)}`);
        const codeGnerationOptions = message.payload;
        const aiInteraction = await this.aiInteractionService.findOne(codeGnerationOptions.aiInteractionId, {
            populate: ['user']
        });
        if (!aiInteraction) {
            const m = `Unable to identified the aiInteraction entry that triggered this job... using id: ${codeGnerationOptions.aiInteractionId}`;
            this.triggerMcpClientSubscriberLogger.log(m);
            throw new Error(m);
        }
        const prompt = aiInteraction.message;
        const genAiInteraction = await this.aiInteractionService.create({
            userId: aiInteraction.user.id,
            threadId: aiInteraction.threadId,
            parentInteractionId: aiInteraction.id,
            role: 'gen-ai',
            message: '...',
            contentType: '',
            errorMessage: '',
            modelUsed: '',
            responseTimeMs: 0,
            metadata: '',
            isApplied: false,
            status: 'pending'
        });
        const existingComputationProviders = this.solidRegistry.getComputedFieldProviders();
        const { records: existingModules } = await this.moduleMetadataService.findMany({
            filters: {
                name: { $ne: 'solid-core' }
            },
            fields: ['id', 'name', 'displayName', 'description'],
            limit: 1000
        });
        const { records: existingModels } = await this.modelMetadataService.findMany({
            filters: {
                module: {
                    name: {
                        $ne: 'solid-core',
                    }
                }
            },
            limit: 1000,
            populate: ['module']
        });
        const existingDashboards = await this.dashboardRepository.find({
            where: {
                module: {
                    name: (0, typeorm_1.Not)('solid-core')
                }
            },
        });
        const existingControllerAndTheirMethods = this.solidRegistry.getControllers();
        const modulesSection = (existingModules ?? [])
            .map(m => [
            `### ${m.displayName}`,
            `- name: ${m.name}`,
            `- description: ${m.description ?? ""}`,
        ].join('\n'))
            .join('\n\n');
        const modelsSection = (existingModels ?? [])
            .map(m => [
            `### ${m.displayName}`,
            `- singularName: ${m.singularName}`,
            `- description: ${m.description ?? ""}`,
            `- moduleName: ${m.module.name}`,
        ].join('\n'))
            .join('\n\n');
        const dashboardsSection = (existingDashboards ?? [])
            .map(d => [
            `### ${d.displayName}`,
            `- name: ${d.name}`,
            `- description: ${d.description ?? ""}`,
        ].join('\n'))
            .join('\n\n');
        const computationProvidersSection = (existingComputationProviders ?? [])
            .map(m => [
            `### ${m.instance.name()}`,
            `- name: ${m.instance.name()}`,
            `- description: ${m.instance.help() ?? ""}`,
        ].join('\n'))
            .join('\n\n');
        const controllersAndTheirMethods = (existingControllerAndTheirMethods ?? [])
            .map(m => [
            `### ${m.name}`,
            `- methods: ${m.methods.length ? m.methods.map(m => `- ${m}`).join('\n') : '- No methods found'}`,
        ].join('\n'))
            .join('\n\n');
        const finalPrompt = `
# User Prompt: 
${prompt}

# System Instructions:
- aiInteractionId: ${genAiInteraction.id}
- You will be invoking tools if needed, hence you will have to choose the applicable tools based on the tool context given to you.
- If a tool is invoked, you must return **exactly** the raw output from the tool, without any json envelopes, additional formatting, commentary, or text.
- Do not wrap the result in quotes, JSON, or markdown fences.
- Do not explain what the result means.

# LISTS FOR REFERENCE AND VALIDATIONS

## LIST OF EXISTING MODULES
Use the below list of modules to infer which module the user is referring to, .

${modulesSection}

## LIST OF EXISTING MODELS
Use the below list of models to infer which model the user is referring to.
You need to pull out the singularName for the model from the user prompt to match against the below list.

${modelsSection}

## LIST OF EXISTING DASHBOARDS
Use the below list of dashboards to infer which dashboard the user is referring to.

${dashboardsSection}

## LIST OF EXISTING COMPUTED FIELD PROVIDERS
Use the below list of computed field providers to infer which provider the user is referring to.

${computationProvidersSection}
`.trim();
        const aiResponse = await this.aiInteractionService.runMcpPrompt(finalPrompt);
        this.triggerMcpClientSubscriberLogger.log(`aiResponse: `);
        this.triggerMcpClientSubscriberLogger.log(JSON.stringify(aiResponse));
        if (!aiResponse.success) {
            this.triggerMcpClientSubscriberLogger.log(`Gen ai has returned with a false status code`);
            const errorsStr = aiResponse.errors?.join('\n ');
            const errorTrace = aiResponse.error_trace?.join('\n');
            await this.aiInteractionService.update(genAiInteraction.id, {
                contentType: aiResponse.content_type,
                errorMessage: `${errorsStr}\n\n${errorTrace}`,
                modelUsed: aiResponse.model,
                responseTimeMs: aiResponse.duration_ms,
                isApplied: aiInteraction.isApplied,
                status: aiResponse.success ? 'succeeded' : 'failed'
            }, [], true);
            throw new Error(errorsStr);
        }
        else {
            let nestedResponse = this.cleanNestedResponse(aiResponse);
            const errorsStr = nestedResponse?.status == "error" && nestedResponse?.errors.join('\n ');
            const errorTrace = nestedResponse?.status == "error" && nestedResponse?.error_trace?.join('\n');
            await this.aiInteractionService.update(genAiInteraction.id, {
                errorMessage: nestedResponse.status == "error" ? `${errorsStr}\n\n${errorTrace}` : "",
                contentType: aiResponse.content_type,
                message: JSON.stringify(nestedResponse),
                modelUsed: aiResponse.model,
                responseTimeMs: aiResponse.duration_ms,
                metadata: JSON.stringify(aiResponse, null, 2),
                isApplied: aiInteraction.isApplied,
                status: aiResponse.success && nestedResponse.status == "success" ? 'succeeded' : 'failed'
            }, [], true);
            if (aiInteraction.isAutoApply) {
                this.aiInteractionService.applySolidAiInteraction(genAiInteraction.id);
            }
        }
        return aiResponse;
    }
};
exports.TriggerMcpClientSubscriberDatabase = TriggerMcpClientSubscriberDatabase;
exports.TriggerMcpClientSubscriberDatabase = TriggerMcpClientSubscriberDatabase = TriggerMcpClientSubscriberDatabase_1 = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [mq_message_service_1.MqMessageService,
        mq_message_queue_service_1.MqMessageQueueService,
        poller_service_1.PollerService,
        ai_interaction_service_1.AiInteractionService,
        module_metadata_service_1.ModuleMetadataService,
        model_metadata_service_1.ModelMetadataService,
        solid_registry_1.SolidRegistry,
        dashboard_repository_1.DashboardRepository])
], TriggerMcpClientSubscriberDatabase);
//# sourceMappingURL=trigger-mcp-client-subscriber-database.service.js.map