import { DataTypes, literal, Op } from 'sequelize';
import { SYNC_DIRECTIONS } from '@tamanu/constants';
import { Model } from '../Model';
import { buildEncounterLinkedSyncFilter } from '../../sync/buildEncounterLinkedSyncFilter';
import { dateType } from '../../types/model';
import { buildEncounterLinkedLookupJoins, buildEncounterLinkedLookupSelect } from '../../sync/buildEncounterLinkedLookupFilter';
export class InvoiceItem extends Model {
    static initModel({ primaryKey, ...options }) {
        super.init({
            id: primaryKey,
            orderDate: dateType('orderDate', {
                allowNull: false
            }),
            productId: {
                type: DataTypes.STRING,
                allowNull: true
            },
            quantity: {
                type: DataTypes.INTEGER,
                allowNull: false
            },
            note: {
                type: DataTypes.STRING,
                allowNull: true
            },
            sourceRecordType: {
                type: DataTypes.STRING,
                allowNull: true
            },
            sourceRecordId: {
                type: DataTypes.STRING,
                allowNull: true
            },
            productNameFinal: {
                type: DataTypes.STRING,
                allowNull: true
            },
            manualEntryPrice: {
                type: DataTypes.DECIMAL,
                allowNull: true
            },
            priceFinal: {
                type: DataTypes.DECIMAL,
                allowNull: true
            },
            productCodeFinal: {
                type: DataTypes.STRING,
                allowNull: true
            },
            approved: {
                type: DataTypes.BOOLEAN,
                allowNull: false,
                defaultValue: false
            }
        }, {
            ...options,
            syncDirection: SYNC_DIRECTIONS.BIDIRECTIONAL
        });
    }
    static initRelations(models) {
        this.belongsTo(models.Invoice, {
            foreignKey: 'invoiceId',
            as: 'invoice'
        });
        this.hasOne(models.InvoiceItemDiscount, {
            foreignKey: 'invoiceItemId',
            as: 'discount'
        });
        this.belongsTo(models.User, {
            foreignKey: 'orderedByUserId',
            as: 'orderedByUser'
        });
        this.belongsTo(models.InvoiceProduct, {
            foreignKey: 'productId',
            as: 'product'
        });
        this.hasMany(models.InvoiceItemFinalisedInsurance, {
            foreignKey: 'invoiceItemId',
            as: 'finalisedInsurances'
        });
    }
    static buildPatientSyncFilter(patientCount, markedForSyncPatientsTable) {
        if (patientCount === 0) {
            return null;
        }
        return buildEncounterLinkedSyncFilter([
            this.tableName,
            'invoices',
            'encounters'
        ], markedForSyncPatientsTable);
    }
    static async buildSyncLookupQueryDetails() {
        return {
            select: await buildEncounterLinkedLookupSelect(this),
            joins: buildEncounterLinkedLookupJoins(this, [
                'invoices',
                'encounters'
            ])
        };
    }
    static getListReferenceAssociations(models, invoicePriceListId, tableAlias = 'InvoiceItem') {
        // Validate tableAlias against allow-list to prevent SQL injection
        const allowedAliases = [
            'InvoiceItem',
            'items'
        ];
        if (!allowedAliases.includes(tableAlias)) {
            throw new Error(`Invalid table alias: ${tableAlias}. Must be one of: ${allowedAliases.join(', ')}`);
        }
        const productInclude = [
            {
                model: models.ReferenceData,
                as: 'sourceRefDataRecord',
                attributes: [
                    'code',
                    'type'
                ]
            },
            {
                model: models.LabTestType,
                as: 'sourceLabTestTypeRecord',
                attributes: [
                    'code'
                ]
            },
            {
                model: models.LabTestPanel,
                as: 'sourceLabTestPanelRecord',
                attributes: [
                    'code'
                ]
            },
            {
                model: models.InvoiceInsurancePlanItem,
                as: 'invoiceInsurancePlanItems',
                required: false,
                where: {
                    [Op.and]: [
                        {
                            invoiceInsurancePlanId: {
                                [Op.in]: literal(`(
                  SELECT iip."invoice_insurance_plan_id"
                  FROM "invoices_invoice_insurance_plans" iip
                  WHERE iip."invoice_id" = "${tableAlias}"."invoice_id"
                    AND iip."deleted_at" IS NULL
                )`)
                            }
                        },
                        literal(`EXISTS (
              SELECT 1
              FROM "invoice_products" ip
              WHERE ip."id" = "${tableAlias}"."product_id"
                AND ip."insurable" = true
                AND ip."deleted_at" IS NULL
            )`)
                    ]
                }
            }
        ];
        if (invoicePriceListId) {
            productInclude.push({
                model: models.InvoicePriceListItem,
                where: {
                    invoicePriceListId
                },
                as: 'invoicePriceListItem',
                attributes: [
                    'price',
                    'invoicePriceListId'
                ],
                required: false
            });
        }
        return [
            {
                model: models.InvoiceProduct,
                as: 'product',
                include: productInclude
            },
            {
                model: models.User,
                as: 'orderedByUser',
                attributes: [
                    'displayName'
                ]
            },
            {
                model: models.InvoiceItemDiscount,
                as: 'discount'
            },
            {
                model: models.InvoiceItemFinalisedInsurance,
                as: 'finalisedInsurances'
            }
        ];
    }
}

//# sourceMappingURL=InvoiceItem.js.map