"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AlertsService = exports.getAlertConditionTitle = void 0;
const drizzle_orm_1 = require("drizzle-orm");
const uuid_1 = require("uuid");
const constants_1 = require("../../constants");
const database_1 = require("../../database");
const tables_1 = require("../../database/tables");
const logger_1 = require("../../logger");
const constants_2 = require("../../redteam/constants");
const time_1 = require("../../util/time");
const get_upgrade_meta_1 = require("../../util/get-upgrade-meta");
const decimal_js_1 = __importDefault(require("decimal.js"));
const restriction_message_1 = require("../constants/restriction.message");
const constants_3 = require("../../constants");
const getAlertConditionTitle = (alert) => {
    let condition = '';
    if (alert?.type === constants_3.ALERT_TYPES.SCOUT_FUNCTIONAL_EVALUATION) {
        condition = `${alert?.metricType} consistently failed atleast ${alert?.metricValue} times in last ${alert?.metricComparator} ${alert?.metricComparatorType}`;
    }
    else if (alert?.type === constants_3.ALERT_TYPES.SCOUT_SECURITY_EVALUATION) {
        condition = `${alert?.metricType} consistently failed atleast ${constants_2.displayNameOverrides[alert?.metricValue]} times in last ${alert?.metricComparator} ${alert?.metricComparatorType}`;
    }
    else if (alert?.type === constants_3.ALERT_TYPES.FUNCTIONAL_EVALUATION) {
        condition = `Test case failed`;
    }
    else if (alert?.type === constants_3.ALERT_TYPES.SECURITY_EVALUATION) {
        condition = `Test case failed`;
    }
    else if (alert?.type === constants_3.ALERT_TYPES.PULSE_SYSTEM_HEALTH && alert?.subType === 'noLogs') {
        condition = `No logs detected in last ${alert?.metricComparator} ${alert?.metricComparatorType}`;
    }
    else if (alert?.type === constants_3.ALERT_TYPES.PULSE_SYSTEM_HEALTH && alert?.subType === 'cost') {
        condition = `Total cost exceeded $${alert?.metricValue || 0} in last ${alert?.metricComparator} ${alert?.metricComparatorType}`;
    }
    else if ([constants_3.ALERT_TYPES.INPUT_GAURD_RAIL, constants_3.ALERT_TYPES.OUTPUT_GAURD_RAIL].includes(alert?.type)) {
        condition = `${alert?.subType} consistently failed atleast ${alert?.metricValue} times in last ${alert?.metricComparator} ${alert?.metricComparatorType}`;
    }
    return condition;
};
exports.getAlertConditionTitle = getAlertConditionTitle;
class AlertsService {
    buildDailyRangeChartData(startDate, endDate, chartData) {
        const start = new Date(startDate);
        const end = new Date(endDate);
        const countsByDate = new Map();
        chartData.forEach((item) => {
            const dateKey = String(item.date).split('T')[0];
            const current = countsByDate.get(dateKey) ?? 0;
            countsByDate.set(dateKey, current + Number(item.count ?? 0));
        });
        const filledData = [];
        const cursor = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate(), 0, 0, 0, 0));
        const endUtc = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate(), 0, 0, 0, 0));
        while (cursor <= endUtc) {
            const dateKey = cursor.toISOString().split('T')[0];
            filledData.push({
                x: dateKey,
                y: countsByDate.get(dateKey) ?? 0,
                date: new Date(cursor),
            });
            cursor.setUTCDate(cursor.getUTCDate() + 1);
        }
        return filledData;
    }
    async getDashboardSummaryGraph(params) {
        try {
            const { startDate, endDate, projectId, orgId } = params;
            // Get alert statistics for the time period
            const db = (0, database_1.getDb)();
            // Get daily incident counts for chart data
            const chartData = await db
                .select({
                date: (0, drizzle_orm_1.sql) `DATE(${tables_1.pulseAlertLogsTable.createdAt})`,
                count: (0, drizzle_orm_1.count)(tables_1.pulseAlertLogsTable.id),
            })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.gte)(tables_1.pulseAlertLogsTable.createdAt, new Date(startDate)), (0, drizzle_orm_1.lte)(tables_1.pulseAlertLogsTable.createdAt, new Date(endDate))))
                .groupBy((0, drizzle_orm_1.sql) `DATE(${tables_1.pulseAlertLogsTable.createdAt})`)
                .orderBy((0, drizzle_orm_1.sql) `DATE(${tables_1.pulseAlertLogsTable.createdAt})`);
            // Format chart data for the component and fill missing date buckets with zero values.
            // This keeps the chart visible even when no incidents exist for the selected range.
            const formattedChartData = this.buildDailyRangeChartData(startDate, endDate, chartData);
            const { restrictionsData, upgradeMetadata, isEnterprise, isStarter, globalBanner, } = await (0, get_upgrade_meta_1.getUpgradeMetaByOrgId)(orgId);
            if (!isEnterprise && restrictionsData?.alerts > 0) {
                const whereConditions = (0, time_1.createTimespanWhereConditions)({
                    table: tables_1.pulseAlertLogsTable,
                    timeColumn: 'createdAt',
                    orgId: orgId,
                    timespan: restrictionsData?.alerts_timespan || 'lifetime',
                });
                const count = await db
                    .select({ count: (0, drizzle_orm_1.sql) `count(*)` }).from(tables_1.pulseAlertLogsTable).where(whereConditions).then((result) => Number(result[0]?.count ?? 0));
                if (count !== 0 && new decimal_js_1.default(count).gte(restrictionsData?.alerts ?? 0)) {
                    upgradeMetadata.upgradeRequired = true;
                    upgradeMetadata.topUpRequired = false;
                    upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.upgrade.title;
                    upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.upgrade.message;
                    upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
                    upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
                    globalBanner.show = true;
                    globalBanner.data.content = `You're out of allotted alerts with your ${restrictionsData?.currentPlan ?? ''} plan. `;
                    globalBanner.data.type = 'upgrade';
                    globalBanner.data.action = 'Upgrade Now';
                    globalBanner.data.actionType = 'upgrade';
                    globalBanner.data.actionContent = `to create more alerts`;
                }
            }
            if (isStarter) {
                upgradeMetadata.upgradeRequired = true;
                upgradeMetadata.topUpRequired = false;
                upgradeMetadata.upgradeTitle = restriction_message_1.RESTRICTION_MESSAGE.upgrade.title;
                upgradeMetadata.upgradeMessage = restriction_message_1.RESTRICTION_MESSAGE.upgrade.message;
                upgradeMetadata.currentPlan = restrictionsData?.currentPlan ?? '';
                upgradeMetadata.currentPlanId = restrictionsData?.currentPlanId ?? '';
            }
            return {
                chartData: formattedChartData,
                upgradeMetadata,
                globalBanner,
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getDashboardSummaryGraph: ${error}`);
            throw error;
        }
    }
    async getSummary(params) {
        try {
            const { startDate, endDate, projectId } = params;
            // Get summary statistics
            const db = (0, database_1.getDb)();
            const alertSummary = await db
                .select({
                totalAlerts: (0, drizzle_orm_1.count)(tables_1.pulseMonitoringAlertsTable.id),
                inactiveAlerts: (0, drizzle_orm_1.sql) `COUNT(CASE WHEN ${tables_1.pulseMonitoringAlertsTable.status} = 0 THEN 1 END)`,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId));
            const incidentSummary = await db
                .select({
                activeAlerts: (0, drizzle_orm_1.sql) `COUNT(DISTINCT ${tables_1.pulseAlertLogsTable.alertId})`,
                totalIncidents: (0, drizzle_orm_1.count)(tables_1.pulseAlertLogsTable.id),
            })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.gte)(tables_1.pulseAlertLogsTable.createdAt, new Date(startDate)), (0, drizzle_orm_1.lte)(tables_1.pulseAlertLogsTable.createdAt, new Date(endDate))));
            // Get top 5 alerts with most incidents
            const topAlerts = await db
                .select({
                id: tables_1.pulseMonitoringAlertsTable.id,
                name: tables_1.pulseMonitoringAlertsTable.name,
                applicationId: tables_1.pulseMonitoringAlertsTable.applicationId,
                applicationName: tables_1.applicationsTable.name,
                alert: tables_1.pulseMonitoringAlertsTable.alert,
                status: tables_1.pulseMonitoringAlertsTable.status,
                alertsTriggered: (0, drizzle_orm_1.count)(tables_1.pulseAlertLogsTable.id),
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
                condition: tables_1.pulseMonitoringAlertsTable.condition,
                notificationChannelId: (0, drizzle_orm_1.sql) `${tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId}`,
                notificationChannelName: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.name}`,
                notificationChannelType: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.type}`,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .leftJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id))
                .leftJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .leftJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .innerJoin(tables_1.pulseAlertLogsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseAlertLogsTable.alertId))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.gte)(tables_1.pulseAlertLogsTable.createdAt, new Date(startDate)), (0, drizzle_orm_1.lte)(tables_1.pulseAlertLogsTable.createdAt, new Date(endDate))))
                .groupBy(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsTable.name, tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.name, tables_1.pulseMonitoringAlertsTable.alert, tables_1.pulseMonitoringAlertsTable.status, tables_1.pulseMonitoringAlertsTable.createdAt, tables_1.pulseMonitoringAlertsTable.condition, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.name, tables_1.notificationChannelTable.type)
                .orderBy((0, drizzle_orm_1.desc)((0, drizzle_orm_1.count)(tables_1.pulseAlertLogsTable.id)))
                .limit(5);
            // Format top alerts data
            const formattedTopAlerts = topAlerts
                .filter((alert) => alert.alertsTriggered > 0)
                .map((alert) => ({
                alertName: alert.name,
                application: alert.applicationName || 'Unknown Application',
                type: alert.alert?.type || 'metric',
                incidents: alert.alertsTriggered || 0,
                notificationChannel: alert.notificationChannelName || 'No Channel',
                notificationChannelType: alert.notificationChannelType || 1,
            }));
            return {
                ...(alertSummary[0] || {
                    totalAlerts: 0,
                    inactiveAlerts: 0,
                }),
                ...(incidentSummary[0] || {
                    activeAlerts: 0,
                    totalIncidents: 0,
                }),
                topAlerts: formattedTopAlerts,
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getSummary: ${error}`);
            throw error;
        }
    }
    async getIncidents(params) {
        try {
            const { startDate, endDate, projectId, page, limit } = params;
            const offset = (page - 1) * limit;
            // Get incidents with pagination
            const db = (0, database_1.getDb)();
            const incidents = await db
                .select({
                id: tables_1.pulseAlertLogsTable.id,
                alertId: tables_1.pulseAlertLogsTable.alertId,
                metrics: tables_1.pulseAlertLogsTable.metrics,
                createdAt: tables_1.pulseAlertLogsTable.createdAt,
                timestamp: tables_1.pulseAlertLogsTable.timestamp,
                count: tables_1.pulseAlertLogsTable.count,
                applicationId: tables_1.pulseAlertLogsTable.applicationId,
                projectId: tables_1.pulseAlertLogsTable.projectId,
                alertName: tables_1.pulseMonitoringAlertsTable.name,
                alertCondition: tables_1.pulseMonitoringAlertsTable.condition,
                applicationName: tables_1.applicationsTable.name,
                notificationChannelType: tables_1.notificationChannelTable.type,
                notificationChannel: tables_1.notificationChannelTable.name,
            })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.applicationId, tables_1.applicationsTable.id))
                .innerJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .innerJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.gte)(tables_1.pulseAlertLogsTable.createdAt, new Date(startDate)), (0, drizzle_orm_1.lte)(tables_1.pulseAlertLogsTable.createdAt, new Date(endDate))))
                .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseAlertLogsTable.createdAt))
                .limit(limit)
                .offset(offset);
            // Get total count for pagination
            const totalCount = await db
                .select({ count: (0, drizzle_orm_1.count)() })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.applicationId, tables_1.applicationsTable.id))
                .innerJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .innerJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.gte)(tables_1.pulseAlertLogsTable.createdAt, new Date(startDate)), (0, drizzle_orm_1.lte)(tables_1.pulseAlertLogsTable.createdAt, new Date(endDate))));
            return {
                incidents,
                pagination: {
                    total: totalCount[0]?.count || 0,
                    page,
                    limit,
                    totalPages: Math.ceil((totalCount[0]?.count || 0) / limit),
                },
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getIncidents: ${error}`);
            throw error;
        }
    }
    async getConditions(params) {
        try {
            const { projectId, page, limit } = params;
            const offset = (page - 1) * limit;
            const db = (0, database_1.getDb)();
            // Get alerts with their conditions, grouped by application
            const alerts = await db
                .select({
                id: tables_1.pulseMonitoringAlertsTable.id,
                applicationId: tables_1.pulseMonitoringAlertsTable.applicationId,
                applicationName: tables_1.applicationsTable.name,
                name: tables_1.pulseMonitoringAlertsTable.name,
                alert: tables_1.pulseMonitoringAlertsTable.alert,
                status: tables_1.pulseMonitoringAlertsTable.status,
                alertsTriggered: tables_1.pulseMonitoringAlertsTable.alertsTriggered,
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
                updatedAt: tables_1.pulseMonitoringAlertsTable.updatedAt,
                condition: tables_1.pulseMonitoringAlertsTable.condition,
                notificationChannelId: (0, drizzle_orm_1.sql) `${tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId}`,
                notificationChannelName: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.name}`,
                notificationChannelType: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.type}`,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id), (0, drizzle_orm_1.eq)(tables_1.applicationsTable.projectId, projectId)))
                .leftJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .leftJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .where((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId) && (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.status, 1))
                .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseMonitoringAlertsTable.createdAt))
                .limit(limit)
                .offset(offset);
            // Get lastAlertAt for each alert from pulseAlertLogsTable
            const alertIds = alerts?.map((alert) => alert.id);
            const lastAlertTimes = alertIds.length > 0
                ? await db
                    .select({
                    alertId: tables_1.pulseAlertLogsTable.alertId,
                    lastAlertAt: (0, drizzle_orm_1.sql) `MAX(${tables_1.pulseAlertLogsTable.createdAt})`,
                })
                    .from(tables_1.pulseAlertLogsTable)
                    .where((0, drizzle_orm_1.sql) `${tables_1.pulseAlertLogsTable.alertId} = ANY(${drizzle_orm_1.sql.raw(`ARRAY[${alertIds.map((id) => `'${id}'`).join(',')}]`)})`)
                    .groupBy(tables_1.pulseAlertLogsTable.alertId)
                : [];
            // Create a map for quick lookup
            const lastAlertMap = new Map();
            lastAlertTimes.forEach((item) => {
                lastAlertMap.set(item.alertId, item.lastAlertAt);
            });
            // Group alerts by application
            const groupedConditions = alerts.reduce((acc, alert) => {
                const existingApp = acc.find((app) => app.applicationName === alert.applicationName);
                const alertData = {
                    id: alert.id,
                    name: alert.name,
                    applicationId: alert.applicationId,
                    applicationName: alert.applicationName,
                    notificationChannelId: alert.notificationChannelId,
                    alert: alert.alert,
                    type: alert.alert?.type || 'metric',
                    incidents: alert.alertsTriggered || 0,
                    alertsConditon: alert.condition || '',
                    notificationChannel: alert.notificationChannelName || 'No Channel',
                    notificationChannelType: alert.notificationChannelType || 1,
                    lastAlertAt: lastAlertMap.get(alert.id) || null,
                    createdAt: alert.createdAt,
                };
                if (existingApp) {
                    existingApp.alerts.push(alertData);
                }
                else {
                    acc.push({
                        applicationName: alert.applicationName || 'Unknown Application',
                        alerts: [alertData],
                    });
                }
                return acc;
            }, []);
            // Get total count for pagination
            const totalCount = await db
                .select({ count: (0, drizzle_orm_1.count)() })
                .from(tables_1.pulseMonitoringAlertsTable)
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.status, 1)));
            return {
                conditions: groupedConditions,
                pagination: {
                    total: totalCount[0]?.count || 0,
                    page,
                    limit,
                    totalPages: Math.ceil((totalCount[0]?.count || 0) / limit),
                },
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getConditions: ${error}`);
            throw error;
        }
    }
    async getConditionDetails(params) {
        try {
            const { alertId, projectId } = params;
            const db = (0, database_1.getDb)();
            // Get alert details with application name
            const condition = await db
                .select({
                id: tables_1.pulseMonitoringAlertsTable.id,
                name: tables_1.pulseMonitoringAlertsTable.name,
                applicationId: tables_1.pulseMonitoringAlertsTable.applicationId,
                applicationName: tables_1.applicationsTable.name,
                alert: tables_1.pulseMonitoringAlertsTable.alert,
                condition: tables_1.pulseMonitoringAlertsTable.condition,
                status: tables_1.pulseMonitoringAlertsTable.status,
                alertsTriggered: tables_1.pulseMonitoringAlertsTable.alertsTriggered,
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
                updatedAt: tables_1.pulseMonitoringAlertsTable.updatedAt,
                notificationChannelId: (0, drizzle_orm_1.sql) `${tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId}`,
                notificationChannelName: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.name}`,
                notificationChannelType: (0, drizzle_orm_1.sql) `${tables_1.notificationChannelTable.type}`,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .leftJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id))
                .leftJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .leftJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, alertId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId)))
                .limit(1);
            if (condition.length === 0) {
                throw new Error('Condition not found');
            }
            const alertData = condition[0];
            // Get lastAlertAt from pulseAlertLogsTable
            const lastAlertTime = await db
                .select({
                lastAlertAt: (0, drizzle_orm_1.sql) `MAX(${tables_1.pulseAlertLogsTable.createdAt})`,
            })
                .from(tables_1.pulseAlertLogsTable)
                .where((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId))
                .groupBy(tables_1.pulseAlertLogsTable.alertId)
                .limit(1);
            return {
                id: alertData.id,
                alertName: alertData.name,
                application: alertData.applicationName || 'Unknown Application',
                type: alertData.alert?.type || 'metric',
                alertsConditon: alertData.condition || alertData.alert?.condition || '',
                notificationChannel: alertData.notificationChannelName || 'No Channel',
                notificationChannelType: alertData.notificationChannelType || 1,
                lastAlertAt: lastAlertTime[0]?.lastAlertAt || alertData.updatedAt,
                createdAt: alertData.createdAt,
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getConditionDetails: ${error}`);
            throw error;
        }
    }
    async getNotificationChannels(params) {
        try {
            const { projectId, page, limit } = params;
            const offset = (page - 1) * limit;
            const db = (0, database_1.getDb)();
            const channels = await db
                .select({
                id: tables_1.notificationChannelTable.id,
                name: tables_1.notificationChannelTable.name,
                type: tables_1.notificationChannelTable.type,
                status: tables_1.notificationChannelTable.status,
                createdAt: tables_1.notificationChannelTable.createdAt,
                config: tables_1.notificationChannelTable.config,
                usedFor: (0, drizzle_orm_1.sql) `(
            SELECT COUNT(*) 
            FROM ${tables_1.pulseMonitoringAlertsToNotificationChannelsTable} 
            WHERE ${tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId} = ${tables_1.notificationChannelTable.id}
          )`,
                details: (0, drizzle_orm_1.sql) `(
            CASE 
              WHEN ${tables_1.notificationChannelTable.type} = ${constants_1.NOTIFICATION_CHANNEL_TYPE.EMAIL} THEN 
                COALESCE(
                  (
                    SELECT string_agg(email, ', ')
                    FROM jsonb_array_elements_text(${tables_1.notificationChannelTable.config}->'emails') AS email
                  ),
                  'No emails configured'
                )
              WHEN ${tables_1.notificationChannelTable.type} = ${constants_1.NOTIFICATION_CHANNEL_TYPE.WEBHOOK} THEN 
                COALESCE(
                  (${tables_1.notificationChannelTable.config}->>'url')::text, 
                  'No URL configured'
                )
              ELSE 'Unknown type'
            END
          )`,
            })
                .from(tables_1.notificationChannelTable)
                .where((0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.projectId, projectId))
                .orderBy((0, drizzle_orm_1.desc)(tables_1.notificationChannelTable.createdAt))
                .limit(limit)
                .offset(offset);
            // Get total count for pagination
            const totalCount = await db
                .select({ count: (0, drizzle_orm_1.count)() })
                .from(tables_1.notificationChannelTable)
                .where((0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.projectId, projectId));
            return {
                channels,
                pagination: {
                    total: totalCount?.[0]?.count || 0,
                    page,
                    limit,
                    totalPages: Math.ceil((totalCount[0]?.count || 0) / limit),
                },
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getNotificationChannels: ${error}`);
            throw error;
        }
    }
    async getNotificationChannelDetails(params) {
        try {
            const { notificationChannelId, projectId } = params;
            const db = (0, database_1.getDb)();
            // Get the notification channel with details
            const channel = await db
                .select({
                id: tables_1.notificationChannelTable.id,
                name: tables_1.notificationChannelTable.name,
                type: tables_1.notificationChannelTable.type,
                status: tables_1.notificationChannelTable.status,
                createdAt: tables_1.notificationChannelTable.createdAt,
                details: (0, drizzle_orm_1.sql) `(
            CASE 
              WHEN ${tables_1.notificationChannelTable.type} = ${constants_1.NOTIFICATION_CHANNEL_TYPE.EMAIL} THEN 
                COALESCE(
                  (
                    SELECT string_agg(e.value, ', ')
                    FROM jsonb_array_elements_text(${tables_1.notificationChannelTable.config}->'emails') AS e(value)
                  ),
                  'No emails configured'
                )
              WHEN ${tables_1.notificationChannelTable.type} = ${constants_1.NOTIFICATION_CHANNEL_TYPE.WEBHOOK} THEN 
                COALESCE(
                  (${tables_1.notificationChannelTable.config}->>'url')::text, 
                  'No URL configured'
                )
              ELSE 'Unknown type'
            END
          )`,
            })
                .from(tables_1.notificationChannelTable)
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.id, notificationChannelId), (0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.projectId, projectId)))
                .limit(1);
            if (channel.length === 0) {
                throw new Error('Notification channel not found');
            }
            return {
                ...channel[0],
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getNotificationChannelDetails: ${error}`);
            throw error;
        }
    }
    async createNotificationChannel(params) {
        try {
            const { name, type, emails, webhookConfig, projectId } = params;
            // Check if a notification channel with the same name already exists for the project
            const db = (0, database_1.getDb)();
            const existing = await db
                .select()
                .from(tables_1.notificationChannelTable)
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.name, name), (0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.projectId, projectId)))
                .limit(1);
            if (existing.length > 0) {
                throw new Error('A notification channel with this name already exists in the project.');
            }
            // Prepare config based on type type
            const id = (0, uuid_1.v4)();
            let config = {};
            if (type === constants_1.NOTIFICATION_CHANNEL_TYPE.EMAIL) {
                config = {
                    emails: emails?.split(',').map((email) => email.trim()),
                };
            }
            else if (type === constants_1.NOTIFICATION_CHANNEL_TYPE.WEBHOOK) {
                config = webhookConfig;
            }
            const newChannel = await db
                .insert(tables_1.notificationChannelTable)
                .values({
                id,
                name,
                type,
                config,
                projectId,
                status: constants_1.NOTIFICATION_CHANNEL_STATUS.ACTIVE,
                createdAt: new Date(),
                updatedAt: new Date(),
            })
                .returning();
            return newChannel[0];
        }
        catch (error) {
            logger_1.logger.error(`Error in createNotificationChannel: ${error}`);
            throw error;
        }
    }
    async createAlert(params) {
        try {
            const { name, applicationId, alert, notificationChannel, projectId, workspaceId, projectName } = params;
            // Generate unique ID
            const id = (0, uuid_1.v4)();
            const db = (0, database_1.getDb)();
            const newAlert = await db
                .insert(tables_1.pulseMonitoringAlertsTable)
                .values({
                id,
                name,
                applicationId,
                alert: {
                    ...alert,
                    projectName,
                },
                condition: (0, exports.getAlertConditionTitle)(alert),
                projectId,
                workspaceId,
                status: 1,
                alertsTriggered: 0,
                createdAt: new Date(),
                updatedAt: new Date(),
            })
                .returning();
            // If notification channel is provided, create the relationship
            if (notificationChannel) {
                await db.insert(tables_1.pulseMonitoringAlertsToNotificationChannelsTable).values({
                    alertId: id,
                    notificationChannelId: notificationChannel,
                    createdAt: new Date(),
                });
            }
            return newAlert[0];
        }
        catch (error) {
            logger_1.logger.error(`Error in createAlert: ${error}`);
            throw error;
        }
    }
    async getNotificationChannelAlerts(params) {
        try {
            const { projectId, page, limit, notificationChannelId } = params;
            const offset = (page - 1) * limit;
            const db = (0, database_1.getDb)();
            // Define common where conditions to avoid duplication
            const whereConditions = (0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, notificationChannelId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId));
            // Get related alerts for this notification channel
            const alerts = await db
                .select({
                id: tables_1.pulseMonitoringAlertsTable.id,
                applicationId: tables_1.pulseMonitoringAlertsTable.applicationId,
                applicationName: tables_1.applicationsTable.name,
                alertsTriggered: tables_1.pulseMonitoringAlertsTable.alertsTriggered,
                createdAt: tables_1.pulseMonitoringAlertsTable.createdAt,
                alertName: tables_1.pulseMonitoringAlertsTable.name,
                alertCondition: tables_1.pulseMonitoringAlertsTable.condition,
            })
                .from(tables_1.pulseMonitoringAlertsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .innerJoin(tables_1.applicationsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.applicationId, tables_1.applicationsTable.id))
                .where(whereConditions)
                .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseMonitoringAlertsTable.createdAt))
                .limit(limit)
                .offset(offset);
            // Get total count using the same where conditions
            const totalCount = await db
                .select({ count: (0, drizzle_orm_1.count)() })
                .from(tables_1.pulseMonitoringAlertsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .where(whereConditions);
            return {
                alerts,
                pagination: {
                    total: totalCount[0]?.count || 0,
                    page,
                    limit,
                    totalPages: Math.ceil((totalCount[0]?.count || 0) / limit),
                },
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getNotificationChannelAlerts: ${error}`);
            throw error;
        }
    }
    async getAlertIncidents(params) {
        try {
            const { projectId, page, limit, alertId } = params;
            const offset = (page - 1) * limit;
            const db = (0, database_1.getDb)();
            // Get incidents for this specific alert
            const incidents = await db
                .select({
                id: tables_1.pulseAlertLogsTable.id,
                // alertId: pulseAlertLogsTable.alertId,
                // metrics: pulseAlertLogsTable.metrics,
                createdAt: tables_1.pulseAlertLogsTable.createdAt,
                timestamp: tables_1.pulseAlertLogsTable.timestamp,
                //count: pulseAlertLogsTable.count,
                //applicationId: pulseAlertLogsTable.applicationId,
                // projectId: pulseAlertLogsTable.projectId,
                alertName: tables_1.pulseMonitoringAlertsTable.alert,
                alertCondition: tables_1.pulseMonitoringAlertsTable.condition,
                notificationChannelType: tables_1.notificationChannelTable.type,
                notificationChannel: tables_1.notificationChannelTable.name,
            })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .innerJoin(tables_1.pulseMonitoringAlertsToNotificationChannelsTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, tables_1.pulseMonitoringAlertsToNotificationChannelsTable.alertId))
                .leftJoin(tables_1.notificationChannelTable, (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsToNotificationChannelsTable.notificationChannelId, tables_1.notificationChannelTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId)))
                .orderBy((0, drizzle_orm_1.desc)(tables_1.pulseAlertLogsTable.createdAt))
                .limit(limit)
                .offset(offset);
            // Get total count for pagination
            const totalCount = await db
                .select({ count: (0, drizzle_orm_1.count)() })
                .from(tables_1.pulseAlertLogsTable)
                .innerJoin(tables_1.pulseMonitoringAlertsTable, (0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, tables_1.pulseMonitoringAlertsTable.id))
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseAlertLogsTable.alertId, alertId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId)));
            return {
                incidents,
                pagination: {
                    total: totalCount[0]?.count || 0,
                    page,
                    limit,
                    totalPages: Math.ceil((totalCount[0]?.count || 0) / limit),
                },
            };
        }
        catch (error) {
            logger_1.logger.error(`Error in getAlertIncidents: ${error}`);
            throw error;
        }
    }
    async updateAlert(params) {
        try {
            const { alertId, name, applicationId, alert, projectId } = params;
            // Generate condition based on alert type
            const condition = (0, exports.getAlertConditionTitle)(alert);
            const db = (0, database_1.getDb)();
            const updatedAlert = await db
                .update(tables_1.pulseMonitoringAlertsTable)
                .set({
                name,
                applicationId,
                alert,
                condition,
                updatedAt: new Date(),
            })
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.id, alertId), (0, drizzle_orm_1.eq)(tables_1.pulseMonitoringAlertsTable.projectId, projectId)))
                .returning();
            if (updatedAlert.length === 0) {
                throw new Error('Alert not found');
            }
            return updatedAlert[0];
        }
        catch (error) {
            logger_1.logger.error(`Error in updateAlert: ${error}`);
            throw error;
        }
    }
    async updateNotificationChannel(params) {
        try {
            const { notificationChannelId, name, type, emails, webhookConfig, projectId } = params;
            // Prepare config based on type type
            let config = {};
            if (type === constants_1.NOTIFICATION_CHANNEL_TYPE.EMAIL) {
                config = {
                    emails: emails?.split(',').map((email) => email.trim()),
                };
            }
            else if (type === constants_1.NOTIFICATION_CHANNEL_TYPE.WEBHOOK) {
                config = webhookConfig;
            }
            const db = (0, database_1.getDb)();
            const updatedChannel = await db
                .update(tables_1.notificationChannelTable)
                .set({
                name,
                type,
                config,
                updatedAt: new Date(),
            })
                .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.id, notificationChannelId), (0, drizzle_orm_1.eq)(tables_1.notificationChannelTable.projectId, projectId)))
                .returning();
            if (updatedChannel.length === 0) {
                throw new Error('Notification channel not found');
            }
            return updatedChannel[0];
        }
        catch (error) {
            logger_1.logger.error(`Error in updateNotificationChannel: ${error}`);
            throw error;
        }
    }
}
exports.AlertsService = AlertsService;
//# sourceMappingURL=alertsService.js.map