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 BadDataException from "../../../../../Types/Exception/BadDataException";
import ObjectID from "../../../../../Types/ObjectID";
import IncidentService from "../../../../Services/IncidentService";
import SlackUtil from "../Slack";
import SlackActionType, { PrivateNoteEmojis, PublicNoteEmojis, } from "./ActionTypes";
import Response from "../../../Response";
import IncidentPublicNoteService from "../../../../Services/IncidentPublicNoteService";
import IncidentInternalNoteService from "../../../../Services/IncidentInternalNoteService";
import OnCallDutyPolicy from "../../../../../Models/DatabaseModels/OnCallDutyPolicy";
import OnCallDutyPolicyService from "../../../../Services/OnCallDutyPolicyService";
import { LIMIT_PER_PROJECT } from "../../../../../Types/Database/LimitMax";
import UserNotificationEventType from "../../../../../Types/UserNotification/UserNotificationEventType";
import IncidentStateService from "../../../../Services/IncidentStateService";
import logger from "../../../Logger";
import IncidentSeverityService from "../../../../Services/IncidentSeverityService";
import SortOrder from "../../../../../Types/BaseDatabase/SortOrder";
import Monitor from "../../../../../Models/DatabaseModels/Monitor";
import WorkspaceNotificationLogService from "../../../../Services/WorkspaceNotificationLogService";
import WorkspaceType from "../../../../../Types/Workspace/WorkspaceType";
import MonitorService from "../../../../Services/MonitorService";
import MonitorStatusService from "../../../../Services/MonitorStatusService";
import Label from "../../../../../Models/DatabaseModels/Label";
import LabelService from "../../../../Services/LabelService";
import Incident from "../../../../../Models/DatabaseModels/Incident";
import AccessTokenService from "../../../../Services/AccessTokenService";
import CaptureSpan from "../../../Telemetry/CaptureSpan";
import WorkspaceProjectAuthTokenService from "../../../../Services/WorkspaceProjectAuthTokenService";
import WorkspaceUserAuthTokenService from "../../../../Services/WorkspaceUserAuthTokenService";
export default class SlackIncidentActions {
    static isIncidentAction(data) {
        const { actionType } = data;
        switch (actionType) {
            case SlackActionType.AcknowledgeIncident:
            case SlackActionType.ResolveIncident:
            case SlackActionType.ViewAddIncidentNote:
            case SlackActionType.SubmitIncidentNote:
            case SlackActionType.ViewChangeIncidentState:
            case SlackActionType.SubmitChangeIncidentState:
            case SlackActionType.ViewExecuteIncidentOnCallPolicy:
            case SlackActionType.SubmitExecuteIncidentOnCallPolicy:
            case SlackActionType.ViewIncident:
            case SlackActionType.NewIncident:
            case SlackActionType.SubmitNewIncident:
                return true;
            default:
                return false;
        }
    }
    static async submitNewIncident(data) {
        var _a;
        const { slackRequest, req, res } = data;
        const { botUserId, userId, projectAuthToken } = slackRequest;
        if (!projectAuthToken) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Project Auth Token"));
        }
        if (!botUserId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Bot User ID"));
        }
        if (data.action.actionType === SlackActionType.SubmitNewIncident) {
            // We send this early let slack know we're ok. We'll do the rest in the background.
            // if view values is empty, then return error.
            if (!data.slackRequest.viewValues) {
                return Response.sendErrorResponse(req, res, new BadDataException("Invalid View Values"));
            }
            if (!data.slackRequest.viewValues["incidentTitle"]) {
                return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident Title"));
            }
            if (!data.slackRequest.viewValues["incidentDescription"]) {
                return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident Description"));
            }
            if (!data.slackRequest.viewValues["incidentSeverity"]) {
                return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident Severity"));
            }
            Response.sendJsonObjectResponse(req, res, {
                response_action: "clear",
            });
            const title = data.slackRequest.viewValues["incidentTitle"].toString();
            const description = data.slackRequest.viewValues["incidentDescription"].toString();
            const severity = data.slackRequest.viewValues["incidentSeverity"].toString();
            const monitors = (data.slackRequest.viewValues["incidentMonitors"] || []);
            const monitorStatus = (_a = data.slackRequest.viewValues["monitorStatus"]) === null || _a === void 0 ? void 0 : _a.toString();
            const labels = data.slackRequest.viewValues["labels"] || [];
            const onCallDutyPolicies = data.slackRequest.viewValues["onCallDutyPolicies"] ||
                [];
            const incidentMonitors = monitors.map((monitor) => {
                return new ObjectID(monitor);
            });
            const incidentLabels = labels.map((label) => {
                return new ObjectID(label);
            });
            const incidentOnCallPolicies = onCallDutyPolicies.map((policy) => {
                return new ObjectID(policy);
            });
            const incidentSeverityId = new ObjectID(severity);
            const monitorStatusId = monitorStatus
                ? new ObjectID(monitorStatus)
                : undefined;
            const incident = new Incident();
            incident.title = title;
            incident.description = description;
            incident.projectId = slackRequest.projectId;
            if (userId) {
                incident.createdByUserId = userId;
            }
            incident.incidentSeverityId = incidentSeverityId;
            const rootCauseInMarkdown = `Incident created by @${slackRequest.slackUsername} on Slack.`;
            incident.rootCause = rootCauseInMarkdown;
            if (incidentOnCallPolicies.length > 0) {
                incident.onCallDutyPolicies = incidentOnCallPolicies.map((policyId) => {
                    const policy = new OnCallDutyPolicy();
                    policy.id = policyId;
                    return policy;
                });
            }
            if (monitors.length > 0) {
                incident.monitors = incidentMonitors.map((monitorId) => {
                    const monitor = new Monitor();
                    monitor.id = monitorId;
                    return monitor;
                });
            }
            if (monitorStatusId) {
                incident.changeMonitorStatusToId = monitorStatusId;
            }
            if (incidentLabels.length > 0) {
                incident.labels = incidentLabels.map((labelId) => {
                    const label = new Label();
                    label.id = labelId;
                    return label;
                });
            }
            const createdIncident = await IncidentService.create({
                data: incident,
                props: {
                    isRoot: true,
                },
            });
            // post a message to Slack after the incident was created.
            const slackChannelId = data.action.actionValue || ""; // this is the channel id where the incident was created.
            if (slackChannelId) {
                await SlackUtil.sendMessage({
                    authToken: projectAuthToken,
                    userId: botUserId,
                    projectId: slackRequest.projectId,
                    workspaceMessagePayload: {
                        _type: "WorkspaceMessagePayload",
                        channelIds: [slackChannelId],
                        channelNames: [],
                        workspaceType: WorkspaceType.Slack,
                        messageBlocks: [
                            {
                                _type: "WorkspacePayloadMarkdown",
                                text: `**Incident ${createdIncident.incidentNumberWithPrefix || "#" + createdIncident.incidentNumber}** created successfully. [View Incident](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId, createdIncident.id)})`,
                            },
                        ],
                    },
                });
            }
        }
    }
    static async viewNewIncidentModal(data) {
        const blocks = [];
        // send response to clear the action.
        Response.sendTextResponse(data.req, data.res, "");
        /*
         * show new incident modal.
         * new incident modal is :
         * Incident Title (this can be prefilled with actionValue)
         * Incident Description
         * Incident Severity (dropdown) (single select)
         * Monitors (dropdown) (miltiselect)
         * Change Monitor Status to (dropdown) (single select)
         * Labels (dropdown) (multiselect)
         */
        const incidentTitle = {
            _type: "WorkspaceTextBoxBlock",
            label: "Incident Title",
            blockId: "incidentTitle",
            placeholder: "Incident Title",
            initialValue: data.action.actionValue || "",
        };
        blocks.push(incidentTitle);
        const incidentDescription = {
            _type: "WorkspaceTextAreaBlock",
            label: "Incident Description",
            blockId: "incidentDescription",
            placeholder: "Incident Description",
        };
        blocks.push(incidentDescription);
        const incidentSeveritiesForProject = await IncidentSeverityService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            sort: {
                order: SortOrder.Ascending,
            },
            skip: 0,
            limit: LIMIT_PER_PROJECT,
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
        });
        const dropdownOptions = incidentSeveritiesForProject.map((severity) => {
            var _a;
            return {
                label: severity.name || "",
                value: ((_a = severity._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        });
        const incidentSeverity = {
            _type: "WorkspaceDropdownBlock",
            label: "Incident Severity",
            blockId: "incidentSeverity",
            placeholder: "Select Incident Severity",
            options: dropdownOptions,
        };
        if (incidentSeveritiesForProject.length > 0) {
            blocks.push(incidentSeverity);
        }
        const monitorsForProject = await MonitorService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const monitorDropdownOptions = monitorsForProject.map((monitor) => {
            var _a;
            return {
                label: monitor.name || "",
                value: ((_a = monitor._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        });
        const incidentMonitors = {
            _type: "WorkspaceDropdownBlock",
            label: "Monitors",
            blockId: "incidentMonitors",
            placeholder: "Select Monitors",
            options: monitorDropdownOptions,
            multiSelect: true,
            optional: true,
        };
        if (monitorsForProject.length > 0) {
            blocks.push(incidentMonitors);
        }
        const monitorStatusForProject = await MonitorStatusService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
            sort: {
                priority: SortOrder.Ascending,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const monitorStatusDropdownOptions = monitorStatusForProject.map((status) => {
            var _a;
            return {
                label: status.name || "",
                value: ((_a = status._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        });
        const monitorStatusDropdown = {
            _type: "WorkspaceDropdownBlock",
            label: "Change Monitor Status to",
            blockId: "monitorStatus",
            placeholder: "Select Monitor Status",
            options: monitorStatusDropdownOptions,
            optional: true,
        };
        if (monitorStatusForProject.length > 0 &&
            monitorDropdownOptions.length > 0) {
            blocks.push(monitorStatusDropdown);
        }
        // add on-call policy dropdown.
        const onCallPolicies = await OnCallDutyPolicyService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const onCallPolicyDropdownOptions = onCallPolicies.map((policy) => {
            var _a;
            return {
                label: policy.name || "",
                value: ((_a = policy._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        });
        if (onCallPolicies.length > 0) {
            const onCallPolicyDropdown = {
                _type: "WorkspaceDropdownBlock",
                label: "Execute On Call Policy",
                blockId: "onCallDutyPolicies",
                placeholder: "Select on call policies to execute when this incident is created",
                options: onCallPolicyDropdownOptions,
                multiSelect: true,
                optional: true,
            };
            blocks.push(onCallPolicyDropdown);
        }
        const labelsForProject = await LabelService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const labelsDropdownOptions = labelsForProject.map((label) => {
            var _a;
            return {
                label: label.name || "",
                value: ((_a = label._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        });
        const labelsDropdown = {
            _type: "WorkspaceDropdownBlock",
            label: "Labels",
            blockId: "labels",
            placeholder: "Select Labels",
            options: labelsDropdownOptions,
            multiSelect: true,
            optional: true,
        };
        if (labelsForProject.length > 0) {
            blocks.push(labelsDropdown);
        }
        const modalBlock = {
            _type: "WorkspaceModalBlock",
            title: "New Incident",
            submitButtonTitle: "Submit",
            cancelButtonTitle: "Cancel",
            actionId: SlackActionType.SubmitNewIncident,
            actionValue: data.slackRequest.slackChannelId || "",
            blocks: blocks,
        };
        await SlackUtil.showModalToUser({
            authToken: data.slackRequest.projectAuthToken,
            modalBlock: modalBlock,
            triggerId: data.slackRequest.triggerId,
        });
    }
    static async acknowledgeIncident(data) {
        var _a;
        const { slackRequest, req, res } = data;
        const { botUserId, userId, projectAuthToken, slackUsername } = slackRequest;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        if (!userId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid User ID"));
        }
        if (!projectAuthToken) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Project Auth Token"));
        }
        if (!botUserId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Bot User ID"));
        }
        if (data.action.actionType === SlackActionType.AcknowledgeIncident) {
            const incidentId = new ObjectID(actionValue);
            // We send this early let slack know we're ok. We'll do the rest in the background.
            Response.sendJsonObjectResponse(req, res, {
                response_action: "clear",
            });
            const isAlreadyAcknowledged = await IncidentService.isIncidentAcknowledged({
                incidentId: incidentId,
            });
            if (isAlreadyAcknowledged) {
                const incidentNumberResult = await IncidentService.getIncidentNumber({
                    incidentId: incidentId,
                });
                const incidentNumberDisplay = incidentNumberResult.numberWithPrefix ||
                    "#" + incidentNumberResult.number;
                // send a message to the channel visible to user, that the incident has already been acknowledged.
                const markdwonPayload = {
                    _type: "WorkspacePayloadMarkdown",
                    text: `@${slackUsername}, unfortunately you cannot acknowledge the **[Incident ${incidentNumberDisplay}](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId, incidentId)})**. It has already been acknowledged.`,
                };
                await SlackUtil.sendDirectMessageToUser({
                    messageBlocks: [markdwonPayload],
                    authToken: projectAuthToken,
                    workspaceUserId: slackRequest.slackUserId,
                });
                return;
            }
            await IncidentService.acknowledgeIncident(incidentId, userId);
            // Log the button interaction
            if (slackRequest.projectId) {
                try {
                    const logData = {
                        projectId: slackRequest.projectId,
                        workspaceType: WorkspaceType.Slack,
                        userId: userId,
                        buttonAction: "acknowledge_incident",
                    };
                    if (slackRequest.slackChannelId) {
                        logData.channelId = slackRequest.slackChannelId;
                    }
                    logData.incidentId = incidentId;
                    await WorkspaceNotificationLogService.logButtonPressed(logData, {
                        isRoot: true,
                    });
                }
                catch (err) {
                    logger.error("Error logging button interaction:", {
                        projectId: (_a = slackRequest.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                        incidentId: incidentId.toString(),
                    });
                    logger.error(err);
                    // Don't throw the error, just log it so the main flow continues
                }
            }
            // Incident Feed will send a message to the channel that the incident has been Acknowledged.
            return;
        }
        // invalid action type.
        return Response.sendErrorResponse(req, res, new BadDataException("Invalid Action Type"));
    }
    static async resolveIncident(data) {
        const { slackRequest, req, res } = data;
        const { botUserId, userId, projectAuthToken, slackUsername } = slackRequest;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        if (!userId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid User ID"));
        }
        if (!projectAuthToken) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Project Auth Token"));
        }
        if (!botUserId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Bot User ID"));
        }
        if (data.action.actionType === SlackActionType.ResolveIncident) {
            const incidentId = new ObjectID(actionValue);
            // We send this early let slack know we're ok. We'll do the rest in the background.
            Response.sendJsonObjectResponse(req, res, {
                response_action: "clear",
            });
            const isAlreadyResolved = await IncidentService.isIncidentResolved({
                incidentId: incidentId,
            });
            if (isAlreadyResolved) {
                const incidentNumberResult = await IncidentService.getIncidentNumber({
                    incidentId: incidentId,
                });
                const incidentNumberDisplay = incidentNumberResult.numberWithPrefix ||
                    "#" + incidentNumberResult.number;
                // send a message to the channel visible to user, that the incident has already been Resolved.
                const markdwonPayload = {
                    _type: "WorkspacePayloadMarkdown",
                    text: `@${slackUsername}, unfortunately you cannot resolve the **[Incident ${incidentNumberDisplay}](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId, incidentId)})**. It has already been resolved.`,
                };
                await SlackUtil.sendDirectMessageToUser({
                    messageBlocks: [markdwonPayload],
                    authToken: projectAuthToken,
                    workspaceUserId: slackRequest.slackUserId,
                });
                return;
            }
            await IncidentService.resolveIncident(incidentId, userId);
            return;
        }
        // invalid action type.
        return Response.sendErrorResponse(req, res, new BadDataException("Invalid Action Type"));
    }
    static async viewExecuteOnCallPolicy(data) {
        const { req, res } = data;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        // We send this early let slack know we're ok. We'll do the rest in the background.
        Response.sendJsonObjectResponse(req, res, {
            response_action: "clear",
        });
        // const incidentId: ObjectID = new ObjectID(actionValue);
        // send a modal with a dropdown that says "Public Note" or "Private Note" and a text area to add the note.
        const onCallPolicies = await OnCallDutyPolicyService.findBy({
            query: {
                projectId: data.slackRequest.projectId,
            },
            select: {
                name: true,
            },
            props: {
                isRoot: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const dropdownOption = onCallPolicies
            .map((policy) => {
            var _a;
            return {
                label: policy.name || "",
                value: ((_a = policy._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        })
            .filter((option) => {
            return option.label !== "" || option.value !== "";
        });
        if (dropdownOption.length === 0) {
            if (data.slackRequest.slackChannelId) {
                await SlackUtil.sendEphemeralMessageToChannel({
                    messageBlocks: [
                        {
                            _type: "WorkspacePayloadMarkdown",
                            text: "No on-call policies have been configured for this project yet. Please add an on-call policy in the OneUptime Dashboard under On-Call Duty > Policies to use this feature.",
                        },
                    ],
                    authToken: data.slackRequest.projectAuthToken,
                    channelId: data.slackRequest.slackChannelId,
                    userId: data.slackRequest.slackUserId,
                });
            }
            return;
        }
        const onCallPolicyDropdown = {
            _type: "WorkspaceDropdownBlock",
            label: "On Call Policy",
            blockId: "onCallPolicy",
            placeholder: "Select On Call Policy",
            options: dropdownOption,
        };
        const modalBlock = {
            _type: "WorkspaceModalBlock",
            title: "Execute On Call Policy",
            submitButtonTitle: "Submit",
            cancelButtonTitle: "Cancel",
            actionId: SlackActionType.SubmitExecuteIncidentOnCallPolicy,
            actionValue: actionValue,
            blocks: [onCallPolicyDropdown],
        };
        await SlackUtil.showModalToUser({
            authToken: data.slackRequest.projectAuthToken,
            modalBlock: modalBlock,
            triggerId: data.slackRequest.triggerId,
        });
    }
    static async viewChangeIncidentState(data) {
        var _a;
        const { req, res } = data;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        // We send this early let slack know we're ok. We'll do the rest in the background.
        Response.sendJsonObjectResponse(req, res, {
            response_action: "clear",
        });
        // const incidentId: ObjectID = new ObjectID(actionValue);
        // send a modal with a dropdown that says "Public Note" or "Private Note" and a text area to add the note.
        const incidentStates = await IncidentStateService.getAllIncidentStates({
            projectId: data.slackRequest.projectId,
            props: {
                isRoot: true,
            },
        });
        logger.debug("Incident States: ", {
            projectId: (_a = data.slackRequest.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
        });
        logger.debug(incidentStates);
        const dropdownOptions = incidentStates
            .map((state) => {
            var _a;
            return {
                label: state.name || "",
                value: ((_a = state._id) === null || _a === void 0 ? void 0 : _a.toString()) || "",
            };
        })
            .filter((option) => {
            return option.label !== "" || option.value !== "";
        });
        logger.debug("Dropdown Options: ");
        logger.debug(dropdownOptions);
        const statePickerDropdown = {
            _type: "WorkspaceDropdownBlock",
            label: "Incident State",
            blockId: "incidentState",
            placeholder: "Select Incident State",
            options: dropdownOptions,
        };
        const modalBlock = {
            _type: "WorkspaceModalBlock",
            title: "Change Incident State",
            submitButtonTitle: "Submit",
            cancelButtonTitle: "Cancel",
            actionId: SlackActionType.SubmitChangeIncidentState,
            actionValue: actionValue,
            blocks: [statePickerDropdown],
        };
        await SlackUtil.showModalToUser({
            authToken: data.slackRequest.projectAuthToken,
            modalBlock: modalBlock,
            triggerId: data.slackRequest.triggerId,
        });
    }
    static async submitChangeIncidentState(data) {
        var _a;
        const { req, res } = data;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        // We send this early let slack know we're ok. We'll do the rest in the background.
        Response.sendJsonObjectResponse(req, res, {
            response_action: "clear",
        });
        // const incidentId: ObjectID = new ObjectID(actionValue);
        // send a modal with a dropdown that says "Public Note" or "Private Note" and a text area to add the note.
        if (!data.slackRequest.viewValues ||
            !data.slackRequest.viewValues["incidentState"]) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid View Values"));
        }
        const incidentId = new ObjectID(actionValue);
        const stateString = data.slackRequest.viewValues["incidentState"].toString();
        const stateId = new ObjectID(stateString);
        await IncidentService.updateOneById({
            id: incidentId,
            data: {
                currentIncidentStateId: stateId,
            },
            props: await AccessTokenService.getDatabaseCommonInteractionPropsByUserAndProject({
                userId: data.slackRequest.userId,
                projectId: data.slackRequest.projectId,
            }),
        });
        // Log the button interaction
        if (data.slackRequest.projectId && data.slackRequest.userId) {
            try {
                const logData = {
                    projectId: data.slackRequest.projectId,
                    workspaceType: WorkspaceType.Slack,
                    userId: data.slackRequest.userId,
                    buttonAction: "change_incident_state",
                    incidentId: incidentId,
                };
                if (data.slackRequest.slackChannelId) {
                    logData.channelId = data.slackRequest.slackChannelId;
                }
                await WorkspaceNotificationLogService.logButtonPressed(logData, {
                    isRoot: true,
                });
            }
            catch (err) {
                logger.error("Error logging button interaction:", {
                    projectId: (_a = data.slackRequest.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
                    incidentId: incidentId.toString(),
                });
                logger.error(err);
                // Don't throw the error, just log it so the main flow continues
            }
        }
    }
    static async executeOnCallPolicy(data) {
        const { slackRequest, req, res } = data;
        const { botUserId, userId, projectAuthToken, slackUsername } = slackRequest;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        if (!userId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid User ID"));
        }
        if (!projectAuthToken) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Project Auth Token"));
        }
        if (!botUserId) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Bot User ID"));
        }
        if (data.action.actionType ===
            SlackActionType.SubmitExecuteIncidentOnCallPolicy) {
            const incidentId = new ObjectID(actionValue);
            // We send this early let slack know we're ok. We'll do the rest in the background.
            Response.sendJsonObjectResponse(req, res, {
                response_action: "clear",
            });
            const isAlreadyResolved = await IncidentService.isIncidentResolved({
                incidentId: incidentId,
            });
            if (isAlreadyResolved) {
                const incidentNumberResult = await IncidentService.getIncidentNumber({
                    incidentId: incidentId,
                });
                const incidentNumberDisplay = incidentNumberResult.numberWithPrefix ||
                    "#" + incidentNumberResult.number;
                // send a message to the channel visible to user, that the incident has already been Resolved.
                const markdwonPayload = {
                    _type: "WorkspacePayloadMarkdown",
                    text: `@${slackUsername}, unfortunately you cannot execute the on-call policy for **[Incident ${incidentNumberDisplay}](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId, incidentId)})**. It has already been resolved.`,
                };
                await SlackUtil.sendDirectMessageToUser({
                    messageBlocks: [markdwonPayload],
                    authToken: projectAuthToken,
                    workspaceUserId: slackRequest.slackUserId,
                });
                return;
            }
            if (!data.slackRequest.viewValues ||
                !data.slackRequest.viewValues["onCallPolicy"]) {
                return Response.sendErrorResponse(req, res, new BadDataException("Invalid View Values"));
            }
            const onCallPolicyString = data.slackRequest.viewValues["onCallPolicy"].toString();
            // get the on-call policy id.
            const onCallPolicyId = new ObjectID(onCallPolicyString);
            await OnCallDutyPolicyService.executePolicy(onCallPolicyId, {
                triggeredByIncidentId: incidentId,
                userNotificationEventType: UserNotificationEventType.IncidentCreated,
            });
        }
    }
    static async submitIncidentNote(data) {
        const { req, res } = data;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        // const incidentId: ObjectID = new ObjectID(actionValue);
        // send a modal with a dropdown that says "Public Note" or "Private Note" and a text area to add the note.
        // if view values is empty, then return error.
        if (!data.slackRequest.viewValues) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid View Values"));
        }
        if (!data.slackRequest.viewValues["noteType"]) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Note Type"));
        }
        if (!data.slackRequest.viewValues["note"]) {
            // return error.
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Note"));
        }
        const incidentId = new ObjectID(actionValue);
        const note = data.slackRequest.viewValues["note"].toString();
        const noteType = data.slackRequest.viewValues["noteType"].toString();
        if (noteType !== "public" && noteType !== "private") {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Note Type"));
        }
        // send empty response.
        Response.sendJsonObjectResponse(req, res, {
            response_action: "clear",
        });
        // if public note then, add a note.
        if (noteType === "public") {
            await IncidentPublicNoteService.addNote({
                incidentId: incidentId,
                note: note || "",
                projectId: data.slackRequest.projectId,
                userId: data.slackRequest.userId,
            });
        }
        // if private note then, add a note.
        if (noteType === "private") {
            await IncidentInternalNoteService.addNote({
                incidentId: incidentId,
                note: note || "",
                projectId: data.slackRequest.projectId,
                userId: data.slackRequest.userId,
            });
        }
    }
    static async viewAddIncidentNote(data) {
        const { req, res } = data;
        const { actionValue } = data.action;
        if (!actionValue) {
            return Response.sendErrorResponse(req, res, new BadDataException("Invalid Incident ID"));
        }
        // We send this early let slack know we're ok. We'll do the rest in the background.
        Response.sendJsonObjectResponse(req, res, {
            response_action: "clear",
        });
        // const incidentId: ObjectID = new ObjectID(actionValue);
        // send a modal with a dropdown that says "Public Note" or "Private Note" and a text area to add the note.
        const notePickerDropdown = {
            _type: "WorkspaceDropdownBlock",
            label: "Note Type",
            blockId: "noteType",
            placeholder: "Select Note Type",
            options: [
                {
                    label: "Public Note (Will be posted on Status Page)",
                    value: "public",
                },
                {
                    label: "Private Note (Only visible to team members)",
                    value: "private",
                },
            ],
        };
        const noteTextArea = {
            _type: "WorkspaceTextAreaBlock",
            label: "Note",
            blockId: "note",
            placeholder: "Note",
            description: "Please type in plain text or markdown.",
        };
        const modalBlock = {
            _type: "WorkspaceModalBlock",
            title: "Add Note",
            submitButtonTitle: "Submit",
            cancelButtonTitle: "Cancel",
            actionId: SlackActionType.SubmitIncidentNote,
            actionValue: actionValue,
            blocks: [notePickerDropdown, noteTextArea],
        };
        await SlackUtil.showModalToUser({
            authToken: data.slackRequest.projectAuthToken,
            modalBlock: modalBlock,
            triggerId: data.slackRequest.triggerId,
        });
    }
    static async handleIncidentAction(data) {
        // now we should be all set, project is authorized and user is authorized. Lets perform some actions based on the action type.
        const actionType = data.action.actionType;
        if (actionType === SlackActionType.AcknowledgeIncident) {
            return await this.acknowledgeIncident(data);
        }
        if (actionType === SlackActionType.ResolveIncident) {
            return await this.resolveIncident(data);
        }
        if (actionType === SlackActionType.ViewAddIncidentNote) {
            return await this.viewAddIncidentNote(data);
        }
        if (actionType === SlackActionType.SubmitIncidentNote) {
            return await this.submitIncidentNote(data);
        }
        if (actionType === SlackActionType.ViewExecuteIncidentOnCallPolicy) {
            return await this.viewExecuteOnCallPolicy(data);
        }
        if (actionType === SlackActionType.SubmitExecuteIncidentOnCallPolicy) {
            return await this.executeOnCallPolicy(data);
        }
        if (actionType === SlackActionType.ViewChangeIncidentState) {
            return await this.viewChangeIncidentState(data);
        }
        if (actionType === SlackActionType.SubmitChangeIncidentState) {
            return await this.submitChangeIncidentState(data);
        }
        if (actionType === SlackActionType.NewIncident) {
            return await this.viewNewIncidentModal(data);
        }
        if (actionType === SlackActionType.SubmitNewIncident) {
            return await this.submitNewIncident(data);
        }
        if (actionType === SlackActionType.ViewIncident) {
            /*
             * do nothing. This is just a view incident action.
             * clear response.
             */
            return Response.sendJsonObjectResponse(data.req, data.res, {
                response_action: "clear",
            });
        }
        // invalid action type.
        return Response.sendErrorResponse(data.req, data.res, new BadDataException("Invalid Action Type"));
    }
    static async handleEmojiReaction(data) {
        logger.debug("Handling emoji reaction with data:", {
            channelId: data.channelId,
        });
        logger.debug(data);
        const { teamId, reaction, userId, channelId, messageTs } = data;
        // Check if the emoji is a supported private or public note emoji
        const isPrivateNoteEmoji = PrivateNoteEmojis.includes(reaction);
        const isPublicNoteEmoji = PublicNoteEmojis.includes(reaction);
        if (!isPrivateNoteEmoji && !isPublicNoteEmoji) {
            logger.debug(`Emoji "${reaction}" is not a supported note emoji. Ignoring.`);
            return;
        }
        // Get the project auth token using the team ID
        const projectAuth = await WorkspaceProjectAuthTokenService.findOneBy({
            query: {
                workspaceProjectId: teamId,
            },
            select: {
                projectId: true,
                authToken: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!projectAuth || !projectAuth.projectId || !projectAuth.authToken) {
            logger.debug("No project auth found for team ID. Ignoring emoji reaction.");
            return;
        }
        const projectId = projectAuth.projectId;
        const authToken = projectAuth.authToken;
        // Find the incident linked to this channel
        const workspaceLog = await WorkspaceNotificationLogService.findOneBy({
            query: {
                channelId: channelId,
                workspaceType: WorkspaceType.Slack,
                projectId: projectId,
            },
            select: {
                incidentId: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!workspaceLog || !workspaceLog.incidentId) {
            logger.debug("No incident found linked to this channel. Ignoring emoji reaction.");
            return;
        }
        const incidentId = workspaceLog.incidentId;
        // Get the incident number for the confirmation message
        const incidentNumberResult = await IncidentService.getIncidentNumber({
            incidentId: incidentId,
        });
        const incidentNumberDisplay = incidentNumberResult.numberWithPrefix ||
            "#" + incidentNumberResult.number;
        // Get the user ID in OneUptime based on Slack user ID
        const userAuth = await WorkspaceUserAuthTokenService.findOneBy({
            query: {
                workspaceUserId: userId,
                workspaceType: WorkspaceType.Slack,
                projectId: projectId,
            },
            select: {
                userId: true,
            },
            props: {
                isRoot: true,
            },
        });
        if (!userAuth || !userAuth.userId) {
            logger.debug("No OneUptime user found for Slack user. Ignoring emoji reaction.");
            return;
        }
        const oneUptimeUserId = userAuth.userId;
        // Fetch the message text using the timestamp
        let messageText = null;
        try {
            messageText = await SlackUtil.getMessageByTimestamp({
                authToken: authToken,
                channelId: channelId,
                messageTs: messageTs,
            });
        }
        catch (err) {
            logger.error("Error fetching message text:", {
                projectId: projectId.toString(),
                incidentId: incidentId.toString(),
                channelId: channelId,
            });
            logger.error(err);
            return;
        }
        if (!messageText) {
            logger.debug("No message text found. Ignoring emoji reaction.", {
                projectId: projectId.toString(),
                incidentId: incidentId.toString(),
                channelId: channelId,
            });
            return;
        }
        // Create a unique identifier for this Slack message to prevent duplicate notes
        const postedFromSlackMessageId = `${channelId}:${messageTs}`;
        // Save the note based on the emoji type
        let noteType;
        try {
            if (isPrivateNoteEmoji) {
                noteType = "private";
                // Check if a note from this Slack message already exists
                const hasExistingNote = await IncidentInternalNoteService.hasNoteFromSlackMessage({
                    incidentId: incidentId,
                    postedFromSlackMessageId: postedFromSlackMessageId,
                });
                if (hasExistingNote) {
                    logger.debug("Private note from this Slack message already exists. Skipping duplicate.", {
                        projectId: projectId.toString(),
                        incidentId: incidentId.toString(),
                    });
                    return;
                }
                await IncidentInternalNoteService.addNote({
                    incidentId: incidentId,
                    note: messageText,
                    projectId: projectId,
                    userId: oneUptimeUserId,
                    postedFromSlackMessageId: postedFromSlackMessageId,
                });
                logger.debug("Private note added successfully.", {
                    projectId: projectId.toString(),
                    incidentId: incidentId.toString(),
                });
            }
            else if (isPublicNoteEmoji) {
                noteType = "public";
                // Check if a note from this Slack message already exists
                const hasExistingNote = await IncidentPublicNoteService.hasNoteFromSlackMessage({
                    incidentId: incidentId,
                    postedFromSlackMessageId: postedFromSlackMessageId,
                });
                if (hasExistingNote) {
                    logger.debug("Public note from this Slack message already exists. Skipping duplicate.", {
                        projectId: projectId.toString(),
                        incidentId: incidentId.toString(),
                    });
                    return;
                }
                await IncidentPublicNoteService.addNote({
                    incidentId: incidentId,
                    note: messageText,
                    projectId: projectId,
                    userId: oneUptimeUserId,
                    postedFromSlackMessageId: postedFromSlackMessageId,
                });
                logger.debug("Public note added successfully.", {
                    projectId: projectId.toString(),
                    incidentId: incidentId.toString(),
                });
            }
            else {
                return;
            }
        }
        catch (err) {
            logger.error("Error saving note:", {
                projectId: projectId.toString(),
                incidentId: incidentId.toString(),
            });
            logger.error(err);
            return;
        }
        // Send confirmation message as a reply to the original message thread
        try {
            const incidentLink = (await IncidentService.getIncidentLinkInDashboard(projectId, incidentId)).toString();
            const confirmationMessage = noteType === "private"
                ? `✅ Message saved as *private note* to <${incidentLink}|Incident ${incidentNumberDisplay}>.`
                : `✅ Message saved as *public note* to <${incidentLink}|Incident ${incidentNumberDisplay}>. This note will be visible on the status page.`;
            await SlackUtil.sendMessageToThread({
                authToken: authToken,
                channelId: channelId,
                threadTs: messageTs,
                text: confirmationMessage,
            });
            logger.debug("Confirmation message sent successfully.", {
                projectId: projectId.toString(),
                incidentId: incidentId.toString(),
            });
        }
        catch (err) {
            logger.error("Error sending confirmation message:", {
                projectId: projectId.toString(),
                incidentId: incidentId.toString(),
            });
            logger.error(err);
            // Don't throw - note was saved successfully, confirmation is best effort
        }
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Boolean)
], SlackIncidentActions, "isIncidentAction", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "submitNewIncident", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "viewNewIncidentModal", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "acknowledgeIncident", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "resolveIncident", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "viewExecuteOnCallPolicy", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "viewChangeIncidentState", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "submitChangeIncidentState", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "executeOnCallPolicy", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "submitIncidentNote", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "viewAddIncidentNote", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "handleIncidentAction", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], SlackIncidentActions, "handleEmojiReaction", null);
//# sourceMappingURL=Incident.js.map