"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "ImagingRequest", {
    enumerable: true,
    get: function() {
        return ImagingRequest;
    }
});
const _sequelize = require("sequelize");
const _constants = require("@tamanu/constants");
const _notes = require("@tamanu/shared/utils/notes");
const _errors = require("@tamanu/errors");
const _dateTime = require("@tamanu/utils/dateTime");
const _Model = require("../Model");
const _buildEncounterLinkedSyncFilter = require("../../sync/buildEncounterLinkedSyncFilter");
const _buildEncounterLinkedLookupFilter = require("../../sync/buildEncounterLinkedLookupFilter");
const _model = require("../../types/model");
const _hooks = require("./hooks");
const ALL_IMAGING_REQUEST_STATUS_TYPES = Object.values(_constants.IMAGING_REQUEST_STATUS_TYPES);
let ImagingRequest = class ImagingRequest extends _Model.Model {
    static initModel(options) {
        super.init({
            id: {
                type: _sequelize.DataTypes.STRING,
                allowNull: false,
                defaultValue: _sequelize.Sequelize.fn('gen_random_uuid'),
                primaryKey: true
            },
            displayId: {
                type: _sequelize.DataTypes.STRING,
                defaultValue: _sequelize.Sequelize.fn('gen_random_uuid'),
                allowNull: false
            },
            imagingType: {
                type: _sequelize.DataTypes.ENUM(..._constants.IMAGING_TYPES_VALUES),
                allowNull: false
            },
            reasonForCancellation: {
                type: _sequelize.DataTypes.STRING
            },
            status: {
                type: _sequelize.DataTypes.ENUM(...ALL_IMAGING_REQUEST_STATUS_TYPES),
                allowNull: false,
                defaultValue: _constants.IMAGING_REQUEST_STATUS_TYPES.PENDING
            },
            requestedDate: (0, _model.dateTimeType)('requestedDate', {
                allowNull: false,
                defaultValue: _dateTime.getCurrentDateTimeString
            }),
            // moved into ImagingResults.description
            legacyResults: {
                type: _sequelize.DataTypes.TEXT,
                defaultValue: ''
            },
            priority: {
                type: _sequelize.DataTypes.STRING
            }
        }, {
            ...options,
            syncDirection: _constants.SYNC_DIRECTIONS.BIDIRECTIONAL,
            validate: {
                mustHaveValidRequestStatusType () {
                    if (!ALL_IMAGING_REQUEST_STATUS_TYPES.includes(this.status)) {
                        throw new _errors.InvalidOperationError('An imaging request must have a valid status.');
                    }
                },
                mustHaveValidRequester () {
                    if (!this.requestedById) {
                        throw new _errors.InvalidOperationError('An imaging request must have a valid requester.');
                    }
                }
            },
            hooks: {
                afterCreate: _hooks.afterCreateHook,
                afterUpdate: _hooks.afterUpdateHook
            }
        });
    }
    async getNotes(options = {}) {
        const { models } = this.sequelize;
        return models.Note.findAll({
            where: {
                recordId: this.id,
                recordType: _constants.NOTE_RECORD_TYPES.IMAGING_REQUEST,
                ...options.where
            },
            include: [
                {
                    model: models.ReferenceData,
                    as: 'noteTypeReference'
                },
                ...options.include || []
            ]
        });
    }
    async extractNotes() {
        const notes = this.notes || await this.getNotes({
            where: {
                visibilityStatus: _constants.VISIBILITY_STATUSES.CURRENT
            }
        });
        const extractWithType = async (type)=>{
            const note = (0, _notes.getNoteWithType)(notes, type);
            return note?.content || '';
        };
        return {
            note: await extractWithType(_constants.NOTE_TYPES.OTHER),
            areaNote: await extractWithType(_constants.NOTE_TYPES.AREA_TO_BE_IMAGED),
            notes
        };
    }
    static getListReferenceAssociations() {
        return [
            'requestedBy',
            'areas',
            'results'
        ];
    }
    static initRelations(models) {
        this.belongsTo(models.Encounter, {
            foreignKey: 'encounterId',
            as: 'encounter'
        });
        this.belongsTo(models.User, {
            foreignKey: 'requestedById',
            as: 'requestedBy'
        });
        this.belongsTo(models.User, {
            foreignKey: 'completedById',
            as: 'completedBy'
        });
        this.belongsTo(models.LocationGroup, {
            as: 'locationGroup',
            foreignKey: 'locationGroupId'
        });
        // Imaging Requests are assigned a Location Group but the Location relation exists for legacy data
        this.belongsTo(models.Location, {
            foreignKey: 'locationId',
            as: 'location'
        });
        this.belongsToMany(models.ReferenceData, {
            through: models.ImagingRequestArea,
            as: 'areas',
            foreignKey: 'imagingRequestId'
        });
        // Used to be able to explicitly include these (hence no alias)
        this.hasMany(models.ImagingRequestArea, {
            foreignKey: 'imagingRequestId'
        });
        this.hasOne(models.ImagingTypeExternalCode, {
            sourceKey: 'imagingType',
            foreignKey: 'imagingTypeCode',
            as: 'imagingTypeExternalCode'
        });
        this.hasMany(models.Note, {
            foreignKey: 'recordId',
            as: 'notes',
            constraints: false,
            scope: {
                recordType: this.name
            }
        });
        this.hasMany(models.ImagingResult, {
            foreignKey: 'imagingRequestId',
            as: 'results'
        });
        this.hasOne(models.InvoiceItem, {
            foreignKey: 'sourceRecordId',
            as: 'invoiceItem',
            constraints: false,
            scope: {
                source_record_type: this.name
            }
        });
    }
    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);
    }
};

//# sourceMappingURL=ImagingRequest.js.map