"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.addIdentifierToPatient = void 0;
const extensions_core_1 = require("@awell-health/extensions-core");
const config_1 = require("./config");
const zod_1 = require("zod");
const lodash_1 = require("lodash");
exports.addIdentifierToPatient = {
    key: 'addIdentifierToPatient',
    category: extensions_core_1.Category.WORKFLOW,
    title: 'Add identifier to patient',
    description: "Add a new identifier to the patient's profile",
    fields: config_1.fields,
    dataPoints: config_1.dataPoints,
    previewable: false,
    supports_automated_retries: true,
    onEvent: async ({ payload, onComplete, onError, helpers }) => {
        var _a, _b, _c, _d, _e, _f, _g, _h;
        // Validate and extract the `system` and `value` fields and `currentPatientId` from the payload
        const { fields: { system, value }, patient: { id: currentPatientId }, } = (0, extensions_core_1.validate)({
            schema: zod_1.z.object({
                fields: config_1.FieldsValidationSchema,
                patient: config_1.PatientValidationSchema,
            }),
            payload,
        });
        const sdk = await helpers.awellSdk();
        /**
         * Check if a patient with the same identifier system and value already exists.
         * This is necessary because identifier system-value pairs must be unique across all patients.
         */
        const { patientByIdentifier: { patient: existingPatient }, } = await sdk.orchestration.query({
            patientByIdentifier: {
                __args: { system, value },
                patient: {
                    id: true,
                },
            },
        });
        const patientExists = !(0, lodash_1.isEmpty)(existingPatient === null || existingPatient === void 0 ? void 0 : existingPatient.id);
        const patientLookUpIsCurrentPatient = (existingPatient === null || existingPatient === void 0 ? void 0 : existingPatient.id) === currentPatientId;
        /**
         * If a different patient already has the provided identifier, we cannot assign this identifier
         * to the current patient, as each identifier system-value pair must be unique.
         */
        if (patientExists && !patientLookUpIsCurrentPatient) {
            await onError({
                events: [
                    {
                        date: new Date().toISOString(),
                        text: {
                            en: `Another patient (${String(existingPatient === null || existingPatient === void 0 ? void 0 : existingPatient.id)}) already has an identifier with system ${system} and value ${value}. Adding this identifier to the current patient is not possible.`,
                        },
                    },
                ],
            });
            return;
        }
        /**
         * Although TypeScript indicates that `payload.patient.profile.identifier` should be accessible within `onEvent`,
         * tests in the Dev environment show that `identifier` data is not reliably available on the extension server.
         * To ensure accurate data, we directly query the API to retrieve the patient's current identifiers.
         */
        const currentPatientData = await sdk.orchestration.query({
            patient: {
                __args: {
                    id: currentPatientId,
                },
                patient: {
                    profile: {
                        identifier: {
                            system: true,
                            value: true,
                        },
                    },
                },
            },
        });
        // Retrieve existing identifiers, excluding any with the specified system.
        const existingIdentifiers = (_d = (_c = (_b = (_a = currentPatientData === null || currentPatientData === void 0 ? void 0 : currentPatientData.patient) === null || _a === void 0 ? void 0 : _a.patient) === null || _b === void 0 ? void 0 : _b.profile) === null || _c === void 0 ? void 0 : _c.identifier) !== null && _d !== void 0 ? _d : [];
        const existingIdentifierExcludingTheOneToUpdate = existingIdentifiers.filter((id) => id.system !== system);
        const previousIdentifier = existingIdentifiers.find((id) => id.system === system);
        const isUpdatingIdentifier = !(0, lodash_1.isEmpty)(previousIdentifier);
        /**
         * If the patient already has this identifier system with the same value, we skip the update to avoid redundancy.
         */
        if (isUpdatingIdentifier && (previousIdentifier === null || previousIdentifier === void 0 ? void 0 : previousIdentifier.value) === value) {
            await onComplete({
                events: [
                    {
                        date: new Date().toISOString(),
                        text: {
                            en: 'Patient already had an identifier of the same value and system. No changes were made.',
                        },
                    },
                ],
            });
            return;
        }
        // Prepare the updated list of identifiers, including the new or updated identifier.
        const newIdentifiers = [
            ...existingIdentifierExcludingTheOneToUpdate,
            { system, value },
        ];
        /**
         * Perform the update to add or update the identifier on the patient's profile.
         * We retrieve the updated identifiers from the API response to ensure we log the final state.
         */
        const result = await sdk.orchestration.mutation({
            updatePatient: {
                __args: {
                    input: {
                        patient_id: currentPatientId,
                        profile: {
                            identifier: newIdentifiers,
                        },
                    },
                },
                patient: {
                    id: true,
                    profile: {
                        identifier: {
                            system: true,
                            value: true,
                        },
                    },
                },
            },
        });
        const updatedIdentifiers = (_h = (_g = (_f = (_e = result === null || result === void 0 ? void 0 : result.updatePatient) === null || _e === void 0 ? void 0 : _e.patient) === null || _f === void 0 ? void 0 : _f.profile) === null || _g === void 0 ? void 0 : _g.identifier) !== null && _h !== void 0 ? _h : [];
        // Log the result, including the old and new lists of identifiers.
        await onComplete({
            events: [
                {
                    date: new Date().toISOString(),
                    text: {
                        en: isUpdatingIdentifier
                            ? `The patient already had an identifier with system ${system} and value ${String(previousIdentifier === null || previousIdentifier === void 0 ? void 0 : previousIdentifier.value)}. The identifier value has been updated to ${value}.`
                            : `The identifier with system ${system} and value ${value} has been added to the patient.`,
                    },
                },
                {
                    date: new Date().toISOString(),
                    text: {
                        en: `Old list of identifiers: ${existingIdentifiers.length === 0
                            ? 'None'
                            : `${existingIdentifiers
                                .map((id) => `${id.system}|${id.value}`)
                                .join(';')}`}`,
                    },
                },
                {
                    date: new Date().toISOString(),
                    text: {
                        en: `Updated list of identifiers: ${updatedIdentifiers
                            .map((id) => `${id.system}|${id.value}`)
                            .join(';')}`,
                    },
                },
            ],
        });
    },
};
//# sourceMappingURL=addIdentifierToPatient.js.map