"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "Triage", {
    enumerable: true,
    get: function() {
        return Triage;
    }
});
const _sequelize = require("sequelize");
const _config = /*#__PURE__*/ _interop_require_default(require("config"));
const _constants = require("@tamanu/constants");
const _errors = require("@tamanu/errors");
const _dateFormatters = require("@tamanu/utils/dateFormatters");
const _dateTime = require("@tamanu/utils/dateTime");
const _timeZoneCheck = require("@tamanu/shared/utils/timeZoneCheck");
const _Model = require("./Model");
const _buildEncounterLinkedSyncFilter = require("../sync/buildEncounterLinkedSyncFilter");
const _buildEncounterLinkedLookupFilter = require("../sync/buildEncounterLinkedLookupFilter");
const _recordModelChanges = require("../utils/recordModelChanges");
const _model = require("../types/model");
function _interop_require_default(obj) {
    return obj && obj.__esModule ? obj : {
        default: obj
    };
}
let Triage = class Triage extends _Model.Model {
    static initModel({ primaryKey, ...options }) {
        super.init({
            id: primaryKey,
            arrivalTime: (0, _model.dateTimeType)('arrivalTime'),
            triageTime: (0, _model.dateTimeType)('triageTime'),
            closedTime: (0, _model.dateTimeType)('closedTime'),
            score: _sequelize.DataTypes.TEXT
        }, {
            ...options,
            syncDirection: _constants.SYNC_DIRECTIONS.BIDIRECTIONAL
        });
    }
    static initRelations(models) {
        this.belongsTo(models.Encounter, {
            foreignKey: 'encounterId',
            as: 'encounter'
        });
        this.belongsTo(models.User, {
            as: 'Practitioner',
            foreignKey: 'practitionerId'
        });
        this.belongsTo(models.ReferenceData, {
            foreignKey: 'chiefComplaintId',
            as: 'chiefComplaint'
        });
        this.belongsTo(models.ReferenceData, {
            foreignKey: 'secondaryComplaintId',
            as: 'secondaryComplaint'
        });
        this.belongsTo(models.ReferenceData, {
            foreignKey: 'arrivalModeId',
            as: 'arrivalMode'
        });
        this.hasMany(models.Note, {
            foreignKey: 'recordId',
            as: 'notes',
            constraints: false,
            scope: {
                recordType: this.name
            }
        });
    }
    static getListReferenceAssociations() {
        return [
            'chiefComplaint',
            'secondaryComplaint'
        ];
    }
    static buildPatientSyncFilter(patientCount, markedForSyncPatientsTable) {
        if (patientCount === 0) {
            return null;
        }
        return (0, _buildEncounterLinkedSyncFilter.buildEncounterLinkedSyncFilter)([
            this.tableName,
            'encounters'
        ], markedForSyncPatientsTable);
    }
    static async buildSyncLookupQueryDetails() {
        return (0, _buildEncounterLinkedLookupFilter.buildEncounterLinkedLookupFilter)(this);
    }
    static async create(data) {
        const { Encounter, ReferenceData } = this.sequelize.models;
        const existingEncounter = await Encounter.findOne({
            where: {
                endDate: {
                    [_sequelize.Op.is]: null
                },
                patientId: data.patientId
            }
        });
        if (existingEncounter) {
            throw new _errors.InvalidOperationError("Can't triage a patient that has an existing encounter");
        }
        const reasons = await Promise.all([
            data.chiefComplaintId,
            data.secondaryComplaintId
        ].map((x)=>ReferenceData.findByPk(x)));
        // TODO: to handle translations for triage reason for encounter
        const reasonsText = reasons.filter((x)=>x).map((x)=>x?.name).join(' and ');
        const reasonForEncounter = `Presented at emergency department with ${reasonsText}`;
        return this.sequelize.transaction(async ()=>{
            const encounter = await Encounter.create({
                encounterType: _constants.ENCOUNTER_TYPES.TRIAGE,
                startDate: data.triageTime,
                reasonForEncounter,
                patientId: data.patientId,
                departmentId: data.departmentId,
                locationId: data.locationId,
                examinerId: data.practitionerId,
                actorId: data.actorId
            });
            return super.create({
                ...data,
                encounterId: encounter.id
            });
        });
    }
    async update(data, user) {
        const { Encounter, ReferenceData } = this.sequelize.models;
        // To collect system note messages describing all changes in this triage update
        const systemNoteRows = [];
        const { onChangeForeignKey, onChangeTextColumn } = (0, _recordModelChanges.createChangeRecorders)(this, data, systemNoteRows);
        const updateTriage = async ()=>{
            await onChangeForeignKey({
                columnName: 'chiefComplaintId',
                noteLabel: 'chief complaint',
                model: ReferenceData
            });
            await onChangeForeignKey({
                columnName: 'secondaryComplaintId',
                noteLabel: 'secondary complaint',
                model: ReferenceData
            });
            await onChangeForeignKey({
                columnName: 'arrivalModeId',
                noteLabel: 'arrival mode',
                model: ReferenceData
            });
            await onChangeTextColumn({
                columnName: 'arrivalTime',
                noteLabel: 'arrival date & time',
                formatText: (date)=>date ? (0, _dateFormatters.formatShortDateTime)(date, (0, _timeZoneCheck.getPrimaryTimeZone)(_config.default)) : '-'
            });
            await onChangeTextColumn({
                columnName: 'triageTime',
                noteLabel: 'triage date & time',
                formatText: (date)=>date ? (0, _dateFormatters.formatShortDateTime)(date, (0, _timeZoneCheck.getPrimaryTimeZone)(_config.default)) : '-'
            });
            await onChangeTextColumn({
                columnName: 'score',
                noteLabel: 'triage score'
            });
            const { submittedTime, ...triageData } = data;
            const updatedTriage = await super.update(triageData, user);
            if (systemNoteRows.length > 0) {
                const encounter = await Encounter.findByPk(this.encounterId);
                if (encounter) {
                    const formattedSystemNote = systemNoteRows.map((row)=>`• ${row}`).join('\n');
                    await encounter.addSystemNote(formattedSystemNote, submittedTime || (0, _dateTime.getCurrentDateTimeString)(), user);
                }
            }
            return updatedTriage;
        };
        if (this.sequelize.isInsideTransaction()) {
            return updateTriage();
        }
        // If the update is not already in a transaction, wrap it in one
        // Having nested transactions can cause bugs in postgres so only conditionally wrap
        return this.sequelize.transaction(async ()=>{
            return await updateTriage();
        });
    }
};

//# sourceMappingURL=Triage.js.map