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 getAllBusinessTrips = sql `
  SELECT *
  FROM accounter_schema.business_trips`;
const getBusinessTripsByIds = sql `
  SELECT *
  FROM accounter_schema.business_trips
  WHERE  id IN $$businessTripsIds;`;
const getBusinessTripsByChargeIds = sql `
  SELECT btc.charge_id, bt.*
  FROM accounter_schema.business_trip_charges btc
  LEFT JOIN accounter_schema.business_trips bt
    ON btc.business_trip_id = bt.id
  WHERE btc.charge_id IN $$chargeIds;`;
const getChargeIdsByBusinessTripId = sql `
  SELECT charge_id, business_trip_id
  FROM accounter_schema.business_trip_charges
  WHERE business_trip_id IN $$businessTripsIds;`;
const getBusinessTripsByDates = sql `
  WITH business_trips_dates AS (SELECT business_trips_attendees.business_trip_id AS id,
      min(business_trips_attendees.arrival)     AS from_date,
      max(business_trips_attendees.departure)   AS to_date
    FROM accounter_schema.business_trips_attendees
    GROUP BY business_trips_attendees.business_trip_id)
  SELECT DISTINCT ON (bt.id) bt.*,
    btc.charge_id,
    business_trips_dates.from_date,
    business_trips_dates.to_date
  FROM accounter_schema.business_trips bt
  LEFT JOIN accounter_schema.business_trip_charges btc
    ON bt.id = btc.business_trip_id
  LEFT JOIN business_trips_dates
    ON business_trips_dates.id = bt.id
  WHERE business_trips_dates.from_date >= $fromDate AND business_trips_dates.to_date < $toDate ;`;
const updateChargeBusinessTrip = sql `
  INSERT INTO accounter_schema.business_trip_charges (charge_id, business_trip_id, owner_id)
  VALUES($chargeId, $businessTripId, $ownerId)
  ON CONFLICT (charge_id) 
  DO 
    UPDATE SET business_trip_id = $businessTripId
  RETURNING *;`;
const deleteChargeBusinessTrip = sql `
  DELETE FROM accounter_schema.business_trip_charges
  WHERE charge_id = $chargeId;`;
const updateBusinessTrip = sql `
  UPDATE accounter_schema.business_trips
  SET
  name = COALESCE(
    $name,
    name
  ),
  destination = COALESCE(
    $destinationCode,
    destination
  ),
  trip_purpose = COALESCE(
    $tripPurpose,
    trip_purpose
  ),
  accountant_status = COALESCE(
    $accountantStatus,
    accountant_status
  )
  WHERE
    id = $businessTripId
  RETURNING id;
`;
const insertBusinessTrip = sql `
  INSERT INTO accounter_schema.business_trips (name, destination, trip_purpose, owner_id)
  VALUES($name, $destinationCode, $tripPurpose, $ownerId)
  RETURNING id;`;
const updateAccountantApproval = sql `
  UPDATE accounter_schema.business_trips
  SET
    accountant_status = $accountantStatus
  WHERE
    id = $businessTripId
  RETURNING *;
`;
let BusinessTripsProvider = class BusinessTripsProvider {
    db;
    adminContextProvider;
    constructor(db, adminContextProvider) {
        this.db = db;
        this.adminContextProvider = adminContextProvider;
    }
    getAllBusinessTrips() {
        return getAllBusinessTrips.run(undefined, this.db);
    }
    async batchBusinessTripsByIds(businessTripsIds) {
        const businessTrips = await getBusinessTripsByIds.run({
            businessTripsIds,
        }, this.db);
        return businessTripsIds.map(id => businessTrips.find(record => record.id === id));
    }
    getBusinessTripsByIdLoader = new DataLoader((ids) => this.batchBusinessTripsByIds(ids));
    async batchBusinessTripByChargeIds(chargeIds) {
        const businessTrips = await getBusinessTripsByChargeIds.run({
            chargeIds,
        }, this.db);
        return chargeIds.map(id => businessTrips.find(record => record.charge_id === id));
    }
    getBusinessTripsByChargeIdLoader = new DataLoader((ids) => this.batchBusinessTripByChargeIds(ids));
    async batchChargeIdsByBusinessTripIds(businessTripsIds) {
        const businessTripsChargeIds = await getChargeIdsByBusinessTripId.run({
            businessTripsIds,
        }, this.db);
        return businessTripsIds.map(tripId => businessTripsChargeIds
            .filter(({ business_trip_id }) => business_trip_id === tripId)
            .map(match => match.charge_id));
    }
    getChargeIdsByBusinessTripIdLoader = new DataLoader((ids) => this.batchChargeIdsByBusinessTripIds(ids));
    getBusinessTripsByDates(params) {
        return getBusinessTripsByDates.run(params, this.db);
    }
    async updateChargeBusinessTrip(chargeId, businessTripId) {
        const trip = await this.getBusinessTripsByChargeIdLoader.load(chargeId);
        if (trip) {
            this.getBusinessTripsByIdLoader.clear(trip.id);
            this.getChargeIdsByBusinessTripIdLoader.clear(trip.id);
        }
        this.getBusinessTripsByChargeIdLoader.clear(chargeId);
        if (businessTripId) {
            this.getBusinessTripsByIdLoader.clear(businessTripId);
            this.getChargeIdsByBusinessTripIdLoader.clear(businessTripId);
            const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
            return updateChargeBusinessTrip.run(reassureOwnerIdExists({ chargeId, businessTripId, ownerId: null }, ownerId), this.db);
        }
        return deleteChargeBusinessTrip.run({ chargeId }, this.db);
    }
    async updateBusinessTrip(params) {
        if (params.businessTripId) {
            const chargeIds = await this.getChargeIdsByBusinessTripIdLoader.load(params.businessTripId);
            if (chargeIds) {
                chargeIds.map(chargeId => this.getBusinessTripsByChargeIdLoader.clear(chargeId));
            }
            this.getBusinessTripsByIdLoader.clear(params.businessTripId);
        }
        return updateBusinessTrip.run(params, this.db);
    }
    async insertBusinessTrip(params) {
        const { ownerId } = await this.adminContextProvider.getVerifiedAdminContext();
        return insertBusinessTrip.run(reassureOwnerIdExists(params, ownerId), this.db);
    }
    async updateAccountantApproval(params) {
        if (params.businessTripId) {
            const chargeIds = await this.getChargeIdsByBusinessTripIdLoader.load(params.businessTripId);
            if (chargeIds) {
                chargeIds.map(chargeId => this.getBusinessTripsByChargeIdLoader.clear(chargeId));
            }
            this.getBusinessTripsByIdLoader.clear(params.businessTripId);
        }
        return updateAccountantApproval.run(params, this.db);
    }
    clearCache() {
        this.getBusinessTripsByIdLoader.clearAll();
        this.getBusinessTripsByChargeIdLoader.clearAll();
        this.getChargeIdsByBusinessTripIdLoader.clearAll();
    }
};
BusinessTripsProvider = __decorate([
    Injectable({
        scope: Scope.Operation,
        global: true,
    }),
    __metadata("design:paramtypes", [TenantAwareDBClient,
        AdminContextProvider])
], BusinessTripsProvider);
export { BusinessTripsProvider };
//# sourceMappingURL=business-trips.provider.js.map