"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSMSBroadcast = void 0;
const zod_1 = require("zod");
const extensions_core_1 = require("@awell-health/extensions-core");
const config_1 = require("./config");
const settings_1 = require("../../settings");
const lib_1 = require("../../lib");
const lodash_1 = require("lodash");
/**
 * Known Text-Em-All error codes and their meanings.
 */
const ERROR_CODES = {
    NO_VALID_CONTACTS: 3005, // "NoValidBroadcastContacts" - invalid/opted-out number
};
/**
 * Determines the delivery result based on an error response.
 */
function getResultFromError(errorCode, errorName, message) {
    if (errorCode === ERROR_CODES.NO_VALID_CONTACTS ||
        errorName === 'NoValidBroadcastContacts') {
        return {
            result: config_1.DeliveryResultType.INVALID_NUMBER,
            details: message !== null && message !== void 0 ? message : 'Phone number is invalid or recipient cannot receive text messages',
        };
    }
    return {
        result: config_1.DeliveryResultType.FAILED,
        details: message !== null && message !== void 0 ? message : 'Broadcast creation failed',
    };
}
exports.createSMSBroadcast = {
    key: 'createSMSBroadcast',
    title: 'Send a new SMS broadcast',
    description: 'Send a text message to a recipient. Returns the delivery result (sent, invalid_number, failed, etc.) for triage purposes.',
    category: extensions_core_1.Category.COMMUNICATION,
    fields: config_1.fields,
    dataPoints: config_1.dataPoints,
    previewable: true,
    onEvent: async ({ payload, onComplete, onError, helpers: { log }, }) => {
        var _a, _b;
        // Step 1: Extract raw field values and settings
        const { fields: rawFields, settings } = (0, extensions_core_1.validate)({
            schema: zod_1.z.object({ fields: config_1.FieldsSchema, settings: settings_1.SettingsSchema }),
            payload,
        });
        const patientProfile = (_a = payload.patient) === null || _a === void 0 ? void 0 : _a.profile;
        // Step 2: Resolve values — fields take priority, patient profile is fallback
        let phoneNumber = rawFields.phoneNumber;
        if ((0, lodash_1.isEmpty)(phoneNumber)) {
            phoneNumber = (_b = patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.mobile_phone) !== null && _b !== void 0 ? _b : patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.phone;
            if ((0, lodash_1.isEmpty)(phoneNumber)) {
                await onError({
                    events: [
                        {
                            date: new Date().toISOString(),
                            text: {
                                en: 'No phone number provided and no mobile phone found on patient profile.',
                            },
                            error: {
                                category: 'WRONG_INPUT',
                                message: 'No phone number provided and no mobile phone found on patient profile',
                            },
                        },
                    ],
                });
                return;
            }
            log({ source: 'patient_profile', field: 'mobile_phone' }, 'Phone number not provided — using patient profile mobile phone');
        }
        let firstName = rawFields.firstName;
        if ((0, lodash_1.isEmpty)(firstName) && !(0, lodash_1.isEmpty)(patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.first_name)) {
            firstName = patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.first_name;
            log({ source: 'patient_profile', field: 'first_name' }, 'First name not provided — using patient profile first name');
        }
        let lastName = rawFields.lastName;
        if ((0, lodash_1.isEmpty)(lastName) && !(0, lodash_1.isEmpty)(patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.last_name)) {
            lastName = patientProfile === null || patientProfile === void 0 ? void 0 : patientProfile.last_name;
            log({ source: 'patient_profile', field: 'last_name' }, 'Last name not provided — using patient profile last name');
        }
        // Step 3: Validate the resolved input (NANP phone format, date transform, etc.)
        const input = config_1.BroadcastInputSchema.parse({
            broadcastName: rawFields.broadcastName,
            phoneNumber,
            firstName,
            lastName,
            notes: rawFields.notes,
            integrationData: rawFields.integrationData,
            textMessage: rawFields.textMessage,
            textNumberID: rawFields.textNumberID,
            startDate: rawFields.startDate,
            checkCallingWindow: rawFields.checkCallingWindow,
        });
        // Step 4: Build the API request
        const contact = {
            PrimaryPhone: input.phoneNumber,
        };
        if (!(0, lodash_1.isEmpty)(input.firstName)) {
            contact.FirstName = input.firstName;
        }
        if (!(0, lodash_1.isEmpty)(input.lastName)) {
            contact.LastName = input.lastName;
        }
        if (!(0, lodash_1.isEmpty)(input.notes)) {
            contact.Notes = input.notes;
        }
        if (!(0, lodash_1.isEmpty)(input.integrationData)) {
            contact.IntegrationData = input.integrationData;
        }
        const request = {
            BroadcastName: input.broadcastName,
            BroadcastType: 'SMS',
            TextMessage: input.textMessage,
            TextNumberID: input.textNumberID,
            StartDate: input.startDate,
            CheckCallingWindow: input.checkCallingWindow,
            Contacts: [contact],
        };
        // Step 5: Send to Text-Em-All
        const client = new lib_1.TextEmAllClient(settings);
        const resp = await client.createBroadcast(request);
        const data = resp.data;
        // Success - broadcast created
        if (resp.status === 200 && 'BroadcastID' in data) {
            await onComplete({
                events: [
                    {
                        date: new Date().toISOString(),
                        text: { en: 'SMS broadcast created successfully' },
                    },
                ],
                data_points: {
                    success: 'true',
                    broadcastId: data.BroadcastID.toString(),
                    broadcastStatus: data.BroadcastStatus,
                    uriBroadcastDetails: data.UriBroadcastDetails,
                    broadcastStatusCategory: data.BroadcastStatusCategory,
                    broadcastStartDate: data.StartDate,
                    deliveryResult: config_1.DeliveryResultType.SENT,
                    deliveryResultDetails: 'Message sent to carrier for delivery',
                },
            });
            return;
        }
        // Rate limiting (429) — transient, retry may help
        if (resp.status === 429) {
            await onError({
                events: [
                    {
                        date: new Date().toISOString(),
                        text: { en: 'Rate limit exceeded. Please try again later.' },
                        error: {
                            category: 'SERVER_ERROR',
                            message: 'Rate limit exceeded (429)',
                        },
                    },
                ],
            });
            return;
        }
        // API errors (400, etc.) — valid triage data, not a retry candidate
        if ('ErrorCode' in data || 'ErrorName' in data || 'Message' in data) {
            const errorData = data;
            const { result, details } = getResultFromError(errorData.ErrorCode, errorData.ErrorName, errorData.Message);
            await onComplete({
                events: [
                    {
                        date: new Date().toISOString(),
                        text: { en: `SMS broadcast result: ${result} - ${details}` },
                    },
                ],
                data_points: {
                    success: 'false',
                    broadcastId: '',
                    broadcastStatus: '',
                    uriBroadcastDetails: '',
                    broadcastStatusCategory: '',
                    broadcastStartDate: '',
                    deliveryResult: result,
                    deliveryResultDetails: details,
                },
            });
            return;
        }
        // Unknown error
        await onError({
            events: [
                {
                    date: new Date().toISOString(),
                    text: { en: 'Broadcast creation failed with unknown error' },
                    error: {
                        category: 'SERVER_ERROR',
                        message: 'Broadcast creation failed',
                    },
                },
            ],
        });
    },
};
//# sourceMappingURL=createSMSBroadcast.js.map