import { __decorate, __metadata } from "tslib";
import DataLoader from 'dataloader';
import { Injectable, Scope } from 'graphql-modules';
import { sql } from '@pgtyped/runtime';
import { reassureOwnerIdExists } from '../../../shared/helpers/index.js';
import { AdminContextProvider } from '../../admin-context/providers/admin-context.provider.js';
import { TenantAwareDBClient } from '../../app-providers/tenant-db-client.js';
import { TagsProvider } from './tags.provider.js';
const getTagIdsByChargeIDs = sql `
    SELECT *
    FROM accounter_schema.charge_tags
    WHERE charge_id IN $$chargeIDs;`;
const clearChargeTags = sql `
    DELETE FROM accounter_schema.charge_tags
    WHERE charge_id = $chargeId
    AND tag_id IN $$tagIDs;`;
const clearAllChargeTags = sql `
    DELETE FROM accounter_schema.charge_tags
    WHERE charge_id = $chargeId;`;
const insertChargeTag = sql `
    INSERT INTO accounter_schema.charge_tags (charge_id, tag_id, part, owner_id) VALUES ($chargeId, $tagId, $part, $ownerId) ON CONFLICT DO NOTHING;`;
const updateChargeTagPart = sql `
    UPDATE accounter_schema.charge_tags
    SET
    part = COALESCE(
      $part,
      part
    )
    WHERE charge_id = $chargeId
      AND tag_id = $tagId;`;
let ChargeTagsProvider = class ChargeTagsProvider {
    db;
    tagsProvider;
    adminContextProvider;
    constructor(db, tagsProvider, adminContextProvider) {
        this.db = db;
        this.tagsProvider = tagsProvider;
        this.adminContextProvider = adminContextProvider;
    }
    async batchTagsByChargeID(chargeIDs) {
        const tagsMatches = await getTagIdsByChargeIDs.run({ chargeIDs }, this.db);
        const tags = await this.tagsProvider.getTagByIDLoader
            .loadMany(tagsMatches.map(tag => tag.tag_id))
            .then(tags => tags.filter(tag => tag && !(tag instanceof Error)));
        const tagsByChargeId = new Map();
        tagsMatches.map(match => {
            const tag = tags.find(tag => tag.id === match.tag_id);
            if (!tag)
                return;
            if (tagsByChargeId.has(match.charge_id)) {
                tagsByChargeId.get(match.charge_id).push(tag);
            }
            else {
                tagsByChargeId.set(match.charge_id, [tag]);
            }
        });
        return chargeIDs.map(id => tagsByChargeId.get(id) ?? []);
    }
    getTagsByChargeIDLoader = new DataLoader((chargeIds) => this.batchTagsByChargeID(chargeIds));
    async clearChargeTags(params) {
        if (params.chargeId) {
            this.invalidateTagsByChargeID(params.chargeId);
        }
        return clearChargeTags.run(params, this.db);
    }
    async clearAllChargeTags(params) {
        if (params.chargeId) {
            this.invalidateTagsByChargeID(params.chargeId);
        }
        return clearAllChargeTags.run(params, this.db);
    }
    async insertChargeTag(params) {
        if (params.chargeId) {
            this.invalidateTagsByChargeID(params.chargeId);
        }
        const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
        return insertChargeTag.run(reassureOwnerIdExists(params, ownerId), this.db);
    }
    async updateChargeTagPart(params) {
        if (params.chargeId) {
            this.invalidateTagsByChargeID(params.chargeId);
        }
        return updateChargeTagPart.run(params, this.db);
    }
    async invalidateTagsByChargeID(chargeId) {
        this.getTagsByChargeIDLoader.clear(chargeId);
    }
    clearCache() {
        this.getTagsByChargeIDLoader.clearAll();
    }
};
ChargeTagsProvider = __decorate([
    Injectable({
        scope: Scope.Operation,
        global: true,
    }),
    __metadata("design:paramtypes", [TenantAwareDBClient,
        TagsProvider,
        AdminContextProvider])
], ChargeTagsProvider);
export { ChargeTagsProvider };
//# sourceMappingURL=charge-tags.provider.js.map