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';
const getAllTags = sql `
  SELECT *
  FROM accounter_schema.extended_tags;
`;
const getTagsByIDs = sql `
  SELECT *
  FROM accounter_schema.extended_tags
  WHERE id in $$tagIDs;`;
const getTagsByNames = sql `
  SELECT *
  FROM accounter_schema.extended_tags
  WHERE name in $$tagNames;`;
const addNewTag = sql `
  INSERT INTO accounter_schema.tags (name, owner_id)
  VALUES ($name, $ownerId)
  RETURNING *;
`;
const renameTag = sql `
  UPDATE accounter_schema.tags
  SET name = $newName
  WHERE id = $id
  RETURNING *;
`;
const deleteTag = sql `
  DELETE FROM accounter_schema.tags
  WHERE id = $id
  RETURNING *;
`;
const updateTagParent = sql `
  UPDATE accounter_schema.tags
  SET parent = $parentId
  WHERE id = $id
  RETURNING *;
`;
let TagsProvider = class TagsProvider {
    db;
    adminContextProvider;
    constructor(db, adminContextProvider) {
        this.db = db;
        this.adminContextProvider = adminContextProvider;
    }
    allTagsCache = null;
    getAllTags() {
        if (this.allTagsCache) {
            return this.allTagsCache;
        }
        this.allTagsCache = getAllTags.run(undefined, this.db).then(tags => {
            // Prime the DataLoaders with the fetched tags
            tags.map(tag => {
                if (tag?.id) {
                    this.getTagByIDLoader.prime(tag.id, tag);
                }
                if (tag?.name) {
                    this.getTagByNameLoader.prime(tag.name, tag);
                }
            });
            return tags;
        });
        return this.allTagsCache;
    }
    async batchTagsByID(tagIDs) {
        const tags = await getTagsByIDs.run({ tagIDs }, this.db);
        return tagIDs.map(id => tags.find(tag => tag.id === id));
    }
    getTagByIDLoader = new DataLoader((keys) => this.batchTagsByID(keys));
    async batchTagsByNames(tagNames) {
        const tags = await getTagsByNames.run({ tagNames }, this.db);
        return tagNames.map(name => tags.find(tag => tag.name === name));
    }
    getTagByNameLoader = new DataLoader((keys) => this.batchTagsByNames(keys));
    async addNewTag(params) {
        this.clearCache();
        // TODO(multi-business): accept an explicit target business once the addTag
        // mutation exposes one; today a tag is created for the request's primary business.
        const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
        return addNewTag.run(reassureOwnerIdExists(params, ownerId), this.db);
    }
    async renameTag(params) {
        this.clearCache();
        return renameTag.run(params, this.db);
    }
    async deleteTag(params) {
        this.clearCache();
        return deleteTag.run(params, this.db);
    }
    updateTagParent(params) {
        this.clearCache();
        return updateTagParent.run(params, this.db);
    }
    clearCache() {
        this.getTagByIDLoader.clearAll();
        this.getTagByNameLoader.clearAll();
    }
};
TagsProvider = __decorate([
    Injectable({
        scope: Scope.Operation,
        global: true,
    }),
    __metadata("design:paramtypes", [TenantAwareDBClient,
        AdminContextProvider])
], TagsProvider);
export { TagsProvider };
//# sourceMappingURL=tags.provider.js.map