function _class_static_private_method_get(receiver, classConstructor, method) {
    _class_check_private_static_access(receiver, classConstructor);
    return method;
}
function _class_check_private_static_access(receiver, classConstructor) {
    if (receiver !== classConstructor) {
        throw new TypeError("Private static access of wrong provenance");
    }
}
import { DataTypes, ValidationError } from 'sequelize';
import { REFERENCE_TYPE_VALUES, SYNC_DIRECTIONS, VISIBILITY_STATUSES } from '@tamanu/constants';
import { InvalidOperationError } from '@tamanu/errors';
import { Model } from './Model';
export class ReferenceData extends Model {
    static initModel({ primaryKey, ...options }) {
        super.init({
            id: primaryKey,
            code: {
                type: DataTypes.STRING,
                allowNull: false
            },
            type: {
                type: DataTypes.STRING(31),
                allowNull: false
            },
            name: {
                type: DataTypes.TEXT,
                allowNull: false
            },
            visibilityStatus: {
                type: DataTypes.TEXT,
                defaultValue: VISIBILITY_STATUSES.CURRENT
            },
            systemRequired: {
                type: DataTypes.BOOLEAN,
                allowNull: false,
                defaultValue: false
            },
            availableFacilities: {
                type: DataTypes.JSONB,
                allowNull: true,
                defaultValue: null
            }
        }, {
            ...options,
            indexes: [
                {
                    unique: false,
                    fields: [
                        'type'
                    ]
                },
                {
                    unique: false,
                    name: 'code_by_type',
                    fields: [
                        'code',
                        'type'
                    ]
                }
            ],
            syncDirection: SYNC_DIRECTIONS.BIDIRECTIONAL
        });
    }
    static initRelations(models) {
        this.belongsToMany(models.Encounter, {
            through: models.EncounterDiet,
            as: 'diet',
            foreignKey: 'dietId'
        });
        this.belongsToMany(models.ImagingRequest, {
            through: models.ImagingRequestArea,
            as: 'area',
            foreignKey: 'areaId'
        });
        this.belongsToMany(models.Task, {
            through: models.TaskDesignation,
            as: 'tasks',
            foreignKey: 'designationId'
        });
        this.belongsToMany(models.User, {
            through: models.UserDesignation,
            as: 'designationUsers',
            foreignKey: 'designationId'
        });
        this.belongsToMany(models.Survey, {
            through: models.ProcedureTypeSurvey,
            as: 'surveys',
            foreignKey: 'procedureTypeId'
        });
        this.belongsToMany(this, {
            as: 'parent',
            through: 'reference_data_relations',
            foreignKey: 'referenceDataId',
            otherKey: 'referenceDataParentId'
        });
        this.belongsToMany(this, {
            as: 'children',
            through: 'reference_data_relations',
            foreignKey: 'referenceDataParentId',
            otherKey: 'referenceDataId'
        });
        this.hasOne(models.ImagingAreaExternalCode, {
            as: 'imagingAreaExternalCode',
            foreignKey: 'areaId'
        });
        this.hasOne(models.Facility, {
            as: 'facility',
            foreignKey: 'catchmentId'
        });
        this.hasOne(models.TaskTemplate, {
            as: 'taskTemplate',
            foreignKey: 'referenceDataId'
        });
        this.hasOne(models.ReferenceDrug, {
            as: 'referenceDrug',
            foreignKey: 'referenceDataId'
        });
        this.hasOne(models.ReferenceMedicationTemplate, {
            as: 'medicationTemplate',
            foreignKey: 'referenceDataId'
        });
    }
    static async create(values) {
        // the type column is just text in sqlite so validate it here
        const { type } = values;
        if (type && !REFERENCE_TYPE_VALUES.includes(type)) {
            throw new ValidationError(`Invalid type: ${type}`, []);
        }
        return super.create(values);
    }
    async update(values) {
        if (values.type && values.type !== this.type) {
            throw new InvalidOperationError('The type of a reference data item cannot be changed');
        }
        return super.update(values);
    }
    static async getParent(id, relationType) {
        const record = await this.getNode({
            where: {
                id
            },
            relationType
        });
        return record?.parent;
    }
    // Gets a node in the hierarchy including the parent record
    static async getNode({ where, raw = true, relationType }) {
        return this.findOne({
            where,
            include: {
                model: this,
                as: 'parent',
                required: true,
                through: {
                    attributes: [],
                    where: {
                        type: relationType
                    }
                }
            },
            raw,
            nest: true
        });
    }
    async getAncestors(relationType) {
        const { ReferenceData: ReferenceData1 } = this.sequelize.models;
        const parentNode = await ReferenceData1.getParent(this.id, relationType);
        if (!parentNode) {
            return [];
        }
        return _class_static_private_method_get(ReferenceData1, ReferenceData, getParentRecursive).call(ReferenceData, parentNode.id, [
            parentNode
        ], relationType);
    }
    static buildSyncFilter() {
        return null; // syncs everywhere
    }
    static async buildSyncLookupQueryDetails() {
        return null; // syncs everywhere
    }
}
// ----------------------------------
// Reference data hierarchy utilities
// ----------------------------------
async function getParentRecursive(id, ancestors, relationType) {
    const { ReferenceData: ReferenceData1 } = this.sequelize.models;
    const parent = await ReferenceData1.getParent(id, relationType);
    if (!parent?.id) {
        return ancestors;
    }
    return _class_static_private_method_get(ReferenceData1, ReferenceData, getParentRecursive).call(ReferenceData, parent.id, [
        parent,
        ...ancestors
    ], relationType);
}

//# sourceMappingURL=ReferenceData.js.map