"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createApplication = void 0;
const decimal_js_1 = __importDefault(require("decimal.js"));
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 get_upgrade_meta_1 = require("../../../util/get-upgrade-meta");
const pulseMonitoringService_1 = require("../../services/pulseMonitoringService");
const clickhouseApplicationsService_1 = require("../../services/clickhouseApplicationsService");
const time_1 = require("../../../util/time");
const restriction_message_1 = require("../../constants/restriction.message");
const constants_1 = require("../../../constants");
const activityLogService_1 = require("../../services/activityLogService");
const createApplication = async (req, res) => {
    try {
        const { name, provider_config, description, projectId, security_config = {}, monitoring_params = null, enableEncryption = '0', orgId, enable_guard_rails = false, guardRails = null, } = req.body;
        const db = await (0, database_1.getDb)();
        const { restrictionsData, isEnterprise, } = await (0, get_upgrade_meta_1.getUpgradeMetaByOrgId)(orgId);
        if (!isEnterprise && restrictionsData?.applications > 0) {
            const whereConditions = (0, time_1.createTimespanWhereConditions)({
                table: tables_1.applicationsTable,
                timeColumn: 'createdAt',
                orgId: orgId,
                timespan: restrictionsData?.applications_timespan || 'lifetime',
            });
            const count = await db
                .select({ count: (0, drizzle_orm_1.sql) `count(*)` })
                .from(tables_1.applicationsTable)
                .where(whereConditions)
                .then((result) => Number(result[0]?.count ?? 0));
            if (count !== 0 && new decimal_js_1.default(count).gte(restrictionsData?.applications ?? 0)) {
                res.status(400).json({
                    success: false,
                    message: restriction_message_1.ERROR_RESTRICTION_MESSAGE.upgrade.title,
                    showToast: true,
                    toastMetadata: {
                        text: restriction_message_1.ERROR_RESTRICTION_MESSAGE.upgrade.message,
                        type: 'error',
                        duration: 5000,
                        action: {
                            label: 'Upgrade',
                            actionType: 'upgrade',
                        },
                    },
                });
                return;
            }
        }
        const pulseMonitoringService = new pulseMonitoringService_1.PulseMonitoringService();
        // Pre-validate monitoring before creating application to avoid partial creation.
        if (monitoring_params) {
            const monitoringValidation = await pulseMonitoringService.validateMonitoringConfig({
                logLocation: monitoring_params?.logLocation,
                serviceProvider: monitoring_params?.serviceProvider,
                locationUrl: monitoring_params?.locationUrl,
                accessKey: monitoring_params?.accessKey,
                secretKey: monitoring_params?.secretKey,
                awsRegion: monitoring_params?.awsRegion,
                clientId: monitoring_params?.clientId,
                clientSecret: monitoring_params?.clientSecret,
                tenantId: monitoring_params?.tenantId,
                apiKey: monitoring_params?.apiKey,
            });
            if (!monitoringValidation?.finalVerdict) {
                res.status(400).json({
                    success: false,
                    message: monitoringValidation?.message || 'Invalid monitoring configuration',
                });
                return;
            }
        }
        const id = (0, uuid_1.v4)();
        // Check for existing application with same name and projectId
        const existing = await db
            .select()
            .from(tables_1.applicationsTable)
            .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.applicationsTable.name, name), (0, drizzle_orm_1.eq)(tables_1.applicationsTable.projectId, projectId)));
        if (existing.length > 0) {
            res
                .status(400)
                .json({ success: false, message: 'Application with this name already exists.' });
            return;
        }
        const [result] = await db
            .insert(tables_1.applicationsTable)
            .values({
            id,
            name,
            provider_config,
            security_config: monitoring_params?.security_config || security_config,
            description,
            test_runs: 0,
            projectId,
            workspaceId: orgId,
            enableEncryption,
        })
            .returning({
            id: tables_1.applicationsTable.id,
            createdAt: tables_1.applicationsTable.createdAt,
        });
        logger_1.default.info(`Saved application ${id} with ${provider_config.provider_type} providers`);
        // Create guardrails configuration if provided
        if (enable_guard_rails && guardRails) {
            try {
                await db.insert(tables_1.applicationGuardrailsTable).values({
                    id: (0, uuid_1.v4)(),
                    applicationId: id,
                    enable_guard_rails: Boolean(enable_guard_rails),
                    input_validators: guardRails.input_validators || [],
                    output_validators: guardRails.output_validators || [],
                });
                logger_1.default.info(`Saved guardrails configuration for application ${id}`);
            }
            catch (guardrailsError) {
                logger_1.default.error(`Error saving guardrails configuration: ${guardrailsError}`);
                // Don't fail the request if guardrails save fails
            }
        }
        if (monitoring_params) {
            try {
                await pulseMonitoringService.createMonitoring({
                    ...monitoring_params,
                    applicationId: id,
                    workspaceId: orgId,
                });
            }
            catch (monitoringError) {
                logger_1.default.error(`Error creating monitoring for application ${id}: ${monitoringError}`);
                // Rollback created app and guardrails to avoid partial creation.
                await db.delete(tables_1.applicationGuardrailsTable).where((0, drizzle_orm_1.eq)(tables_1.applicationGuardrailsTable.applicationId, id));
                await db.delete(tables_1.applicationsTable).where((0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, id));
                res.status(400).json({
                    success: false,
                    message: monitoringError?.message ||
                        'Failed to create monitoring. Application creation has been rolled back.',
                });
                return;
            }
        }
        // Best-effort ClickHouse upsert (do not block app creation).
        try {
            await clickhouseApplicationsService_1.clickhouseApplicationsService.upsertFromPostgres(id);
        }
        catch (chError) {
            logger_1.default.error(`Failed to upsert application ${id} 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 [orgName, projectName] = await Promise.all([
                (0, activityLogService_1.fetchOrgName)(token, orgId),
                (0, activityLogService_1.fetchProjectName)(token, orgId, projectId),
            ]);
            await (0, activityLogService_1.logActivity)(token, {
                type: constants_1.ActivityType.CREATE_APPLICATION,
                params: (0, activityLogService_1.buildActivityParams)({
                    application_name: { value: name, _id: id },
                    user_name: { value: userName, _id: userId },
                    org_name: { value: orgName || orgId, _id: orgId },
                    project_name: { value: projectName || projectId, _id: projectId },
                }),
                project_id: projectId,
                org_id: orgId,
                created_by: userId,
                updated_by: userId,
            });
        }
        catch (activityError) {
            logger_1.default.error(`Error logging activity for create application: ${activityError}`);
            // Don't fail the request if activity logging fails
        }
        res.json({
            success: true,
            data: result,
        });
    }
    catch (error) {
        logger_1.default.error(`Error saving application: ${error}`);
        res.status(500).json({
            success: false,
            message: error instanceof Error ? error.message : 'Failed to save application',
        });
    }
};
exports.createApplication = createApplication;
//# sourceMappingURL=create-application.js.map