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 { validateClientIntegrations } from '../helpers/clients.helper.js';
const getAllClients = sql `
  SELECT *
  FROM accounter_schema.clients;
`;
const getClientsByIds = sql `
  SELECT *
  FROM accounter_schema.clients
  WHERE business_id IN $$businessIds;
`;
const getClientsByGreenInvoiceIds = sql `
  SELECT *, (integrations->>'greenInvoiceId')::uuid as green_invoice_business_id
  FROM accounter_schema.clients
  WHERE (integrations->>'greenInvoiceId')::uuid in $$greenInvoiceBusinessIds;
`;
const updateClient = sql `
  UPDATE accounter_schema.clients
  SET
  emails = COALESCE(
    $emails,
    emails,
    NULL
  ),
  business_id = COALESCE(
    $newBusinessId,
    business_id,
    NULL
  ),
  integrations = COALESCE(
    $integrations,
    integrations,
    NULL
  )
  WHERE
    business_id = $businessId
  RETURNING *;
`;
const deleteClient = sql `
  DELETE FROM accounter_schema.clients
  WHERE business_id = $businessId
  RETURNING business_id;
`;
const insertClient = sql `
    INSERT INTO accounter_schema.clients (business_id, emails, integrations, owner_id)
    VALUES ($businessId, $emails, $integrations, $ownerId)
    RETURNING *;`;
let ClientsProvider = class ClientsProvider {
    db;
    adminContextProvider;
    constructor(db, adminContextProvider) {
        this.db = db;
        this.adminContextProvider = adminContextProvider;
    }
    allClientsPython = null;
    async getAllClients() {
        if (this.allClientsPython) {
            return this.allClientsPython;
        }
        this.allClientsPython = getAllClients.run(undefined, this.db).then(clients => {
            clients.map(client => {
                this.getClientByIdLoader.prime(client.business_id, client);
                try {
                    const { greenInvoiceId } = validateClientIntegrations(client.integrations ?? {});
                    if (greenInvoiceId) {
                        this.getClientByGreenInvoiceIdLoader.prime(greenInvoiceId, {
                            ...client,
                            green_invoice_business_id: greenInvoiceId,
                        });
                    }
                }
                catch {
                    // swallow errors
                }
            });
            return clients;
        });
        return this.allClientsPython;
    }
    async batchClientsByIds(ids) {
        try {
            const matches = await getClientsByIds.run({ businessIds: ids }, this.db);
            return ids.map(id => matches.find(match => match.business_id === id));
        }
        catch (e) {
            console.error(e);
            return ids.map(() => undefined);
        }
    }
    getClientByIdLoader = new DataLoader((keys) => this.batchClientsByIds(keys));
    async batchClientsByGreenInvoiceIds(greenInvoiceIds) {
        try {
            const matches = await getClientsByGreenInvoiceIds.run({ greenInvoiceBusinessIds: greenInvoiceIds }, this.db);
            matches.map(match => {
                this.getClientByIdLoader.prime(match.business_id, match);
            });
            return greenInvoiceIds.map(id => matches.find(match => match.green_invoice_business_id === id));
        }
        catch (e) {
            console.error(e);
            return greenInvoiceIds.map(() => undefined);
        }
    }
    getClientByGreenInvoiceIdLoader = new DataLoader((keys) => this.batchClientsByGreenInvoiceIds(keys));
    async updateClient(params) {
        if (params.businessId) {
            this.getClientByIdLoader.clear(params.businessId);
        }
        this.clearCache();
        return updateClient.run(params, this.db);
    }
    async deleteClient(businessId) {
        this.clearCache();
        return deleteClient.run({ businessId }, this.db);
    }
    async insertClient(params) {
        this.clearCache();
        const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
        return insertClient.run(reassureOwnerIdExists(params, ownerId), this.db);
    }
    clearCache() {
        this.allClientsPython = null;
        this.getClientByIdLoader.clearAll();
        this.getClientByGreenInvoiceIdLoader.clearAll();
    }
};
ClientsProvider = __decorate([
    Injectable({
        scope: Scope.Operation,
        global: true,
    }),
    __metadata("design:paramtypes", [TenantAwareDBClient,
        AdminContextProvider])
], ClientsProvider);
export { ClientsProvider };
//# sourceMappingURL=clients.provider.js.map