"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateApplication = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const uuid_1 = require("uuid");
const database_1 = require("../../../database");
const tables_1 = require("../../../database/tables");
const logger_1 = __importDefault(require("../../../logger"));
const constants_1 = require("../../../constants");
const clickhouseApplicationsService_1 = require("../../services/clickhouseApplicationsService");
const activityLogService_1 = require("../../services/activityLogService");
const customAIApplicationService_1 = require("../../services/customAIApplicationService");
const updateApplication = async (req, res) => {
    try {
        const { applicationId } = req.params;
        const db = await (0, database_1.getDb)();
        const updateData = {};
        const [existingApplication] = await db
            .select({
            id: tables_1.applicationsTable.id,
            name: tables_1.applicationsTable.name,
            projectId: tables_1.applicationsTable.projectId,
            workspaceId: tables_1.applicationsTable.workspaceId,
            provider_config: tables_1.applicationsTable.provider_config,
        })
            .from(tables_1.applicationsTable)
            .where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId))
            .limit(1);
        if (!existingApplication) {
            res.status(404).json({
                success: false,
                message: 'Application not found',
            });
            return;
        }
        // Only include fields that are present in the request body
        if (req.body.name !== undefined) {
            const nextName = String(req.body.name ?? '').trim();
            if (!nextName) {
                res.status(400).json({ success: false, message: 'Application name is required' });
                return;
            }
            const projectIdForUniq = String(req.body.projectId ?? existingApplication.projectId ?? '').trim();
            if (!projectIdForUniq) {
                res.status(400).json({ success: false, message: 'projectId is required to update application name' });
                return;
            }
            const [conflict] = await db
                .select({ id: tables_1.applicationsTable.id })
                .from(tables_1.applicationsTable)
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.applicationsTable.projectId, projectIdForUniq), (0, drizzle_orm_1.eq)(tables_1.applicationsTable.name, nextName), (0, drizzle_orm_1.ne)(tables_1.applicationsTable.id, applicationId)))
                .limit(1);
            if (conflict?.id) {
                res.status(409).json({
                    success: false,
                    message: `An application named "${nextName}" already exists in this project`,
                });
                return;
            }
            updateData.name = nextName;
        }
        if (req.body.useCase !== undefined) {
            updateData.useCase = req.body.useCase;
        }
        if (req.body.provider_config !== undefined) {
            updateData.provider_config = req.body.provider_config;
            const priorConfig = (existingApplication.provider_config ?? {});
            const priorInner = (priorConfig.config ?? {});
            const priorProvider = (priorInner.provider ?? {});
            const nextConfig = (req.body.provider_config ?? {});
            const nextInner = (nextConfig.config ?? {});
            const nextProvider = (nextInner.provider ?? {});
            const isCustomAI = String(nextInner.custom_provider_type ?? '') === 'Custom AI Application';
            const wasUpload = isCustomAI && String(priorProvider.setupMethod ?? 'shell').trim() === 'upload';
            const isShell = isCustomAI && String(nextProvider.setupMethod ?? 'shell').trim() === 'shell';
            if (wasUpload && isShell) {
                try {
                    await new customAIApplicationService_1.CustomAIApplicationService().clearEnvSecrets(applicationId);
                }
                catch (error) {
                    logger_1.default.warn(`updateApplication: failed to clear custom AI env for ${applicationId}: ${error}`);
                }
            }
        }
        if (req.body.description !== undefined) {
            updateData.description = req.body.description;
        }
        if (req.body.projectId !== undefined) {
            updateData.projectId = req.body.projectId;
        }
        if (req.body.security_config !== undefined) {
            updateData.security_config = req.body.security_config;
        }
        if (req.body.enableEncryption !== undefined) {
            updateData.enableEncryption = req.body.enableEncryption;
        }
        if (req.body.enable_guard_rails !== undefined) {
            // Guardrails will be handled separately
        }
        if (req.body.guardRails !== undefined) {
            // Guardrails will be handled separately
        }
        // Handle monitoringDetails update
        if (req.body.monitoringDetails !== undefined && Array.isArray(req.body.monitoringDetails)) {
            const monitoringData = req.body.monitoringDetails[0]; // Take the first monitoring detail
            if (monitoringData) {
                try {
                    // Check if monitoring config exists for this application
                    const [existingMonitoring] = await db
                        .select()
                        .from(tables_1.pulseMonitoringTable)
                        .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, applicationId));
                    if (existingMonitoring) {
                        // Update existing monitoring config
                        const { createdAt: _createdAt, ...rest } = monitoringData;
                        const updatePayload = {
                            ...rest,
                            samplingPercentage: rest.samplingPercentage ?? 0,
                            samplingCount: rest.samplingCount ?? 0,
                            updatedAt: new Date(),
                        };
                        await db
                            .update(tables_1.pulseMonitoringTable)
                            .set(updatePayload)
                            .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, applicationId));
                        logger_1.default.info(`Updated monitoring config for application ${applicationId}`);
                    }
                    else {
                        logger_1.default.warn(`No monitoring config found for application ${applicationId} to update`);
                    }
                }
                catch (monitoringError) {
                    logger_1.default.error(`Error updating monitoring config for application ${applicationId}: ${monitoringError}`);
                    // Don't fail the entire request if monitoring update fails
                }
            }
        }
        // Always update the updatedAt timestamp
        updateData.updatedAt = new Date();
        const [result] = await db
            .update(tables_1.applicationsTable)
            .set(updateData)
            .where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId))
            .returning({
            id: tables_1.applicationsTable.id,
            updatedAt: tables_1.applicationsTable.updatedAt,
        });
        // Handle guardrails update
        if (req.body.enable_guard_rails !== undefined || req.body.guardRails !== undefined) {
            try {
                const [existingGuardrails] = await db
                    .select()
                    .from(tables_1.applicationGuardrailsTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, applicationId))
                    .limit(1);
                const guardrailsData = {
                    enable_guard_rails: req.body.enable_guard_rails === undefined
                        ? (existingGuardrails?.enable_guard_rails ?? false)
                        : Boolean(req.body.enable_guard_rails),
                    input_validators: req.body.guardRails?.input_validators ?? existingGuardrails?.input_validators ?? [],
                    output_validators: req.body.guardRails?.output_validators ?? existingGuardrails?.output_validators ?? [],
                    updatedAt: new Date(),
                };
                if (existingGuardrails) {
                    // Update existing guardrails
                    await db
                        .update(tables_1.applicationGuardrailsTable)
                        .set(guardrailsData)
                        .where((0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, applicationId));
                    logger_1.default.info(`Updated guardrails configuration for application ${applicationId}`);
                }
                else {
                    // Create new guardrails entry
                    await db.insert(tables_1.applicationGuardrailsTable).values({
                        id: (0, uuid_1.v4)(),
                        applicationId,
                        ...guardrailsData,
                    });
                    logger_1.default.info(`Created guardrails configuration for application ${applicationId}`);
                }
            }
            catch (guardrailsError) {
                logger_1.default.error(`Error updating guardrails configuration: ${guardrailsError}`);
                // Don't fail the entire request if guardrails update fails
            }
        }
        // result should always exist since we checked upfront, but keep the guard.
        if (!result) {
            res.status(404).json({ success: false, message: 'Application not found' });
            return;
        }
        logger_1.default.info(`Updated application ${applicationId}`);
        // Best-effort ClickHouse upsert (do not fail update if ClickHouse is unavailable).
        try {
            await clickhouseApplicationsService_1.clickhouseApplicationsService.upsertFromPostgres(applicationId);
        }
        catch (chError) {
            logger_1.default.error(`Failed to upsert application ${applicationId} to ClickHouse: ${chError}`);
        }
        // Log activity
        try {
            const token = req.headers['x-access-token'] || req.headers.authorization;
            const { userId, userName } = (0, activityLogService_1.getUserInfo)(req);
            const [application] = await db.select().from(tables_1.applicationsTable).where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, applicationId));
            if (application && token) {
                const orgId = req.body.orgId || application.workspaceId || '';
                const projectId = req.body.projectId || application.projectId || '';
                if (orgId && typeof orgId === 'string') {
                    const [orgName, projectName] = await Promise.all([
                        (0, activityLogService_1.fetchOrgName)(token, orgId),
                        projectId && typeof projectId === 'string' ? (0, activityLogService_1.fetchProjectName)(token, orgId, projectId) : Promise.resolve(''),
                    ]);
                    await (0, activityLogService_1.logActivity)(token, {
                        type: constants_1.ActivityType.UPDATE_APPLICATION,
                        params: (0, activityLogService_1.buildActivityParams)({
                            application_name: { value: application.name || '', _id: applicationId },
                            user_name: { value: userName, _id: userId },
                            org_name: { value: orgName || orgId, _id: orgId },
                            project_name: { value: projectName || (projectId && typeof projectId === 'string' ? projectId : ''), _id: projectId && typeof projectId === 'string' ? projectId : undefined },
                        }),
                        project_id: projectId && typeof projectId === 'string' ? projectId : undefined,
                        org_id: orgId,
                        created_by: userId,
                        updated_by: userId,
                    });
                }
            }
        }
        catch (activityError) {
            logger_1.default.error(`Error logging activity for update application: ${activityError}`);
        }
        res.json({
            success: true,
            data: result,
        });
    }
    catch (error) {
        logger_1.default.error(`Error updating application: ${error}`);
        res.status(500).json({
            success: false,
            message: 'Failed to update application',
        });
    }
};
exports.updateApplication = updateApplication;
//# sourceMappingURL=update-application.js.map