"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.pulseMonitoringService = exports.PulseMonitoringService = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const lodash_1 = __importDefault(require("lodash"));
const uuid_1 = require("uuid");
const database_1 = require("../../database");
const tables_1 = require("../../database/tables");
const logger_1 = __importDefault(require("../../logger"));
const CredentialsProviderService_1 = require("../../util/credentials/CredentialsProviderService");
const SecretProviderService_1 = require("../../util/secrets/SecretProviderService");
class PulseMonitoringService {
    async validateMonitoringConfig(params) {
        if (!params?.logLocation) {
            return {
                finalVerdict: false,
                message: 'Log location is required for monitoring',
            };
        }
        if (params.logLocation === 'folder-path') {
            if (!params.locationUrl) {
                return {
                    finalVerdict: false,
                    message: 'Log location URL is required for folder-path monitoring',
                };
            }
            if (!params.serviceProvider) {
                return {
                    finalVerdict: false,
                    message: 'Service provider is required for folder-path monitoring',
                };
            }
            if (params.serviceProvider === 'aws' && (!params.accessKey || !params.secretKey || !params.awsRegion)) {
                return {
                    finalVerdict: false,
                    message: 'AWS credentials and region are required for folder-path monitoring',
                };
            }
            if (params.serviceProvider === 'azure' && (!params.clientId || !params.clientSecret || !params.tenantId)) {
                return {
                    finalVerdict: false,
                    message: 'Azure client credentials are required for folder-path monitoring',
                };
            }
            const credentialCheck = await this.verifyCredentials({
                logLocation: params.logLocation,
                serviceProvider: params.serviceProvider,
                apiKey: params.apiKey || '',
                accessKey: params.accessKey || '',
                secretKey: params.secretKey || '',
                awsRegion: params.awsRegion || '',
                clientId: params.clientId || '',
                clientSecret: params.clientSecret || '',
                tenantId: params.tenantId || '',
            });
            return credentialCheck;
        }
        // SDK path does not require cloud credentials.
        return {
            finalVerdict: true,
            message: 'Monitoring configuration is valid',
        };
    }
    async getMonitoringConfig(params) {
        const config = {
            applicationId: params.applicationId,
            logLocations: [
                { label: 'Folder Path', value: 'folder-path' },
                { label: 'SDK', value: 'sdk' },
            ],
            serviceProviders: [
                { label: 'AWS', value: 'aws' },
                { label: 'Azure', value: 'azure' },
            ],
            awsRegions: [
                { label: 'US East (N. Virginia)', value: 'us-east-1' },
                { label: 'US East (Ohio)', value: 'us-east-2' },
                { label: 'US West (N. California)', value: 'us-west-1' },
                { label: 'US West (Oregon)', value: 'us-west-2' },
                { label: 'Africa (Cape Town)', value: 'af-south-1' },
                { label: 'Asia Pacific (Hong Kong)', value: 'ap-east-1' },
                { label: 'Asia Pacific (Hyderabad)', value: 'ap-south-2' },
                { label: 'Asia Pacific (Jakarta)', value: 'ap-southeast-3' },
                { label: 'Asia Pacific (Melbourne)', value: 'ap-southeast-4' },
                { label: 'Asia Pacific (Mumbai)', value: 'ap-south-1' },
                { label: 'Asia Pacific (Osaka)', value: 'ap-northeast-3' },
                { label: 'Asia Pacific (Seoul)', value: 'ap-northeast-2' },
                { label: 'Asia Pacific (Singapore)', value: 'ap-southeast-1' },
                { label: 'Asia Pacific (Sydney)', value: 'ap-southeast-2' },
                { label: 'Asia Pacific (Tokyo)', value: 'ap-northeast-1' },
                { label: 'Canada (Central)', value: 'ca-central-1' },
                { label: 'Canada West (Calgary)', value: 'ca-west-1' },
                { label: 'Europe (Frankfurt)', value: 'eu-central-1' },
                { label: 'Europe (Ireland)', value: 'eu-west-1' },
                { label: 'Europe (London)', value: 'eu-west-2' },
                { label: 'Europe (Milan)', value: 'eu-south-1' },
                { label: 'Europe (Paris)', value: 'eu-west-3' },
                { label: 'Europe (Spain)', value: 'eu-south-2' },
                { label: 'Europe (Stockholm)', value: 'eu-north-1' },
                { label: 'Europe (Zurich)', value: 'eu-central-2' },
                { label: 'Middle East (Bahrain)', value: 'me-south-1' },
                { label: 'Middle East (UAE)', value: 'me-central-1' },
                { label: 'South America (São Paulo)', value: 'sa-east-1' },
                { label: 'AWS GovCloud (US-East)', value: 'us-gov-east-1' },
                { label: 'AWS GovCloud (US-West)', value: 'us-gov-west-1' },
                { label: 'Israel (Tel Aviv)', value: 'il-central-1' },
            ],
        };
        if (lodash_1.default.isEmpty(params.applicationId) === false) {
            const db = await (0, database_1.getDb)();
            const [monitoring] = await db
                .select()
                .from(tables_1.pulseMonitoringTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId));
            if (monitoring) {
                config.monitoring = monitoring;
            }
        }
        return config;
    }
    async verifyCredentials(params) {
        // Dynamically import CredentialService here
        if (params.logLocation === 'folder-path' && params.serviceProvider === 'aws') {
            const credentialsProvider = new CredentialsProviderService_1.CredentialService({
                cloudProvider: 'aws',
                accessKey: params.accessKey,
                secretKey: params.secretKey,
            });
            const { apiError,
            // apiResponse,
             } = await credentialsProvider.verify();
            if (apiError) {
                return {
                    finalVerdict: false,
                    message: apiError?.message,
                };
            }
            return {
                finalVerdict: true,
                message: 'AWS credentials verified successfully',
            };
        }
        if (params.logLocation === 'folder-path' && params.serviceProvider === 'azure') {
            const credentialsProvider = new CredentialsProviderService_1.CredentialService({
                cloudProvider: 'azure',
                applicationId: params.clientId,
                applicationSecret: params.clientSecret,
                tenantId: params.tenantId,
            });
            const { apiError,
            // apiResponse,
             } = await credentialsProvider.verify();
            if (apiError) {
                return {
                    finalVerdict: false,
                    message: apiError?.message,
                };
            }
            return {
                finalVerdict: true,
                message: 'Azure credentials verified successfully',
            };
        }
        return {
            finalVerdict: false,
            message: 'Invalid service provider',
        };
    }
    async createMonitoring(params) {
        try {
            logger_1.default.info('Creating monitoring');
            const db = await (0, database_1.getDb)();
            // Check for existing alert with same applicationId
            const existing = await db
                .select()
                .from(tables_1.pulseMonitoringTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId));
            // if (existing.length > 0) {
            //   throw new Error('Monitoring already exists for this application');
            // }
            let secretName = '';
            if (lodash_1.default.isEmpty(params?.accessKey) === false ||
                lodash_1.default.isEmpty(params?.secretKey) === false ||
                lodash_1.default.isEmpty(params?.clientId) === false ||
                lodash_1.default.isEmpty(params?.clientSecret) === false ||
                lodash_1.default.isEmpty(params?.tenantId) === false ||
                lodash_1.default.isEmpty(params?.awsRegion) === false) {
                const { finalVerdict, message } = await this.verifyCredentials({
                    logLocation: params.logLocation,
                    serviceProvider: params.serviceProvider,
                    apiKey: params.apiKey,
                    accessKey: params.accessKey,
                    secretKey: params.secretKey,
                    awsRegion: params.awsRegion,
                    clientId: params.clientId,
                    clientSecret: params.clientSecret,
                    tenantId: params.tenantId,
                });
                if (!finalVerdict && params.logLocation === 'folder-path') {
                    throw new Error(message);
                }
                if (params.logLocation === 'folder-path') {
                    const secretManager = new SecretProviderService_1.SecretProviderService({
                        cloudProvider: process.env.CLOUD_PROVIDER || 'azure',
                        vault: process.env.DEFAULT_AZURE_VAULT || 'sccentralindiadev',
                        region: process.env.DEFAULT_AZURE_REGION || 'ap-south-1',
                    });
                    secretName = `pulse-monitoring-${params.applicationId}`;
                    if (params.serviceProvider === 'aws') {
                        // create secret_key entry on secret manager
                        await secretManager.create(secretName, {
                            AWS_ACCESS_KEY_ID: params.accessKey,
                            AWS_SECRET_ACCESS_KEY: params.secretKey,
                            AWS_REGION: params.awsRegion,
                        });
                    }
                    if (params.serviceProvider === 'azure') {
                        // create secret_key entry on secret manager
                        await secretManager.create(secretName, {
                            AZURE_CLIENT_ID: params.clientId,
                            AZURE_CLIENT_SECRET: params.clientSecret,
                            AZURE_TENANT_ID: params.tenantId,
                            // AZURE_SUBSCRIPTION_ID: params.subscriptionId,
                        });
                    }
                }
            }
            if (params.logLocation === 'folder-path' && lodash_1.default.isEmpty(secretName) && existing.length > 0) {
                secretName = existing[0].secretName;
            }
            if (lodash_1.default.isEmpty(secretName) && params.logLocation === 'folder-path') {
                throw new Error('Credentials not found');
            }
            // save the monitoring config
            const monitoringConfig = {
                applicationId: params.applicationId,
                logLocation: params.logLocation,
                serviceProvider: params.serviceProvider,
                locationUrl: params.locationUrl,
                samplingFrequency: params.samplingFrequency,
                samplingPercentage: params.samplingPercentage ?? 0,
                samplingCount: params.samplingCount ?? 0,
                evaluationWindow: params.evaluationWindow,
                metrics: params.metrics,
                pluginsByCategory: params.pluginsByCategory,
                secretName,
                projectId: params.projectId,
                workspaceId: params.workspaceId,
            };
            let result;
            if (existing.length > 0) {
                result = await db
                    .update(tables_1.pulseMonitoringTable)
                    .set({
                    ...monitoringConfig,
                    updatedAt: new Date(),
                })
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId))
                    .returning({
                    id: tables_1.pulseMonitoringTable.id,
                    updatedAt: tables_1.pulseMonitoringTable.updatedAt,
                })
                    .then(([result]) => result);
            }
            else {
                result = await db
                    .insert(tables_1.pulseMonitoringTable)
                    .values({
                    id: (0, uuid_1.v4)(),
                    ...monitoringConfig,
                })
                    .returning({
                    id: tables_1.pulseMonitoringTable.id,
                    createdAt: tables_1.pulseMonitoringTable.createdAt,
                })
                    .then(([result]) => result);
            }
            logger_1.default.info(`Monitoring ${existing.length > 0 ? 'updated' : 'created'} with id: ${result.id}`);
            return {
                success: true,
                data: result,
            };
        }
        catch (error) {
            logger_1.default.error(`Error in creating monitoring: ${error}`);
            throw error;
        }
    }
    async updateMonitoring(params) {
        try {
            logger_1.default.info('Updating monitoring');
            const db = await (0, database_1.getDb)();
            const [existing] = await db
                .select()
                .from(tables_1.pulseMonitoringTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId));
            if (!existing) {
                throw new Error('Monitoring config not found for this application');
            }
            const updatePayload = {
                ...params,
                samplingPercentage: params.samplingPercentage ?? 0,
                samplingCount: params.samplingCount ?? 0,
            };
            delete updatePayload.applicationId;
            await db
                .update(tables_1.pulseMonitoringTable)
                .set(updatePayload)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId));
            logger_1.default.info(`Monitoring updated for applicationId: ${params.applicationId}`);
            return { success: true };
        }
        catch (error) {
            logger_1.default.error(`Error in updating monitoring: ${error}`);
            throw error;
        }
    }
    async getMonitoring(params) {
        try {
            const db = await (0, database_1.getDb)();
            const [monitoring] = await db
                .select()
                .from(tables_1.pulseMonitoringTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, params.applicationId));
            return monitoring ?? {};
        }
        catch (error) {
            logger_1.default.error(`Error in getting monitoring: ${error}`);
            throw error;
        }
    }
    async createAlert(params) {
        try {
            logger_1.default.info('Creating alert');
            // save the monitoring config
            const db = await (0, database_1.getDb)();
            // Check for existing alert with same applicationId
            const existing = await db
                .select()
                .from(tables_1.pulseMonitoringAlertsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, params.applicationId));
            if (existing.length > 0) {
                throw new Error('Alert already exists for this application');
            }
            const [result] = await db
                .insert(tables_1.pulseMonitoringAlertsTable)
                .values({
                id: (0, uuid_1.v4)(),
                name: 'New Alert',
                projectId: params.projectId,
                workspaceId: params.workspaceId,
                applicationId: params.applicationId,
                alert: null,
                emails: null,
                webhook: null,
            })
                .returning({
                id: tables_1.pulseMonitoringAlertsTable.id,
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
            });
            logger_1.default.info(`Alert created with id: ${result.id}`);
            return {
                success: true,
                data: result,
            };
        }
        catch (error) {
            logger_1.default.error(`Error in creating alert: ${error}`);
            throw error;
        }
    }
    async updateAlert(params) {
        try {
            logger_1.default.info('Updating alert');
            const db = await (0, database_1.getDb)();
            // Check for existing alert with same applicationId
            const existing = await db
                .select()
                .from(tables_1.pulseMonitoringAlertsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, params.applicationId));
            if (existing.length === 0) {
                throw new Error('Alert not found for this application');
            }
            const [result] = await db
                .update(tables_1.pulseMonitoringAlertsTable)
                .set({
                alert: params.alerts,
                emails: params.emails,
                webhook: params.webhook,
                status: 1,
                updatedAt: new Date(),
            })
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, params.applicationId))
                .returning({
                id: tables_1.pulseMonitoringAlertsTable.id,
                updatedAt: tables_1.pulseMonitoringAlertsTable.updatedAt,
            });
            logger_1.default.info(`Alert updated with id: ${result.id}`);
            return {
                success: true,
                data: result,
            };
        }
        catch (error) {
            logger_1.default.error(`Error in updating alert: ${error}`);
            throw error;
        }
    }
    async getAlerts(params) {
        try {
            logger_1.default.info('Getting alerts for project');
            const db = await (0, database_1.getDb)();
            const { projectId, limit = 10, page = 1 } = params;
            const offset = (page - 1) * limit;
            const [alerts, totalCount] = await Promise.all([
                db
                    .select({
                    id: tables_1.pulseMonitoringAlertsTable.id,
                    alert: tables_1.pulseMonitoringAlertsTable.alert,
                    status: tables_1.pulseMonitoringAlertsTable.status,
                    alertsTriggered: tables_1.pulseMonitoringAlertsTable.alertsTriggered,
                    updatedAt: tables_1.pulseMonitoringAlertsTable.updatedAt,
                    applicationName: tables_1.applicationsTable.name,
                })
                    .from(tables_1.pulseMonitoringAlertsTable)
                    .leftJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id))
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId))
                    .limit(limit)
                    .offset(offset)
                    .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseMonitoringAlertsTable.createdAt)),
                db
                    .select({ count: (0, drizzle_orm_1.sql) `count(*)` })
                    .from(tables_1.pulseMonitoringAlertsTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId)),
            ]);
            return {
                alerts,
                pagination: {
                    total: totalCount[0]?.count || 0,
                    page,
                    limit,
                },
            };
        }
        catch (error) {
            logger_1.default.error(`Error getting alerts: ${error}`);
            throw error;
        }
    }
    async getApplicationsWithMonitoring({ limit = 10, page = 1, applicationIds, }) {
        const db = await (0, database_1.getDb)();
        const offset = (page - 1) * limit;
        const applications = await db
            .select({
            // All pulse monitoring fields
            ...tables_1.pulseMonitoringTable,
            // All application fields
            application: tables_1.applicationsTable,
        })
            .from(tables_1.pulseMonitoringTable)
            .where(applicationIds ? (0, drizzle_orm_1.inArray)(tables_1.pulseMonitoringTable.applicationId, applicationIds) : undefined)
            .leftJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringTable.applicationId, tables_1.applicationsTable.id))
            .limit(limit)
            .offset(offset);
        return applications;
    }
    async getApplicationsWithForAlerts({ limit = 10, page = 1, projectId, }) {
        const db = await (0, database_1.getDb)();
        const applicationsWithMonitoring = await db
            .select({
            id: tables_1.applicationsTable.id,
            name: tables_1.applicationsTable.name,
            createdAt: tables_1.applicationsTable.createdAt,
            projectId: tables_1.applicationsTable.projectId,
        })
            .from(tables_1.applicationsTable)
            .innerJoin(tables_1.pulseMonitoringTable, (0, drizzle_orm_1.eq)(tables_1.applicationsTable.id, tables_1.pulseMonitoringTable.applicationId))
            .where((0, drizzle_orm_1.and)(projectId ? (0, drizzle_orm_1.eq)(tables_1.applicationsTable.projectId, projectId) : (0, drizzle_orm_1.sql) `TRUE`))
            .orderBy(tables_1.applicationsTable.createdAt);
        return applicationsWithMonitoring;
    }
    async getAlertDetails(params) {
        try {
            logger_1.default.info('Getting alert details');
            const db = await (0, database_1.getDb)();
            const [alertDetails] = await db
                .select({
                id: tables_1.pulseMonitoringAlertsTable.id,
                applicationId: tables_1.pulseMonitoringAlertsTable.applicationId,
                alert: tables_1.pulseMonitoringAlertsTable.alert,
                emails: tables_1.pulseMonitoringAlertsTable.emails,
                webhook: tables_1.pulseMonitoringAlertsTable.webhook,
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
                updatedAt: tables_1.pulseMonitoringAlertsTable.updatedAt,
                applicationName: tables_1.applicationsTable.name,
                applicationDescription: tables_1.applicationsTable.description,
                metrics: tables_1.pulseMonitoringTable.metrics,
                pluginsByCategory: tables_1.pulseMonitoringTable.pluginsByCategory,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id))
                .leftJoin(tables_1.pulseMonitoringTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.pulseMonitoringTable.applicationId))
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, params.alertId));
            if (!alertDetails) {
                throw new Error('Alert not found');
            }
            return alertDetails;
        }
        catch (error) {
            logger_1.default.error(`Error in getting alert details: ${error}`);
            throw error;
        }
    }
    async getAlertLogs(params) {
        try {
            logger_1.default.info('Getting alert logs');
            const { alertId, limit = 50, page = 1 } = params;
            const offset = (page - 1) * limit;
            const db = await (0, database_1.getDb)();
            // Get total count and last alert time
            const [countResult, lastAlertResult] = await Promise.all([
                db
                    .select({ count: (0, drizzle_orm_1.sql) `count(*)` })
                    .from(tables_1.pulseAlertLogsTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId)),
                db
                    .select({ lastAlertTime: tables_1.pulseAlertLogsTable.createdAt })
                    .from(tables_1.pulseAlertLogsTable)
                    .where((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId))
                    .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseAlertLogsTable.createdAt))
                    .limit(1),
            ]);
            const count = countResult[0]?.count || 0;
            const lastAlertTime = lastAlertResult[0]?.lastAlertTime;
            // Get logs with pagination
            const logs = await db
                .select({
                id: tables_1.pulseAlertLogsTable.id,
                metrics: tables_1.pulseAlertLogsTable.metrics,
                count: tables_1.pulseAlertLogsTable.count,
                timestamp: tables_1.pulseAlertLogsTable.timestamp,
                createdAt: tables_1.pulseAlertLogsTable.createdAt,
            })
                .from(tables_1.pulseAlertLogsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId))
                .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseAlertLogsTable.createdAt))
                .limit(limit)
                .offset(offset);
            return {
                logs,
                total: count,
                page,
                limit,
                lastAlertTime: lastAlertTime?.toISOString(),
            };
        }
        catch (error) {
            logger_1.default.error(`Error in getting alert logs: ${error}`);
            throw error;
        }
    }
}
exports.PulseMonitoringService = PulseMonitoringService;
// Export a singleton instance
exports.pulseMonitoringService = new PulseMonitoringService();
//# sourceMappingURL=pulseMonitoringService.js.map