var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import DatabaseConfig from "../DatabaseConfig";
import QueryHelper from "../Types/Database/QueryHelper";
import { applyAlertSelfPrivacyFilter } from "../Utils/Alert/AlertPrivacyFilter";
import DatabaseService from "./DatabaseService";
import AlertOwnerTeamService from "./AlertOwnerTeamService";
import AlertOwnerUserService from "./AlertOwnerUserService";
import AlertStateService from "./AlertStateService";
import AlertStateTimelineService from "./AlertStateTimelineService";
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
import TeamMemberService from "./TeamMemberService";
import UserService from "./UserService";
import URL from "../../Types/API/URL";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
import BadDataException from "../../Types/Exception/BadDataException";
import ObjectID from "../../Types/ObjectID";
import Typeof from "../../Types/Typeof";
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
import Model from "../../Models/DatabaseModels/Alert";
import AlertOwnerTeam from "../../Models/DatabaseModels/AlertOwnerTeam";
import AlertOwnerUser from "../../Models/DatabaseModels/AlertOwnerUser";
import AlertStateTimeline from "../../Models/DatabaseModels/AlertStateTimeline";
import { IsBillingEnabled } from "../EnvironmentConfig";
import logger from "../Utils/Logger";
import TelemetryUtil from "../Utils/Telemetry/Telemetry";
import MetricService from "./MetricService";
import GlobalConfigService from "./GlobalConfigService";
import OneUptimeDate from "../../Types/Date";
import Metric, { MetricPointType } from "../../Models/AnalyticsModels/Metric";
import ServiceType from "../../Types/Telemetry/ServiceType";
import AlertMetricType from "../../Types/Alerts/AlertMetricType";
import AlertFeedService from "./AlertFeedService";
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
import { Gray500, Red500 } from "../../Types/BrandColors";
import LabelService from "./LabelService";
import AlertSeverityService from "./AlertSeverityService";
import AlertWorkspaceMessages from "../Utils/Workspace/WorkspaceMessages/Alert";
import MonitorService from "./MonitorService";
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
import MetricType from "../../Models/DatabaseModels/MetricType";
import AlertGroupingEngineService from "./AlertGroupingEngineService";
import AlertLabelRuleEngineService from "./AlertLabelRuleEngineService";
import AlertOnCallRuleEngineService from "./AlertOnCallRuleEngineService";
import AlertOwnerRuleEngineService from "./AlertOwnerRuleEngineService";
import RunbookRuleEngineService from "./RunbookRuleEngineService";
import AlertPrivacyRuleEngineService from "./AlertPrivacyRuleEngineService";
import ProjectService from "./ProjectService";
export class Service extends DatabaseService {
    constructor() {
        super(Model);
        if (IsBillingEnabled) {
            this.hardDeleteItemsOlderThanInDays("createdAt", 3 * 365); // 3 years
        }
    }
    async isAlertAcknowledged(data) {
        const alert = await this.findOneBy({
            query: {
                _id: data.alertId,
            },
            select: {
                projectId: true,
                currentAlertState: {
                    order: true,
                },
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert) {
            throw new BadDataException("Alert not found");
        }
        if (!alert.projectId) {
            throw new BadDataException("Alert Project ID not found");
        }
        const ackAlertState = await AlertStateService.getAcknowledgedAlertState({
            projectId: alert.projectId,
            props: {
                isRoot: true,
            },
        });
        const currentAlertStateOrder = alert.currentAlertState.order;
        const ackAlertStateOrder = ackAlertState.order;
        if (currentAlertStateOrder >= ackAlertStateOrder) {
            return true;
        }
        return false;
    }
    async acknowledgeAlert(alertId, acknowledgedByUserId) {
        const alert = await this.findOneById({
            id: alertId,
            select: {
                projectId: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert || !alert.projectId) {
            throw new BadDataException("Alert not found.");
        }
        const alertState = await AlertStateService.findOneBy({
            query: {
                projectId: alert.projectId,
                isAcknowledgedState: true,
            },
            select: {
                _id: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alertState || !alertState.id) {
            throw new BadDataException("Acknowledged state not found for this project. Please add acknowledged state from settings.");
        }
        const alertStateTimeline = new AlertStateTimeline();
        alertStateTimeline.projectId = alert.projectId;
        alertStateTimeline.alertId = alertId;
        alertStateTimeline.alertStateId = alertState.id;
        alertStateTimeline.createdByUserId = acknowledgedByUserId;
        await AlertStateTimelineService.create({
            data: alertStateTimeline,
            props: {
                isRoot: true,
            },
        });
    }
    async onBeforeFind(findBy) {
        findBy.query = applyAlertSelfPrivacyFilter(findBy.query, findBy.props);
        return { findBy, carryForward: null };
    }
    async countBy(countBy) {
        countBy.query = applyAlertSelfPrivacyFilter(countBy.query, countBy.props);
        return super.countBy(countBy);
    }
    async onBeforeUpdate(updateBy) {
        updateBy.query = applyAlertSelfPrivacyFilter(updateBy.query, updateBy.props);
        return { updateBy, carryForward: null };
    }
    async onBeforeCreate(createBy) {
        if (!createBy.props.tenantId && !createBy.props.isRoot) {
            throw new BadDataException("ProjectId required to create alert.");
        }
        const projectId = createBy.props.tenantId || createBy.data.projectId;
        const alertState = await AlertStateService.findOneBy({
            query: {
                projectId: projectId,
                isCreatedState: true,
            },
            select: {
                _id: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alertState || !alertState.id) {
            throw new BadDataException("Created alert state not found for this project. Please add created alert state from settings.");
        }
        createBy.data.currentAlertStateId = alertState.id;
        const alertCounterResult = await ProjectService.incrementAndGetAlertCounter(projectId);
        createBy.data.alertNumber = alertCounterResult.counter;
        createBy.data.alertNumberWithPrefix = alertCounterResult.prefix
            ? `${alertCounterResult.prefix}${alertCounterResult.counter}`
            : `#${alertCounterResult.counter}`;
        if ((createBy.data.createdByUserId ||
            createBy.data.createdByUser ||
            createBy.props.userId) &&
            !createBy.data.rootCause) {
            let userId = createBy.data.createdByUserId;
            if (createBy.props.userId) {
                userId = createBy.props.userId;
            }
            if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
                userId = createBy.data.createdByUser.id;
            }
            if (userId) {
                createBy.data.rootCause = `Alert created by ${await UserService.getUserMarkdownString({
                    userId: userId,
                    projectId: projectId,
                })}`;
            }
        }
        return { createBy, carryForward: null };
    }
    async onCreateSuccess(onCreate, createdItem) {
        if (!createdItem.projectId) {
            throw new BadDataException("projectId is required");
        }
        if (!createdItem.id) {
            throw new BadDataException("id is required");
        }
        if (!createdItem.currentAlertStateId) {
            throw new BadDataException("currentAlertStateId is required");
        }
        // Execute operations sequentially with error handling
        Promise.resolve()
            .then(async () => {
            var _a, _b;
            /*
             * Apply privacy rules BEFORE workspace operations so the workspace
             * channel is created with the correct privacy setting. This may set
             * createdItem.isPrivate=true in memory.
             */
            try {
                await AlertPrivacyRuleEngineService.applyRulesToAlert(createdItem);
            }
            catch (error) {
                logger.error(`Apply alert privacy rules failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
            }
        })
            .then(async () => {
            var _a, _b;
            if (createdItem.projectId && createdItem.id) {
                try {
                    return await this.handleAlertWorkspaceOperationsAsync(createdItem);
                }
                catch (error) {
                    logger.error(`Workspace operations failed in AlertService.onCreateSuccess: ${error}`, {
                        projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                        alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                    });
                    return Promise.resolve();
                }
            }
            return Promise.resolve();
        })
            .then(async () => {
            var _a, _b;
            try {
                return await this.createAlertFeedAsync(createdItem.id);
            }
            catch (error) {
                logger.error(`Create alert feed failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
                return Promise.resolve(); // Continue chain even on error
            }
        })
            .then(async () => {
            var _a, _b;
            try {
                return await this.handleAlertStateChangeAsync(createdItem);
            }
            catch (error) {
                logger.error(`Handle alert state change failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
                return Promise.resolve(); // Continue chain even on error
            }
        })
            .then(async () => {
            var _a, _b;
            try {
                if (onCreate.createBy.miscDataProps &&
                    (onCreate.createBy.miscDataProps["ownerTeams"] ||
                        onCreate.createBy.miscDataProps["ownerUsers"])) {
                    return await this.addOwners(createdItem.projectId, createdItem.id, onCreate.createBy.miscDataProps["ownerUsers"] || [], onCreate.createBy.miscDataProps["ownerTeams"] || [], false, onCreate.createBy.props);
                }
                return Promise.resolve();
            }
            catch (error) {
                logger.error(`Add owners failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
                return Promise.resolve(); // Continue chain even on error
            }
        })
            .then(async () => {
            var _a, _b;
            // Apply owner rules: add matched owner users/teams to the alert.
            try {
                await AlertOwnerRuleEngineService.applyRulesToAlert(createdItem);
            }
            catch (error) {
                logger.error(`Apply alert owner rules failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
            }
        })
            .then(async () => {
            var _a, _b;
            // Apply label rules: attach matched (and inherited monitor) labels.
            try {
                await AlertLabelRuleEngineService.applyRulesToAlert(createdItem);
            }
            catch (error) {
                logger.error(`Apply alert label rules failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
            }
        })
            .then(async () => {
            var _a, _b;
            /*
             * Apply on-call rules: match alert against AlertOnCallRule rows and
             * merge their on-call policies into createdItem.onCallDutyPolicies
             * before the fan-out below picks up the merged list.
             */
            try {
                await AlertOnCallRuleEngineService.applyRulesToAlert(createdItem);
            }
            catch (error) {
                logger.error(`Apply alert on-call rules failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
            }
        })
            .then(async () => {
            var _a, _b;
            try {
                await RunbookRuleEngineService.applyRulesToAlert(createdItem);
            }
            catch (error) {
                logger.error(`Apply runbook rules failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
            }
        })
            .then(async () => {
            var _a, _b, _c, _d;
            if (((_a = createdItem.onCallDutyPolicies) === null || _a === void 0 ? void 0 : _a.length) &&
                ((_b = createdItem.onCallDutyPolicies) === null || _b === void 0 ? void 0 : _b.length) > 0) {
                try {
                    return await this.executeAlertOnCallDutyPoliciesAsync(createdItem);
                }
                catch (error) {
                    logger.error(`On-call duty policy execution failed in AlertService.onCreateSuccess: ${error}`, {
                        projectId: (_c = createdItem.projectId) === null || _c === void 0 ? void 0 : _c.toString(),
                        alertId: (_d = createdItem.id) === null || _d === void 0 ? void 0 : _d.toString(),
                    });
                    return Promise.resolve();
                }
            }
            return Promise.resolve();
        })
            .then(async () => {
            var _a, _b;
            // Process alert for grouping into episodes
            try {
                await AlertGroupingEngineService.processAlert(createdItem);
            }
            catch (error) {
                logger.error(`Alert grouping failed in AlertService.onCreateSuccess: ${error}`, {
                    projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
                });
                return Promise.resolve();
            }
        })
            .catch((error) => {
            var _a, _b;
            logger.error(`Critical error in AlertService sequential operations: ${error}`, {
                projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
            });
        });
        return createdItem;
    }
    async handleAlertWorkspaceOperationsAsync(createdItem) {
        var _a, _b, _c, _d, _e, _f, _g;
        try {
            if (!createdItem.projectId || !createdItem.id) {
                throw new BadDataException("projectId and id are required for workspace operations");
            }
            // send message to workspaces - slack, teams, etc.
            const workspaceResult = await AlertWorkspaceMessages.createChannelsAndInviteUsersToChannels(Object.assign(Object.assign({ projectId: createdItem.projectId, alertId: createdItem.id, alertNumber: createdItem.alertNumber }, (createdItem.alertNumberWithPrefix
                ? { alertNumberWithPrefix: createdItem.alertNumberWithPrefix }
                : {})), { isPrivate: createdItem.isPrivate === true }));
            logger.debug("Alert created. Workspace result:", {
                projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
            });
            logger.debug(workspaceResult, {
                projectId: (_c = createdItem.projectId) === null || _c === void 0 ? void 0 : _c.toString(),
                alertId: (_d = createdItem.id) === null || _d === void 0 ? void 0 : _d.toString(),
            });
            if (workspaceResult && ((_e = workspaceResult.channelsCreated) === null || _e === void 0 ? void 0 : _e.length) > 0) {
                // update alert with these channels.
                await this.updateOneById({
                    id: createdItem.id,
                    data: {
                        postUpdatesToWorkspaceChannels: workspaceResult.channelsCreated || [],
                    },
                    props: {
                        isRoot: true,
                    },
                });
            }
        }
        catch (error) {
            logger.error(`Error in handleAlertWorkspaceOperationsAsync: ${error}`, {
                projectId: (_f = createdItem.projectId) === null || _f === void 0 ? void 0 : _f.toString(),
                alertId: (_g = createdItem.id) === null || _g === void 0 ? void 0 : _g.toString(),
            });
            throw error;
        }
    }
    async createAlertFeedAsync(alertId) {
        var _a, _b, _c, _d;
        try {
            // Get alert data for feed creation
            const alert = await this.findOneById({
                id: alertId,
                select: {
                    projectId: true,
                    alertNumber: true,
                    alertNumberWithPrefix: true,
                    title: true,
                    description: true,
                    alertSeverity: {
                        name: true,
                    },
                    rootCause: true,
                    createdByUserId: true,
                    createdByUser: {
                        _id: true,
                        name: true,
                        email: true,
                    },
                    remediationNotes: true,
                    currentAlertState: {
                        name: true,
                    },
                    labels: {
                        name: true,
                    },
                    monitor: {
                        name: true,
                        _id: true,
                    },
                },
                props: {
                    isRoot: true,
                },
            });
            if (!alert) {
                throw new BadDataException("Alert not found");
            }
            const createdByUserId = alert.createdByUserId || ((_a = alert.createdByUser) === null || _a === void 0 ? void 0 : _a.id);
            let feedInfoInMarkdown = `#### 🚨 Alert ${alert.alertNumberWithPrefix || "#" + ((_b = alert.alertNumber) === null || _b === void 0 ? void 0 : _b.toString())} Created:
           
**${alert.title || "No title provided."}**:
     
${alert.description || "No description provided."}
     
`;
            if ((_c = alert.currentAlertState) === null || _c === void 0 ? void 0 : _c.name) {
                feedInfoInMarkdown += `🔴 **Alert State**: ${alert.currentAlertState.name} \n\n`;
            }
            if ((_d = alert.alertSeverity) === null || _d === void 0 ? void 0 : _d.name) {
                feedInfoInMarkdown += `⚠️ **Severity**: ${alert.alertSeverity.name} \n\n`;
            }
            if (alert.monitor) {
                feedInfoInMarkdown += `🌎 **Resources Affected**:\n`;
                const monitor = alert.monitor;
                feedInfoInMarkdown += `- [${monitor.name}](${(await MonitorService.getMonitorLinkInDashboard(alert.projectId, monitor.id)).toString()})\n`;
                feedInfoInMarkdown += `\n\n`;
            }
            if (alert.rootCause) {
                feedInfoInMarkdown += `\n
📄 **Root Cause**:
     
${alert.rootCause || "No root cause provided."}
     
`;
            }
            if (alert.remediationNotes) {
                feedInfoInMarkdown += `\n 
🎯 **Remediation Notes**:
     
${alert.remediationNotes || "No remediation notes provided."}
     
     
     `;
            }
            const alertCreateMessageBlocks = await AlertWorkspaceMessages.getAlertCreateMessageBlocks({
                alertId: alert.id,
                projectId: alert.projectId,
            });
            await AlertFeedService.createAlertFeedItem({
                alertId: alert.id,
                projectId: alert.projectId,
                alertFeedEventType: AlertFeedEventType.AlertCreated,
                displayColor: Red500,
                feedInfoInMarkdown: feedInfoInMarkdown,
                userId: createdByUserId || undefined,
                workspaceNotification: {
                    appendMessageBlocks: alertCreateMessageBlocks,
                    sendWorkspaceNotification: true,
                },
            });
        }
        catch (error) {
            logger.error(`Error in createAlertFeedAsync: ${error}`, {
                alertId: alertId === null || alertId === void 0 ? void 0 : alertId.toString(),
            });
            throw error;
        }
    }
    async handleAlertStateChangeAsync(createdItem) {
        var _a, _b;
        try {
            if (!createdItem.projectId || !createdItem.id) {
                throw new BadDataException("projectId and id are required for state change");
            }
            await this.changeAlertState({
                projectId: createdItem.projectId,
                alertId: createdItem.id,
                alertStateId: createdItem.currentAlertStateId,
                notifyOwners: false,
                rootCause: createdItem.rootCause,
                stateChangeLog: createdItem.createdStateLog,
                props: {
                    isRoot: true,
                },
            });
        }
        catch (error) {
            logger.error(`Error in handleAlertStateChangeAsync: ${error}`, {
                projectId: (_a = createdItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                alertId: (_b = createdItem.id) === null || _b === void 0 ? void 0 : _b.toString(),
            });
            throw error;
        }
    }
    async executeAlertOnCallDutyPoliciesAsync(createdItem) {
        var _a, _b, _c, _d;
        try {
            if (((_a = createdItem.onCallDutyPolicies) === null || _a === void 0 ? void 0 : _a.length) &&
                ((_b = createdItem.onCallDutyPolicies) === null || _b === void 0 ? void 0 : _b.length) > 0) {
                // Execute all on-call policies in parallel
                const policyPromises = createdItem.onCallDutyPolicies.map((policy) => {
                    return OnCallDutyPolicyService.executePolicy(new ObjectID(policy["_id"]), {
                        triggeredByAlertId: createdItem.id,
                        userNotificationEventType: UserNotificationEventType.AlertCreated,
                    });
                });
                await Promise.allSettled(policyPromises);
            }
        }
        catch (error) {
            logger.error(`Error in executeAlertOnCallDutyPoliciesAsync: ${error}`, {
                projectId: (_c = createdItem.projectId) === null || _c === void 0 ? void 0 : _c.toString(),
                alertId: (_d = createdItem.id) === null || _d === void 0 ? void 0 : _d.toString(),
            });
            throw error;
        }
    }
    async getWorkspaceChannelForAlert(data) {
        const alert = await this.findOneById({
            id: data.alertId,
            select: {
                postUpdatesToWorkspaceChannels: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert) {
            throw new BadDataException("Alert not found.");
        }
        return (alert.postUpdatesToWorkspaceChannels || []).filter((channel) => {
            if (!data.workspaceType) {
                return true;
            }
            return channel.workspaceType === data.workspaceType;
        });
    }
    async getAlertIdentifiedDate(alertId) {
        const timeline = await AlertStateTimelineService.findOneBy({
            query: {
                alertId: alertId,
            },
            select: {
                startsAt: true,
            },
            sort: {
                startsAt: SortOrder.Ascending,
            },
            props: {
                isRoot: true,
            },
        });
        if (!timeline || !timeline.startsAt) {
            throw new BadDataException("Alert identified date not found.");
        }
        return timeline.startsAt;
    }
    async findOwners(alertId) {
        if (!alertId) {
            throw new BadDataException("alertId is required");
        }
        const ownerUsers = await AlertOwnerUserService.findBy({
            query: {
                alertId: alertId,
            },
            select: {
                _id: true,
                user: {
                    _id: true,
                    email: true,
                    name: true,
                    timezone: true,
                },
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const ownerTeams = await AlertOwnerTeamService.findBy({
            query: {
                alertId: alertId,
            },
            select: {
                _id: true,
                teamId: true,
            },
            skip: 0,
            limit: LIMIT_PER_PROJECT,
            props: {
                isRoot: true,
            },
        });
        const users = ownerUsers.map((ownerUser) => {
            return ownerUser.user;
        }) || [];
        if (ownerTeams.length > 0) {
            const teamIds = ownerTeams.map((ownerTeam) => {
                return ownerTeam.teamId;
            }) || [];
            const teamUsers = await TeamMemberService.getUsersInTeams(teamIds);
            for (const teamUser of teamUsers) {
                //check if the user is already added.
                const isUserAlreadyAdded = users.find((user) => {
                    return user.id.toString() === teamUser.id.toString();
                });
                if (!isUserAlreadyAdded) {
                    users.push(teamUser);
                }
            }
        }
        return users;
    }
    async addOwners(projectId, alertId, userIds, teamIds, notifyOwners, props) {
        for (let teamId of teamIds) {
            if (typeof teamId === Typeof.String) {
                teamId = new ObjectID(teamId.toString());
            }
            const teamOwner = new AlertOwnerTeam();
            teamOwner.alertId = alertId;
            teamOwner.projectId = projectId;
            teamOwner.teamId = teamId;
            teamOwner.isOwnerNotified = !notifyOwners;
            await AlertOwnerTeamService.create({
                data: teamOwner,
                props: props,
            });
        }
        for (let userId of userIds) {
            if (typeof userId === Typeof.String) {
                userId = new ObjectID(userId.toString());
            }
            const teamOwner = new AlertOwnerUser();
            teamOwner.alertId = alertId;
            teamOwner.projectId = projectId;
            teamOwner.userId = userId;
            teamOwner.isOwnerNotified = !notifyOwners;
            await AlertOwnerUserService.create({
                data: teamOwner,
                props: props,
            });
        }
    }
    async getAlertLinkInDashboard(projectId, alertId) {
        const dashboardUrl = await DatabaseConfig.getDashboardUrl();
        return URL.fromString(dashboardUrl.toString()).addRoute(`/${projectId.toString()}/alerts/${alertId.toString()}`);
    }
    async onUpdateSuccess(onUpdate, updatedItemIds) {
        var _a;
        if (onUpdate.updateBy.data.currentAlertStateId &&
            onUpdate.updateBy.props.tenantId) {
            for (const itemId of updatedItemIds) {
                await this.changeAlertState({
                    projectId: onUpdate.updateBy.props.tenantId,
                    alertId: itemId,
                    alertStateId: onUpdate.updateBy.data.currentAlertStateId,
                    notifyOwners: true,
                    rootCause: "This status was changed when the alert was updated.",
                    stateChangeLog: undefined,
                    props: {
                        isRoot: true,
                    },
                });
            }
        }
        if (updatedItemIds.length > 0) {
            for (const alertId of updatedItemIds) {
                let shouldAddAlertFeed = false;
                const alert = await this.findOneById({
                    id: alertId,
                    select: {
                        projectId: true,
                        alertNumber: true,
                        alertNumberWithPrefix: true,
                    },
                    props: {
                        isRoot: true,
                    },
                });
                const projectId = alert.projectId;
                const alertNumber = alert.alertNumber;
                const alertNumberWithPrefix = alert.alertNumberWithPrefix || undefined;
                let feedInfoInMarkdown = `**[Alert ${alertNumberWithPrefix || "#" + alertNumber}](${(await this.getAlertLinkInDashboard(projectId, alertId)).toString()}) was updated.**`;
                const createdByUserId = onUpdate.updateBy.props.userId;
                if (onUpdate.updateBy.data.title) {
                    // add alert feed.
                    feedInfoInMarkdown += `\n\n**Title**: 
${onUpdate.updateBy.data.title || "No title provided."}
`;
                    shouldAddAlertFeed = true;
                }
                if (onUpdate.updateBy.data.rootCause) {
                    if (onUpdate.updateBy.data.title) {
                        // add alert feed.
                        feedInfoInMarkdown += `\n\n**📄 Root Cause**: 
${onUpdate.updateBy.data.rootCause || "No root cause provided."}
  `;
                        shouldAddAlertFeed = true;
                    }
                }
                if (onUpdate.updateBy.data.description) {
                    // add alert feed.
                    feedInfoInMarkdown += `\n\n**Alert Description**: 
          ${onUpdate.updateBy.data.description || "No description provided."}
          `;
                    shouldAddAlertFeed = true;
                }
                if (onUpdate.updateBy.data.remediationNotes) {
                    // add alert feed.
                    feedInfoInMarkdown += `\n\n**🎯 Remediation Notes**: 
${onUpdate.updateBy.data.remediationNotes || "No remediation notes provided."}
        `;
                    shouldAddAlertFeed = true;
                }
                if (onUpdate.updateBy.data.labels &&
                    onUpdate.updateBy.data.labels.length > 0 &&
                    Array.isArray(onUpdate.updateBy.data.labels)) {
                    const labelIds = onUpdate.updateBy.data.labels
                        .map((label) => {
                        var _a;
                        if (label._id) {
                            return new ObjectID((_a = label._id) === null || _a === void 0 ? void 0 : _a.toString());
                        }
                        return null;
                    })
                        .filter((labelId) => {
                        return labelId !== null;
                    });
                    const labels = await LabelService.findBy({
                        query: {
                            _id: QueryHelper.any(labelIds),
                        },
                        select: {
                            name: true,
                        },
                        limit: LIMIT_PER_PROJECT,
                        skip: 0,
                        props: {
                            isRoot: true,
                        },
                    });
                    if (labels.length > 0) {
                        feedInfoInMarkdown += `\n\n**🏷️ Labels**:

${labels
                            .map((label) => {
                            return `- ${label.name}`;
                        })
                            .join("\n")}
`;
                        shouldAddAlertFeed = true;
                    }
                }
                if (onUpdate.updateBy.data.alertSeverity &&
                    onUpdate.updateBy.data.alertSeverity._id) {
                    const alertSeverity = await AlertSeverityService.findOneBy({
                        query: {
                            _id: new ObjectID((_a = onUpdate.updateBy.data.alertSeverity) === null || _a === void 0 ? void 0 : _a._id.toString()),
                        },
                        select: {
                            name: true,
                        },
                        props: {
                            isRoot: true,
                        },
                    });
                    if (alertSeverity) {
                        feedInfoInMarkdown += `\n\n**⚠️ Alert Severity**:
${alertSeverity.name}
`;
                        shouldAddAlertFeed = true;
                    }
                }
                if (shouldAddAlertFeed) {
                    await AlertFeedService.createAlertFeedItem({
                        alertId: alertId,
                        projectId: onUpdate.updateBy.props.tenantId,
                        alertFeedEventType: AlertFeedEventType.AlertUpdated,
                        displayColor: Gray500,
                        feedInfoInMarkdown: feedInfoInMarkdown,
                        userId: createdByUserId || undefined,
                        workspaceNotification: {
                            sendWorkspaceNotification: true,
                        },
                    });
                }
            }
        }
        return onUpdate;
    }
    async doesMonitorHasMoreActiveManualAlerts(monitorId, proojectId) {
        const resolvedState = await AlertStateService.findOneBy({
            query: {
                projectId: proojectId,
                isResolvedState: true,
            },
            props: {
                isRoot: true,
            },
            select: {
                _id: true,
                order: true,
            },
        });
        const alertCount = await this.countBy({
            query: {
                monitorId: monitorId,
                currentAlertState: {
                    order: QueryHelper.lessThan(resolvedState === null || resolvedState === void 0 ? void 0 : resolvedState.order),
                },
                isCreatedAutomatically: false,
            },
            props: {
                isRoot: true,
            },
        });
        return alertCount.toNumber() > 0;
    }
    async onBeforeDelete(deleteBy) {
        deleteBy.query = applyAlertSelfPrivacyFilter(deleteBy.query, deleteBy.props);
        const alerts = await this.findBy({
            query: deleteBy.query,
            limit: LIMIT_MAX,
            skip: 0,
            select: {
                projectId: true,
                monitor: {
                    _id: true,
                },
            },
            props: {
                isRoot: true,
            },
        });
        return {
            deleteBy,
            carryForward: {
                alerts: alerts,
            },
        };
    }
    async changeAlertState(data) {
        const { projectId, alertId, alertStateId, notifyOwners, rootCause, stateChangeLog, props, } = data;
        // get last monitor status timeline.
        const lastAlertStatusTimeline = await AlertStateTimelineService.findOneBy({
            query: {
                alertId: alertId,
                projectId: projectId,
            },
            select: {
                _id: true,
                alertStateId: true,
            },
            sort: {
                createdAt: SortOrder.Descending,
            },
            props: {
                isRoot: true,
            },
        });
        if (lastAlertStatusTimeline &&
            lastAlertStatusTimeline.alertStateId &&
            lastAlertStatusTimeline.alertStateId.toString() ===
                alertStateId.toString()) {
            return;
        }
        const statusTimeline = new AlertStateTimeline();
        statusTimeline.alertId = alertId;
        statusTimeline.alertStateId = alertStateId;
        statusTimeline.projectId = projectId;
        statusTimeline.isOwnerNotified = !notifyOwners;
        if (stateChangeLog) {
            statusTimeline.stateChangeLog = stateChangeLog;
        }
        if (rootCause) {
            statusTimeline.rootCause = rootCause;
        }
        await AlertStateTimelineService.create({
            data: statusTimeline,
            props: props || {},
        });
    }
    async getMetricRetentionDays() {
        try {
            const globalConfig = await GlobalConfigService.findOneBy({
                query: {
                    _id: ObjectID.getZeroObjectID().toString(),
                },
                props: {
                    isRoot: true,
                },
                select: {
                    monitorMetricRetentionInDays: true,
                },
            });
            if (globalConfig &&
                globalConfig.monitorMetricRetentionInDays !== undefined &&
                globalConfig.monitorMetricRetentionInDays !== null &&
                globalConfig.monitorMetricRetentionInDays > 0) {
                return globalConfig.monitorMetricRetentionInDays;
            }
        }
        catch (error) {
            logger.error("Error fetching metric retention config, using default:");
            logger.error(error);
        }
        return Service.DEFAULT_METRIC_RETENTION_DAYS;
    }
    async refreshAlertMetrics(data) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
        const alert = await this.findOneById({
            id: data.alertId,
            select: {
                projectId: true,
                monitor: {
                    _id: true,
                    name: true,
                },
                alertSeverity: {
                    _id: true,
                    name: true,
                },
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert) {
            throw new BadDataException("Alert not found");
        }
        if (!alert.projectId) {
            throw new BadDataException("Alert Project ID not found");
        }
        // get alert state timeline
        const alertStateTimelines = await AlertStateTimelineService.findBy({
            query: {
                alertId: data.alertId,
            },
            select: {
                projectId: true,
                alertStateId: true,
                alertState: {
                    isAcknowledgedState: true,
                    isResolvedState: true,
                },
                startsAt: true,
                endsAt: true,
            },
            sort: {
                startsAt: SortOrder.Ascending,
            },
            skip: 0,
            limit: LIMIT_PER_PROJECT,
            props: {
                isRoot: true,
            },
        });
        const firstAlertStateTimeline = alertStateTimelines[0];
        // delete all the alert metrics with this alert id because it's a refresh
        await MetricService.deleteBy({
            query: {
                primaryEntityId: data.alertId,
            },
            props: {
                isRoot: true,
            },
        });
        const itemsToSave = [];
        const metricTypesMap = {};
        const metricRetentionDays = await this.getMetricRetentionDays();
        const alertMetricRetentionDate = OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), metricRetentionDays);
        // now we need to create new metrics for this alert - TimeToAcknowledge, TimeToResolve, AlertCount, AlertDuration
        const alertStartsAt = (firstAlertStateTimeline === null || firstAlertStateTimeline === void 0 ? void 0 : firstAlertStateTimeline.startsAt) ||
            alert.createdAt ||
            OneUptimeDate.getCurrentDate();
        const alertCountMetric = new Metric();
        alertCountMetric.projectId = alert.projectId;
        alertCountMetric.primaryEntityId = alert.id;
        alertCountMetric.primaryEntityType = ServiceType.Alert;
        alertCountMetric.name = AlertMetricType.AlertCount;
        alertCountMetric.value = 1;
        alertCountMetric.attributes = {
            alertId: data.alertId.toString(),
            projectId: alert.projectId.toString(),
            monitorId: (_b = (_a = alert.monitor) === null || _a === void 0 ? void 0 : _a._id) === null || _b === void 0 ? void 0 : _b.toString(),
            monitorName: (_d = (_c = alert.monitor) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.toString(),
            alertSeverityId: (_f = (_e = alert.alertSeverity) === null || _e === void 0 ? void 0 : _e._id) === null || _f === void 0 ? void 0 : _f.toString(),
            alertSeverityName: (_h = (_g = alert.alertSeverity) === null || _g === void 0 ? void 0 : _g.name) === null || _h === void 0 ? void 0 : _h.toString(),
        };
        alertCountMetric.attributeKeys = TelemetryUtil.getAttributeKeys(alertCountMetric.attributes);
        alertCountMetric.time = alertStartsAt;
        alertCountMetric.timeUnixNano = OneUptimeDate.toUnixNano(alertCountMetric.time);
        alertCountMetric.metricPointType = MetricPointType.Sum;
        alertCountMetric.retentionDate = alertMetricRetentionDate;
        itemsToSave.push(alertCountMetric);
        const metricType = new MetricType();
        metricType.name = alertCountMetric.name;
        metricType.description = "Number of alerts created";
        metricType.unit = "";
        metricType.services = [];
        metricTypesMap[alertCountMetric.name] = metricType;
        // is the alert acknowledged?
        const isAlertAcknowledged = alertStateTimelines.some((timeline) => {
            var _a;
            return (_a = timeline.alertState) === null || _a === void 0 ? void 0 : _a.isAcknowledgedState;
        });
        if (isAlertAcknowledged) {
            const ackAlertStateTimeline = alertStateTimelines.find((timeline) => {
                var _a;
                return (_a = timeline.alertState) === null || _a === void 0 ? void 0 : _a.isAcknowledgedState;
            });
            if (ackAlertStateTimeline) {
                const timeToAcknowledgeMetric = new Metric();
                timeToAcknowledgeMetric.projectId = alert.projectId;
                timeToAcknowledgeMetric.primaryEntityId = alert.id;
                timeToAcknowledgeMetric.primaryEntityType = ServiceType.Alert;
                timeToAcknowledgeMetric.name = AlertMetricType.TimeToAcknowledge;
                timeToAcknowledgeMetric.value = OneUptimeDate.getDifferenceInSeconds((ackAlertStateTimeline === null || ackAlertStateTimeline === void 0 ? void 0 : ackAlertStateTimeline.startsAt) || OneUptimeDate.getCurrentDate(), alertStartsAt);
                timeToAcknowledgeMetric.attributes = {
                    alertId: data.alertId.toString(),
                    projectId: alert.projectId.toString(),
                    monitorId: (_k = (_j = alert.monitor) === null || _j === void 0 ? void 0 : _j._id) === null || _k === void 0 ? void 0 : _k.toString(),
                    monitorName: (_m = (_l = alert.monitor) === null || _l === void 0 ? void 0 : _l.name) === null || _m === void 0 ? void 0 : _m.toString(),
                    alertSeverityId: (_p = (_o = alert.alertSeverity) === null || _o === void 0 ? void 0 : _o._id) === null || _p === void 0 ? void 0 : _p.toString(),
                    alertSeverityName: (_r = (_q = alert.alertSeverity) === null || _q === void 0 ? void 0 : _q.name) === null || _r === void 0 ? void 0 : _r.toString(),
                };
                timeToAcknowledgeMetric.attributeKeys = TelemetryUtil.getAttributeKeys(timeToAcknowledgeMetric.attributes);
                timeToAcknowledgeMetric.time =
                    (ackAlertStateTimeline === null || ackAlertStateTimeline === void 0 ? void 0 : ackAlertStateTimeline.startsAt) ||
                        alert.createdAt ||
                        OneUptimeDate.getCurrentDate();
                timeToAcknowledgeMetric.timeUnixNano = OneUptimeDate.toUnixNano(timeToAcknowledgeMetric.time);
                timeToAcknowledgeMetric.metricPointType = MetricPointType.Sum;
                timeToAcknowledgeMetric.retentionDate = alertMetricRetentionDate;
                itemsToSave.push(timeToAcknowledgeMetric);
                const metricType = new MetricType();
                metricType.name = timeToAcknowledgeMetric.name;
                metricType.description = "Time taken to acknowledge the alert";
                metricType.unit = "seconds";
                metricTypesMap[timeToAcknowledgeMetric.name] = metricType;
            }
        }
        // time to resolve
        const isAlertResolved = alertStateTimelines.some((timeline) => {
            var _a;
            return (_a = timeline.alertState) === null || _a === void 0 ? void 0 : _a.isResolvedState;
        });
        if (isAlertResolved) {
            const resolvedAlertStateTimeline = alertStateTimelines.find((timeline) => {
                var _a;
                return (_a = timeline.alertState) === null || _a === void 0 ? void 0 : _a.isResolvedState;
            });
            if (resolvedAlertStateTimeline) {
                const timeToResolveMetric = new Metric();
                timeToResolveMetric.projectId = alert.projectId;
                timeToResolveMetric.primaryEntityId = alert.id;
                timeToResolveMetric.primaryEntityType = ServiceType.Alert;
                timeToResolveMetric.name = AlertMetricType.TimeToResolve;
                timeToResolveMetric.value = OneUptimeDate.getDifferenceInSeconds((resolvedAlertStateTimeline === null || resolvedAlertStateTimeline === void 0 ? void 0 : resolvedAlertStateTimeline.startsAt) ||
                    OneUptimeDate.getCurrentDate(), alertStartsAt);
                timeToResolveMetric.attributes = {
                    alertId: data.alertId.toString(),
                    projectId: alert.projectId.toString(),
                    monitorId: (_t = (_s = alert.monitor) === null || _s === void 0 ? void 0 : _s._id) === null || _t === void 0 ? void 0 : _t.toString(),
                    monitorName: (_v = (_u = alert.monitor) === null || _u === void 0 ? void 0 : _u.name) === null || _v === void 0 ? void 0 : _v.toString(),
                    alertSeverityId: (_x = (_w = alert.alertSeverity) === null || _w === void 0 ? void 0 : _w._id) === null || _x === void 0 ? void 0 : _x.toString(),
                    alertSeverityName: (_z = (_y = alert.alertSeverity) === null || _y === void 0 ? void 0 : _y.name) === null || _z === void 0 ? void 0 : _z.toString(),
                };
                timeToResolveMetric.attributeKeys = TelemetryUtil.getAttributeKeys(timeToResolveMetric.attributes);
                timeToResolveMetric.time =
                    (resolvedAlertStateTimeline === null || resolvedAlertStateTimeline === void 0 ? void 0 : resolvedAlertStateTimeline.startsAt) ||
                        alert.createdAt ||
                        OneUptimeDate.getCurrentDate();
                timeToResolveMetric.timeUnixNano = OneUptimeDate.toUnixNano(timeToResolveMetric.time);
                timeToResolveMetric.metricPointType = MetricPointType.Sum;
                timeToResolveMetric.retentionDate = alertMetricRetentionDate;
                itemsToSave.push(timeToResolveMetric);
                const metricType = new MetricType();
                metricType.name = timeToResolveMetric.name;
                metricType.description = "Time taken to resolve the alert";
                metricType.unit = "seconds";
                metricTypesMap[timeToResolveMetric.name] = metricType;
            }
        }
        // alert duration
        const alertDurationMetric = new Metric();
        const lastAlertStateTimeline = alertStateTimelines[alertStateTimelines.length - 1];
        if (lastAlertStateTimeline) {
            const alertEndsAt = lastAlertStateTimeline.startsAt || OneUptimeDate.getCurrentDate();
            alertDurationMetric.projectId = alert.projectId;
            alertDurationMetric.primaryEntityId = alert.id;
            alertDurationMetric.primaryEntityType = ServiceType.Alert;
            alertDurationMetric.name = AlertMetricType.AlertDuration;
            alertDurationMetric.value = OneUptimeDate.getDifferenceInSeconds(alertEndsAt, alertStartsAt);
            alertDurationMetric.attributes = {
                alertId: data.alertId.toString(),
                projectId: alert.projectId.toString(),
                monitorId: (_1 = (_0 = alert.monitor) === null || _0 === void 0 ? void 0 : _0._id) === null || _1 === void 0 ? void 0 : _1.toString(),
                monitorName: (_3 = (_2 = alert.monitor) === null || _2 === void 0 ? void 0 : _2.name) === null || _3 === void 0 ? void 0 : _3.toString(),
                alertSeverityId: (_5 = (_4 = alert.alertSeverity) === null || _4 === void 0 ? void 0 : _4._id) === null || _5 === void 0 ? void 0 : _5.toString(),
                alertSeverityName: (_7 = (_6 = alert.alertSeverity) === null || _6 === void 0 ? void 0 : _6.name) === null || _7 === void 0 ? void 0 : _7.toString(),
            };
            alertDurationMetric.attributeKeys = TelemetryUtil.getAttributeKeys(alertDurationMetric.attributes);
            alertDurationMetric.time =
                (lastAlertStateTimeline === null || lastAlertStateTimeline === void 0 ? void 0 : lastAlertStateTimeline.startsAt) ||
                    alert.createdAt ||
                    OneUptimeDate.getCurrentDate();
            alertDurationMetric.timeUnixNano = OneUptimeDate.toUnixNano(alertDurationMetric.time);
            alertDurationMetric.metricPointType = MetricPointType.Sum;
            alertDurationMetric.retentionDate = alertMetricRetentionDate;
            itemsToSave.push(alertDurationMetric);
            const metricType = new MetricType();
            metricType.name = alertDurationMetric.name;
            metricType.description = "Duration of the alert";
            metricType.unit = "seconds";
            metricTypesMap[alertDurationMetric.name] = metricType;
        }
        await MetricService.createMany({
            items: itemsToSave,
            props: {
                isRoot: true,
            },
        });
        TelemetryUtil.indexMetricNameServiceNameMap({
            metricNameServiceNameMap: metricTypesMap,
            projectId: alert.projectId,
        }).catch((err) => {
            var _a, _b;
            logger.error(err, {
                projectId: (_a = alert.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                alertId: (_b = alert.id) === null || _b === void 0 ? void 0 : _b.toString(),
            });
        });
    }
    async isAlertResolved(data) {
        const alert = await this.findOneBy({
            query: {
                _id: data.alertId,
            },
            select: {
                projectId: true,
                currentAlertState: {
                    order: true,
                },
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert) {
            throw new BadDataException("Alert not found");
        }
        if (!alert.projectId) {
            throw new BadDataException("Alert Project ID not found");
        }
        const resolvedAlertState = await AlertStateService.getResolvedAlertState({
            projectId: alert.projectId,
            props: {
                isRoot: true,
            },
        });
        const currentAlertStateOrder = alert.currentAlertState.order;
        const resolvedAlertStateOrder = resolvedAlertState.order;
        if (currentAlertStateOrder >= resolvedAlertStateOrder) {
            return true;
        }
        return false;
    }
    async getAlertNumber(data) {
        const alert = await this.findOneById({
            id: data.alertId,
            select: {
                alertNumber: true,
                alertNumberWithPrefix: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert) {
            throw new BadDataException("Alert not found.");
        }
        return {
            number: alert.alertNumber ? Number(alert.alertNumber) : null,
            numberWithPrefix: alert.alertNumberWithPrefix || null,
        };
    }
    async resolveAlert(alertId, resolvedByUserId) {
        const alert = await this.findOneById({
            id: alertId,
            select: {
                projectId: true,
                alertNumber: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alert || !alert.projectId) {
            throw new BadDataException("Alert not found.");
        }
        const alertState = await AlertStateService.findOneBy({
            query: {
                projectId: alert.projectId,
                isResolvedState: true,
            },
            select: {
                _id: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!alertState || !alertState.id) {
            throw new BadDataException("Acknowledged state not found for this project. Please add acknowledged state from settings.");
        }
        const alertStateTimeline = new AlertStateTimeline();
        alertStateTimeline.projectId = alert.projectId;
        alertStateTimeline.alertId = alertId;
        alertStateTimeline.alertStateId = alertState.id;
        alertStateTimeline.createdByUserId = resolvedByUserId;
        await AlertStateTimelineService.create({
            data: alertStateTimeline,
            props: {
                isRoot: true,
            },
        });
        // store alert metric
        return alert;
    }
    /**
     * Ensures the currentAlertStateId of the alert matches the latest timeline entry.
     */
    async refreshAlertCurrentStatus(alertId) {
        var _a, _b, _c;
        const alert = await this.findOneById({
            id: alertId,
            select: {
                _id: true,
                projectId: true,
                currentAlertStateId: true,
            },
            props: { isRoot: true },
        });
        if (!alert || !alert.projectId) {
            return;
        }
        const latestTimeline = await AlertStateTimelineService.findOneBy({
            query: {
                alertId: alert.id,
                projectId: alert.projectId,
            },
            sort: {
                startsAt: SortOrder.Descending,
            },
            select: {
                alertStateId: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (latestTimeline &&
            latestTimeline.alertStateId &&
            ((_a = alert.currentAlertStateId) === null || _a === void 0 ? void 0 : _a.toString()) !==
                latestTimeline.alertStateId.toString()) {
            await this.updateOneBy({
                query: { _id: alert.id.toString() },
                data: {
                    currentAlertStateId: latestTimeline.alertStateId,
                },
                props: { isRoot: true },
            });
            logger.info(`Updated Alert ${alert.id} current state to ${latestTimeline.alertStateId}`, {
                projectId: (_b = alert.projectId) === null || _b === void 0 ? void 0 : _b.toString(),
                alertId: (_c = alert.id) === null || _c === void 0 ? void 0 : _c.toString(),
            });
        }
    }
}
Service.DEFAULT_METRIC_RETENTION_DAYS = 180;
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "isAlertAcknowledged", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID,
        ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "acknowledgeAlert", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onBeforeFind", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "countBy", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onBeforeUpdate", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onBeforeCreate", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Model]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onCreateSuccess", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Model]),
    __metadata("design:returntype", Promise)
], Service.prototype, "handleAlertWorkspaceOperationsAsync", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "createAlertFeedAsync", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Model]),
    __metadata("design:returntype", Promise)
], Service.prototype, "handleAlertStateChangeAsync", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Model]),
    __metadata("design:returntype", Promise)
], Service.prototype, "executeAlertOnCallDutyPoliciesAsync", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "getWorkspaceChannelForAlert", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "getAlertIdentifiedDate", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "findOwners", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID,
        ObjectID,
        Array,
        Array, Boolean, Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "addOwners", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID,
        ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "getAlertLinkInDashboard", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Array]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onUpdateSuccess", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID,
        ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "doesMonitorHasMoreActiveManualAlerts", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "onBeforeDelete", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "changeAlertState", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "refreshAlertMetrics", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "isAlertResolved", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], Service.prototype, "getAlertNumber", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID,
        ObjectID]),
    __metadata("design:returntype", Promise)
], Service.prototype, "resolveAlert", null);
export default new Service();
//# sourceMappingURL=AlertService.js.map