import BadDataException from "../../Types/Exception/BadDataException";
import DatabaseService from "./DatabaseService";
import Model from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
import UserNotificationSettingService from "./UserNotificationSettingService";
import NotificationSettingEventType from "../../Types/NotificationSetting/NotificationSettingEventType";
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
import OnCallDutyPolicyFeedService from "./OnCallDutyPolicyFeedService";
import { OnCallDutyPolicyFeedEventType } from "../../Models/DatabaseModels/OnCallDutyPolicyFeed";
import { Gray500, Red500 } from "../../Types/BrandColors";
import UserService from "./UserService";
import PushNotificationUtil from "../Utils/PushNotificationUtil";
import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
import OneUptimeDate from "../../Types/Date";
import { createWhatsAppMessageFromTemplate } from "../Utils/WhatsAppTemplateUtil";
import logger from "../Utils/Logger";
export class Service extends DatabaseService {
    constructor() {
        super(Model);
    }
    async onCreateSuccess(_onCreate, createdItem) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
        const createdItemId = createdItem.id;
        if (!createdItemId) {
            throw new BadDataException("Created item does not have an ID");
        }
        const createdModel = await this.findOneById({
            id: createdItemId,
            select: {
                projectId: true,
                user: {
                    timezone: true,
                    _id: true,
                },
                onCallDutyPolicyEscalationRule: {
                    name: true,
                    _id: true,
                    order: true,
                },
                onCallDutyPolicy: {
                    name: true,
                    _id: true,
                },
                createdByUserId: true,
            },
            props: {
                isRoot: true,
            },
        });
        // send notification to the new current user.
        const sendEmailToUserId = (_a = createdModel === null || createdModel === void 0 ? void 0 : createdModel.user) === null || _a === void 0 ? void 0 : _a.id;
        if (!sendEmailToUserId) {
            return createdItem;
        }
        if (!createdModel) {
            return createdItem;
        }
        const vars = {
            onCallPolicyName: ((_b = createdModel.onCallDutyPolicy) === null || _b === void 0 ? void 0 : _b.name) || "No name provided",
            escalationRuleName: ((_c = createdModel.onCallDutyPolicyEscalationRule) === null || _c === void 0 ? void 0 : _c.name) || "No name provided",
            escalationRuleOrder: ((_e = (_d = createdModel.onCallDutyPolicyEscalationRule) === null || _d === void 0 ? void 0 : _d.order) === null || _e === void 0 ? void 0 : _e.toString()) ||
                "No order provided",
            reason: "You have been added to the on-call duty policy escalation rule.",
            onCallPolicyViewLink: (await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(createdModel.projectId, createdModel.onCallDutyPolicy.id)).toString(),
        };
        // current user changed, send alert the new current user.
        const emailMessage = {
            templateType: EmailTemplateType.UserAddedToOnCallPolicy,
            vars: vars,
            subject: `You have been added to the on-call duty policy ${(_f = createdModel.onCallDutyPolicy) === null || _f === void 0 ? void 0 : _f.name}`,
        };
        const sms = {
            message: `This is a message from OneUptime. You have been added to the on-call duty policy ${(_g = createdModel.onCallDutyPolicy) === null || _g === void 0 ? void 0 : _g.name} for escalation rule ${(_h = createdModel.onCallDutyPolicyEscalationRule) === null || _h === void 0 ? void 0 : _h.name} with order ${(_j = createdModel.onCallDutyPolicyEscalationRule) === null || _j === void 0 ? void 0 : _j.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
        };
        const callMessage = {
            data: [
                {
                    sayMessage: `This is a message from OneUptime. You have been added to the on-call duty policy ${(_k = createdModel.onCallDutyPolicy) === null || _k === void 0 ? void 0 : _k.name} for escalation rule ${(_l = createdModel.onCallDutyPolicyEscalationRule) === null || _l === void 0 ? void 0 : _l.name} with order ${(_m = createdModel.onCallDutyPolicyEscalationRule) === null || _m === void 0 ? void 0 : _m.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
                },
            ],
        };
        const pushMessage = PushNotificationUtil.createOnCallPolicyAddedNotification({
            policyName: ((_o = createdModel.onCallDutyPolicy) === null || _o === void 0 ? void 0 : _o.name) || "",
        });
        const eventType = NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY;
        const whatsAppMessage = createWhatsAppMessageFromTemplate({
            eventType,
            templateVariables: {
                on_call_policy_name: ((_p = createdModel.onCallDutyPolicy) === null || _p === void 0 ? void 0 : _p.name) || "No name provided",
                on_call_context: `escalation rule ${((_q = createdModel.onCallDutyPolicyEscalationRule) === null || _q === void 0 ? void 0 : _q.name) || "No name provided"}`,
                policy_link: vars["onCallPolicyViewLink"] || "",
            },
        });
        await UserNotificationSettingService.sendUserNotification({
            userId: sendEmailToUserId,
            projectId: createdModel.projectId,
            emailEnvelope: emailMessage,
            smsMessage: sms,
            callRequestMessage: callMessage,
            pushNotificationMessage: pushMessage,
            whatsAppMessage,
            eventType,
            onCallPolicyId: createdModel.onCallDutyPolicy.id,
            onCallPolicyEscalationRuleId: createdModel.onCallDutyPolicyEscalationRule.id,
        });
        // add workspace message.
        const onCallDutyPolicyId = createdModel.onCallDutyPolicy.id;
        const projectId = createdModel.projectId;
        if (onCallDutyPolicyId) {
            await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
                onCallDutyPolicyId: onCallDutyPolicyId,
                projectId: projectId,
                onCallDutyPolicyFeedEventType: OnCallDutyPolicyFeedEventType.UserAdded,
                displayColor: Gray500,
                feedInfoInMarkdown: `👨🏻‍💻 Added **${await UserService.getUserMarkdownString({
                    userId: createdModel.user.id,
                    projectId: projectId,
                })}** to the [On-Call Policy ${(_r = createdModel.onCallDutyPolicy) === null || _r === void 0 ? void 0 : _r.name}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId, onCallDutyPolicyId)).toString()}) escalation rule **${(_s = createdModel.onCallDutyPolicyEscalationRule) === null || _s === void 0 ? void 0 : _s.name}** with order **${(_t = createdModel.onCallDutyPolicyEscalationRule) === null || _t === void 0 ? void 0 : _t.order}**.`,
                userId: createdModel.createdByUserId || undefined,
                workspaceNotification: {
                    sendWorkspaceNotification: true,
                    notifyUserId: createdModel.createdByUserId || undefined,
                },
            });
            // also add on-call duty time log.
            OnCallDutyPolicyTimeLogService.startTimeLogForUser({
                projectId: projectId,
                onCallDutyPolicyId: onCallDutyPolicyId,
                onCallDutyPolicyEscalationRuleId: createdModel.onCallDutyPolicyEscalationRule.id,
                userId: createdModel.user.id,
                startsAt: OneUptimeDate.getCurrentDate(),
            }).catch((error) => {
                var _a, _b, _c;
                logger.error(`Error starting time log for user ${(_a = createdModel.user) === null || _a === void 0 ? void 0 : _a.id}: ${error}`, {
                    projectId: projectId === null || projectId === void 0 ? void 0 : projectId.toString(),
                    userId: (_c = (_b = createdModel.user) === null || _b === void 0 ? void 0 : _b.id) === null || _c === void 0 ? void 0 : _c.toString(),
                });
            });
        }
        return createdItem;
    }
    async onBeforeDelete(deleteBy) {
        var _a, _b, _c, _d, _e;
        const itemsToFetchBeforeDelete = await this.findBy({
            query: deleteBy.query,
            props: {
                isRoot: true,
            },
            select: {
                projectId: true,
                user: {
                    timezone: true,
                    _id: true,
                },
                onCallDutyPolicyEscalationRule: {
                    name: true,
                    _id: true,
                    order: true,
                },
                onCallDutyPolicy: {
                    name: true,
                    _id: true,
                },
                createdByUserId: true,
            },
            limit: LIMIT_PER_PROJECT,
            skip: 0,
        });
        const deleteByUserId = ((_a = deleteBy.deletedByUser) === null || _a === void 0 ? void 0 : _a.id) || deleteBy.props.userId;
        for (const item of itemsToFetchBeforeDelete) {
            const onCallDutyPolicyId = item.onCallDutyPolicy.id;
            const projectId = item.projectId;
            const userId = item.user.id;
            if (onCallDutyPolicyId && userId && projectId) {
                const user = await UserService.findOneById({
                    id: userId,
                    select: {
                        name: true,
                        email: true,
                    },
                    props: {
                        isRoot: true,
                    },
                });
                const onCallDutyPolicyName = ((_b = item.onCallDutyPolicy) === null || _b === void 0 ? void 0 : _b.name) || "No name provided";
                if (user && user.name) {
                    await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
                        onCallDutyPolicyId: onCallDutyPolicyId,
                        projectId: projectId,
                        onCallDutyPolicyFeedEventType: OnCallDutyPolicyFeedEventType.OwnerUserRemoved,
                        displayColor: Red500,
                        feedInfoInMarkdown: `👨🏻‍💻 Removed **${user.name.toString()}** (${(_c = user.email) === null || _c === void 0 ? void 0 : _c.toString()}) from the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId, onCallDutyPolicyId)).toString()}) for escalation rule ${(_d = item.onCallDutyPolicyEscalationRule) === null || _d === void 0 ? void 0 : _d.name} with order ${(_e = item.onCallDutyPolicyEscalationRule) === null || _e === void 0 ? void 0 : _e.order}.`,
                        userId: deleteByUserId || undefined,
                        workspaceNotification: {
                            sendWorkspaceNotification: true,
                            notifyUserId: userId || undefined,
                        },
                    });
                    // also remove on-call duty time log.
                    OnCallDutyPolicyTimeLogService.endTimeLogForUser({
                        projectId: projectId,
                        onCallDutyPolicyId: onCallDutyPolicyId,
                        onCallDutyPolicyEscalationRuleId: item.onCallDutyPolicyEscalationRule.id,
                        userId: userId,
                        endsAt: OneUptimeDate.getCurrentDate(),
                    }).catch((error) => {
                        logger.error(`Error ending time log for user ${userId}: ${error}`, {
                            projectId: projectId === null || projectId === void 0 ? void 0 : projectId.toString(),
                            userId: userId === null || userId === void 0 ? void 0 : userId.toString(),
                        });
                    });
                }
            }
        }
        return {
            deleteBy,
            carryForward: {
                deletedItems: itemsToFetchBeforeDelete,
            },
        };
    }
    async onDeleteSuccess(onDelete, _itemIdsBeforeDelete) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
        const deletedItems = onDelete.carryForward.deletedItems;
        for (const deletedItem of deletedItems) {
            const sendEmailToUserId = (_a = deletedItem.user) === null || _a === void 0 ? void 0 : _a.id;
            if (!sendEmailToUserId) {
                return onDelete;
            }
            const vars = {
                onCallPolicyName: ((_b = deletedItem.onCallDutyPolicy) === null || _b === void 0 ? void 0 : _b.name) || "No name provided",
                escalationRuleName: ((_c = deletedItem.onCallDutyPolicyEscalationRule) === null || _c === void 0 ? void 0 : _c.name) ||
                    "No name provided",
                escalationRuleOrder: ((_e = (_d = deletedItem.onCallDutyPolicyEscalationRule) === null || _d === void 0 ? void 0 : _d.order) === null || _e === void 0 ? void 0 : _e.toString()) ||
                    "No order provided",
                reason: "You have been removed from the on-call duty policy escalation rule.",
                onCallPolicyViewLink: (await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(deletedItem.projectId, deletedItem.onCallDutyPolicy.id)).toString(),
            };
            // current user changed, send alert the new current user.
            const emailMessage = {
                templateType: EmailTemplateType.UserRemovedFromOnCallPolicy,
                vars: vars,
                subject: `You have been removed from the on-call duty policy ${(_f = deletedItem.onCallDutyPolicy) === null || _f === void 0 ? void 0 : _f.name}`,
            };
            const sms = {
                message: `This is a message from OneUptime. You have been removed from the on-call duty policy ${(_g = deletedItem.onCallDutyPolicy) === null || _g === void 0 ? void 0 : _g.name} for escalation rule ${(_h = deletedItem.onCallDutyPolicyEscalationRule) === null || _h === void 0 ? void 0 : _h.name} with order ${(_j = deletedItem.onCallDutyPolicyEscalationRule) === null || _j === void 0 ? void 0 : _j.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
            };
            const callMessage = {
                data: [
                    {
                        sayMessage: `This is a message from OneUptime. You have been removed from the on-call duty policy ${(_k = deletedItem.onCallDutyPolicy) === null || _k === void 0 ? void 0 : _k.name} for escalation rule ${(_l = deletedItem.onCallDutyPolicyEscalationRule) === null || _l === void 0 ? void 0 : _l.name} with order ${(_m = deletedItem.onCallDutyPolicyEscalationRule) === null || _m === void 0 ? void 0 : _m.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
                    },
                ],
            };
            const pushMessage = PushNotificationUtil.createOnCallPolicyRemovedNotification({
                policyName: ((_o = deletedItem.onCallDutyPolicy) === null || _o === void 0 ? void 0 : _o.name) || "",
            });
            const eventType = NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY;
            const whatsAppMessage = createWhatsAppMessageFromTemplate({
                eventType,
                templateVariables: {
                    on_call_policy_name: ((_p = deletedItem.onCallDutyPolicy) === null || _p === void 0 ? void 0 : _p.name) || "No name provided",
                    on_call_context: `escalation rule ${((_q = deletedItem.onCallDutyPolicyEscalationRule) === null || _q === void 0 ? void 0 : _q.name) || "No name provided"}`,
                    policy_link: vars["onCallPolicyViewLink"] || "",
                },
            });
            UserNotificationSettingService.sendUserNotification({
                userId: sendEmailToUserId,
                projectId: deletedItem.projectId,
                emailEnvelope: emailMessage,
                smsMessage: sms,
                callRequestMessage: callMessage,
                pushNotificationMessage: pushMessage,
                whatsAppMessage,
                eventType,
                onCallPolicyId: deletedItem.onCallDutyPolicy.id,
                onCallPolicyEscalationRuleId: deletedItem.onCallDutyPolicyEscalationRule.id,
            });
        }
        return onDelete;
    }
}
export default new Service();
//# sourceMappingURL=OnCallDutyPolicyEscalationRuleUserService.js.map