"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "getValues", {
    enumerable: true,
    get: function() {
        return getValues;
    }
});
const _config = /*#__PURE__*/ _interop_require_default(require("config"));
const _lodash = require("lodash");
const _fhirTypes = require("@tamanu/shared/services/fhirTypes");
const _fhir = require("@tamanu/shared/utils/fhir");
const _medication = require("@tamanu/shared/utils/medication");
const _constants = require("@tamanu/constants");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
const CATEGORY_CODE_SYSTEM = 'https://hl7.org/fhir/R4B/codesystem-medicationrequest-category.html';
async function getValues(upstream, models) {
    const { PharmacyOrder } = models;
    const pharmacyOrder = await PharmacyOrder.findOne({
        where: {
            id: upstream.pharmacyOrderId
        }
    });
    if (!pharmacyOrder) {
        throw new Error(`Pharmacy order not found for ${upstream.id}`);
    }
    const recorder = await recorderRef(pharmacyOrder, models);
    const requester = await requesterRef(pharmacyOrder, models);
    const subject = await subjectRef(pharmacyOrder, models);
    const encounter = await _fhirTypes.FhirReference.to(models.FhirEncounter, pharmacyOrder.encounterId);
    const prescription = await models.Prescription.findOne({
        where: {
            id: upstream.prescriptionId
        }
    });
    return {
        lastUpdated: new Date(),
        identifier: [
            new _fhirTypes.FhirIdentifier({
                system: _config.default.hl7.dataDictionaries.pharmacyOrderPrescriptionId,
                value: upstream.id
            })
        ],
        status: 'active',
        intent: 'order',
        category: category(pharmacyOrder),
        groupIdentifier: [
            new _fhirTypes.FhirIdentifier({
                system: _config.default.hl7.dataDictionaries.pharmacyOrderId,
                value: pharmacyOrder.id
            })
        ],
        medication: await medication(upstream, models),
        authoredOn: pharmacyOrder.createdAt,
        dosageInstruction: await dosageInstruction(upstream, models),
        dispenseRequest: {
            quantity: upstream.quantity,
            numberOfRepeatsAllowed: upstream.repeats,
            ...prescription?.endDate && {
                validityPeriod: new _fhirTypes.FhirPeriod({
                    start: (0, _fhir.formatFhirDate)(prescription.startDate),
                    end: (0, _fhir.formatFhirDate)(prescription.endDate)
                })
            }
        },
        recorder,
        requester,
        subject,
        encounter,
        note: note(pharmacyOrder, prescription, recorder),
        resolved: requester.isResolved() && recorder.isResolved() && subject.isResolved() && encounter.isResolved()
    };
}
async function requesterRef(pharmacyOrder, models) {
    const encounter = await models.Encounter.findOne({
        where: {
            id: pharmacyOrder.encounterId
        }
    });
    const location = await models.Location.findOne({
        where: {
            id: encounter?.locationId
        }
    });
    const facility = await models.Facility.findOne({
        where: {
            id: location?.facilityId
        }
    });
    return _fhirTypes.FhirReference.to(models.FhirOrganization, facility?.id, {
        display: facility?.name
    });
}
async function subjectRef(pharmacyOrder, models) {
    const encounter = await models.Encounter.findOne({
        where: {
            id: pharmacyOrder.encounterId
        }
    });
    const patient = await models.Patient.findOne({
        where: {
            id: encounter?.patientId
        }
    });
    return _fhirTypes.FhirReference.to(models.FhirPatient, patient?.id, {
        display: `${patient?.firstName} ${patient?.lastName}`
    });
}
async function recorderRef(pharmacyOrder, models) {
    const orderedByUser = await models.User.findOne({
        where: {
            id: pharmacyOrder.orderingClinicianId
        }
    });
    return _fhirTypes.FhirReference.to(models.FhirPractitioner, orderedByUser?.id, {
        display: orderedByUser?.displayName
    });
}
async function medication(pharmacyOrderPrescription, models) {
    const prescription = await models.Prescription.findOne({
        where: {
            id: pharmacyOrderPrescription.prescriptionId
        }
    });
    const medication = await models.ReferenceData.findOne({
        where: {
            id: prescription?.medicationId
        }
    });
    return new _fhirTypes.FhirCodeableConcept({
        coding: [
            new _fhirTypes.FhirCoding({
                system: _config.default.hl7.dataDictionaries.medicationCodeSystem,
                code: medication?.code,
                display: medication?.name
            })
        ]
    });
}
async function dosageInstruction(pharmacyOrderPrescription, models) {
    const prescription = await models.Prescription.findOne({
        where: {
            id: pharmacyOrderPrescription.prescriptionId
        }
    });
    if (!prescription) {
        return null;
    }
    const getTranslation = await models.TranslatedString.getTranslationFunction(_config.default.language);
    const getEnumTranslation = await models.TranslatedString.getEnumTranslationFunction(_config.default.language);
    const doseAmount = (0, _lodash.isNaN)(parseFloat(prescription.doseAmount)) ? null : parseFloat(prescription.doseAmount);
    return new _fhirTypes.FhirDosageInstruction({
        text: `${(0, _medication.getMedicationDoseDisplay)(prescription, getTranslation, getEnumTranslation)} - ${(0, _medication.getTranslatedFrequency)(prescription.frequency, getTranslation)}`,
        timing: new _fhirTypes.FhirTiming({
            repeat: {
                ...getFrequencyPeriodUnit(prescription),
                timeOfDay: prescription.idealTimes ? prescription.idealTimes.map((time)=>time.concat(':00')) // Append seconds as its required by FHIR time type
                 : null
            }
        }),
        doseAndRate: [
            new _fhirTypes.FhirDoseAndRate({
                dose: {
                    doseQuantity: {
                        value: doseAmount,
                        unit: prescription.units
                    }
                }
            })
        ],
        route: new _fhirTypes.FhirCodeableConcept({
            coding: [
                new _fhirTypes.FhirCoding({
                    system: _config.default.hl7.dataDictionaries.medicationRouteCodeSystem,
                    code: prescription.route
                })
            ]
        })
    });
}
function getFrequencyPeriodUnit(prescription) {
    switch(prescription.frequency){
        case _constants.ADMINISTRATION_FREQUENCIES.DAILY:
        case _constants.ADMINISTRATION_FREQUENCIES.DAILY_IN_THE_MORNING:
        case _constants.ADMINISTRATION_FREQUENCIES.DAILY_AT_MIDDAY:
        case _constants.ADMINISTRATION_FREQUENCIES.DAILY_AT_NIGHT:
            return {
                periodUnit: 'd',
                frequency: 1,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.TWO_TIMES_DAILY:
        case _constants.ADMINISTRATION_FREQUENCIES.TWICE_DAILY_AM_AND_MIDDAY:
            return {
                periodUnit: 'd',
                frequency: 2,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.THREE_TIMES_DAILY:
            return {
                periodUnit: 'd',
                frequency: 3,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.FOUR_TIMES_DAILY:
            return {
                periodUnit: 'd',
                frequency: 4,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.EVERY_4_HOURS:
            return {
                periodUnit: 'h',
                frequency: 1,
                period: 4
            };
        case _constants.ADMINISTRATION_FREQUENCIES.EVERY_6_HOURS:
            return {
                periodUnit: 'h',
                frequency: 1,
                period: 6
            };
        case _constants.ADMINISTRATION_FREQUENCIES.EVERY_8_HOURS:
            return {
                periodUnit: 'h',
                frequency: 1,
                period: 8
            };
        case _constants.ADMINISTRATION_FREQUENCIES.EVERY_SECOND_DAY:
            return {
                periodUnit: 'd',
                frequency: 1,
                period: 2
            };
        case _constants.ADMINISTRATION_FREQUENCIES.ONCE_A_WEEK:
            return {
                periodUnit: 'wk',
                frequency: 1,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.ONCE_A_MONTH:
            return {
                periodUnit: 'mo',
                frequency: 1,
                period: 1
            };
        case _constants.ADMINISTRATION_FREQUENCIES.IMMEDIATELY:
        case _constants.ADMINISTRATION_FREQUENCIES.AS_DIRECTED:
            return {};
        default:
            throw new Error(`Unmapped frequency: ${prescription.frequency}`);
    }
}
function category(pharmacyOrder) {
    if (pharmacyOrder.isDischargePrescription) {
        return new _fhirTypes.FhirCodeableConcept({
            coding: [
                new _fhirTypes.FhirCoding({
                    system: CATEGORY_CODE_SYSTEM,
                    code: 'discharge'
                })
            ]
        });
    }
    return null;
}
function note(pharmacyOrder, prescription, recorder) {
    const annotations = [];
    if (pharmacyOrder.comments) {
        annotations.push(new _fhirTypes.FhirAnnotation({
            author: recorder,
            text: pharmacyOrder.comments
        }));
    }
    if (prescription?.notes?.trim()) {
        annotations.push(new _fhirTypes.FhirAnnotation({
            text: prescription.notes.trim()
        }));
    }
    return annotations.length > 0 ? annotations : null;
}

//# sourceMappingURL=getValues.js.map