import { ComponentStore } from '@ngrx/component-store';
import { tapResponse } from '@ngrx/operators';

import { PickupShelfDetailsState } from './pickup-shelf-details.state';
import { Observable, combineLatest, from } from 'rxjs';
import {
  DBHOrderItemListItemDTO,
  EntityDTOContainerOfOrderItemSubsetDTO,
  ListResponseArgsOfDBHOrderItemListItemDTO,
  ListResponseArgsOfOrderItemSubsetTaskListItemDTO,
  OrderDTO,
  OrderItemProcessingStatusValue,
  OrderItemSubsetDTO,
  OrderItemSubsetTaskListItemDTO,
  ReceiptDTO,
  ReceiptType,
  ResponseArgsOfIEnumerableOfValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO,
  ResponseArgsOfOrderDTO,
  ResponseArgsOfOrderItemSubsetDTO,
} from '@generated/swagger/oms-api';
import { PickupShelfIOService, PickupShelfService } from '@domain/pickup-shelf';
import { Injectable, inject } from '@angular/core';
import { distinctUntilChanged, filter, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { UiModalService } from '@ui/modal';
import { CrmCustomerService } from '@domain/crm';
import * as Selectors from './pickup-shelf-details.selectors';
import { CustomerInfoDTO, ListResponseArgsOfCustomerInfoDTO } from '@generated/swagger/crm-api';
import { CacheService } from '@core/cache';
import { RunCheckTrigger } from '../trigger';
import { DomainReceiptService } from '@domain/oms';
import { PickupShelfStore } from './pickup-shelf.store';
import { isEqual } from 'lodash';

@Injectable()
export class PickupShelfDetailsStore extends ComponentStore<PickupShelfDetailsState> {
  private _listStore = inject(PickupShelfStore);

  private _cacheService = inject(CacheService);

  private _pickupShelfService = inject(PickupShelfService);

  private _pickupShelfIOService = inject(PickupShelfIOService);

  private _customerService = inject(CrmCustomerService);

  private _modal = inject(UiModalService);

  private _runCheckTrigger = inject(RunCheckTrigger);

  order$ = this.select(Selectors.selectOrder);

  get order() {
    return this.get(Selectors.selectOrder);
  }

  fetchingOrder$ = this.select(Selectors.selectFetchingOrder);

  get fetchingOrder() {
    return this.get(Selectors.selectFetchingOrder);
  }

  orderItems$ = combineLatest([
    this.select(Selectors.selectOrderItems),
    this.select((s) => s).pipe(switchMap((s) => this._listStore.itemsForPreview$(s))),
  ]).pipe(
    map(([orderItems, itemsForPreview]) => (orderItems?.length ? orderItems : itemsForPreview)),
    distinctUntilChanged((a, b) => isEqual(a, b)),
  );

  get orderItems() {
    const orderItems = this.get(Selectors.selectOrderItems);
    return orderItems?.length ? orderItems : this.get((s) => this._listStore.itemsForPreview(s));
  }

  fetchingOrderItems$ = this.select(Selectors.selectFetchingOrderItems);

  get fetchingOrderItems() {
    return this.get(Selectors.selectFetchingOrderItems);
  }

  noOrderItemsFound$ = this.select(Selectors.selectNoOrderItemsFound);

  get noOrderItemsFound() {
    return this.get(Selectors.selectNoOrderItemsFound);
  }

  processingStatus$ = this.select(Selectors.selectDisplayedOrderItemProcessingStatus);

  get processingStatus() {
    return this.get(Selectors.selectDisplayedOrderItemProcessingStatus);
  }

  orderItemSubsetId$ = this.select(Selectors.selectDisplayedOrderItemSubsetId);

  get orderItemSubsetId() {
    return this.get(Selectors.selectDisplayedOrderItemSubsetId);
  }

  customer$ = this.select(Selectors.selectCustomer);

  get customer() {
    return this.get(Selectors.selectCustomer);
  }

  fetchingCustomer$ = this.select(Selectors.selectFetchingCustomer);

  get fetchingCustomer() {
    return this.get(Selectors.selectFetchingCustomer);
  }

  compartmentCode$ = this.select(Selectors.selectDisplayedCompartmentCode);

  get compartmentCode() {
    return this.get(Selectors.selectDisplayedCompartmentCode);
  }

  compartmentInfo$ = this.select(Selectors.selectDisplayedCompartmentInfo);

  get compartmentInfo() {
    return this.get(Selectors.selectDisplayedCompartmentInfo);
  }

  compartment$ = this.select(Selectors.selectCompartment);

  get compartment() {
    return this.get(Selectors.selectCompartment);
  }

  fetchReceipts$ = this.select(Selectors.selectFetchReceipts);

  get fetchReceipts() {
    return this.get(Selectors.selectFetchReceipts);
  }

  receipts$ = this.select(Selectors.selectReceipts);

  get receipts() {
    return this.get(Selectors.selectReceipts);
  }

  fetchPartial$ = this.select(Selectors.selectFetchPartial);

  get fetchPartial() {
    return this.get(Selectors.selectFetchPartial);
  }

  selectedOrderItemIds$ = this.select(Selectors.selectSelectedOrderItemIds);

  get selectedOrderItemIds() {
    return this.get(Selectors.selectSelectedOrderItemIds);
  }

  selectedOrderItemQuantity$ = this.select(Selectors.selectSelectedOrderItemQuantity);

  get selectedOrderItemQuantity() {
    return this.get(Selectors.selectSelectedOrderItemQuantity);
  }

  selectedCompartmentInfo$ = this.select(Selectors.selectSelectedCompartmentInfo);

  get selectedCompartmentInfo() {
    return this.get(Selectors.selectSelectedCompartmentInfo);
  }
  set selectedCompartmentInfo(selectedCompartmentInfo: string) {
    if (this.selectedCompartmentInfo !== selectedCompartmentInfo) {
      this.patchState({ selectedCompartmentInfo });
    }
  }

  selectedCompartmentCode$ = this.select(Selectors.selectDisplayedCompartmentCode);

  get selectedCompartmentCode() {
    return this.get(Selectors.selectDisplayedCompartmentCode);
  }

  latestCompartmentCodeAndInfoForOrder$ = this.select(Selectors.selectLatestCompartmentCodeAndInfoForOrder);

  get latestCompartmentCodeForOrder() {
    return this.get(Selectors.selectLatestCompartmentCodeAndInfoForOrder);
  }

  selectedOrderItems$ = this.select(Selectors.selectedOrderItems);

  get selectedOrderItems() {
    return this.get(Selectors.selectedOrderItems);
  }

  selectedOrderItem$ = this.select(Selectors.selectedOrderItem);

  get selectedOrderItem() {
    return this.get(Selectors.selectedOrderItem);
  }

  selectPreviousSelectedOrderItemSubsetId$ = this.select(Selectors.selectPreviousSelectedOrderItemSubsetId);

  get selectPreviousSelectedOrderItemSubsetId() {
    return this.get(Selectors.selectPreviousSelectedOrderItemSubsetId);
  }

  canSelectAction$ = this.select(Selectors.selectCanSelectAction);

  get canSelectAction() {
    return this.get(Selectors.selectCanSelectAction);
  }

  showTagsComponent$ = this.select(Selectors.selectShowTagsComponent);

  get showTagsComponent() {
    return this.get(Selectors.selectShowTagsComponent);
  }

  addToPreviousCompartmentAction$ = this.select(Selectors.selectAddToPreviousCompartmentAction);

  get addToPreviousCompartmentAction() {
    return this.get(Selectors.selectAddToPreviousCompartmentAction);
  }

  mainActions$ = this.select(Selectors.selectMainActions);

  get mainActions() {
    return this.get(Selectors.selectMainActions);
  }

  mainShelfOutActions$ = this.select(Selectors.selectShelfOutMainActions);

  get mainShelfOutActions() {
    return this.get(Selectors.selectShelfOutMainActions);
  }

  customerNumber$ = this.select(Selectors.selectCustomerNumber);

  get customerNumber() {
    return this.get(Selectors.selectCustomerNumber);
  }

  fetchingCoverOrderItems$ = this.select(Selectors.selectFetchingCoverOrderItems);

  get fetchingCoverOrderItems() {
    return this.get(Selectors.selectFetchingCoverOrderItems);
  }

  coverOrderItems$ = this.select(Selectors.selectCoverOrderItems);

  get coverOrderItems() {
    return this.get(Selectors.selectCoverOrderItems);
  }

  orderItemSubsetLoading$ = this.select(Selectors.selectOrderItemSubsetLoading);

  get orderItemSubsetLoading() {
    return this.get(Selectors.selectOrderItemSubsetLoading);
  }

  // Wird benöitgt um das Status Dropdown in der Details Header Komponente zu disablen wenn eine Action gehandled wird
  disableHeaderStatusDropdown$ = this.select(Selectors.selectDisableHeaderStatusDropdown);

  get disableHeaderStatusDropdown() {
    return this.get(Selectors.selectDisableHeaderStatusDropdown);
  }

  constructor(private _domainReceiptService: DomainReceiptService) {
    super({
      fetchingOrderItemSubsetTasks: {},
      orderItemSubsetTasks: {},
    });
  }

  setDisableHeaderStatusDropdown(disable: boolean) {
    this.patchState({ disableHeaderStatusDropdown: disable });
  }

  setFetchPartial(fetchPartial: boolean) {
    this.patchState({ fetchPartial });
  }

  resetCoverItems() {
    this.patchState({ coverOrderItems: [] });
  }

  resetSelectedOrderItems() {
    this.patchState({ selectedOrderItemIds: [] });
  }

  resetSelectedOrderItemQuantity() {
    this.patchState({ selectedOrderItemQuantity: {} });
  }

  setSelectedOrderItemQuantity = this.updater(
    (state, { orderItemSubsetId, quantity }: { orderItemSubsetId: number; quantity: number }) => {
      return {
        ...state,
        selectedOrderItemQuantity: { ...state.selectedOrderItemQuantity, [orderItemSubsetId]: quantity },
      };
    },
  );

  setPreviousSelectedOrderItemSubsetId(previousSelectedOrderItemSubsetId: number) {
    this.patchState({ previousSelectedOrderItemSubsetId });
  }

  selectOrderItem(item: DBHOrderItemListItemDTO, selected: boolean) {
    const included = this.selectedOrderItemIds.includes(item?.orderItemSubsetId);

    if (!included && selected) {
      this.patchState({ selectedOrderItemIds: [...this.selectedOrderItemIds, item.orderItemSubsetId] });
    } else if (included && !selected) {
      this.patchState({
        selectedOrderItemIds: this.selectedOrderItemIds.filter((id) => id !== item?.orderItemSubsetId),
      });
    }
  }

  selectAllOrderItemIds() {
    this.patchState({ selectedOrderItemIds: this.orderItems?.map((item) => item?.orderItemSubsetId) });
  }

  updateOrderItems(orderItems: DBHOrderItemListItemDTO[]) {
    this.patchState({
      orderItems: this.orderItems.map((item) => {
        const newItem = orderItems.find((i) => i.orderItemSubsetId === item.orderItemSubsetId);
        return newItem ? newItem : item;
      }),
    });
  }

  updateReceipts(receipts: ReceiptDTO[]) {
    this.patchState({
      receipts,
    });
  }

  loadReceipts = this.effect((item$: Observable<DBHOrderItemListItemDTO>) =>
    item$.pipe(
      filter((item) => !!item),
      tap((_) => this.beforeFetchReceipts()),
      switchMap((item) =>
        this._domainReceiptService
          .getReceipts({
            receiptType: 65 as ReceiptType,
            ids: [item.orderItemSubsetId],
            eagerLoading: 1,
          })
          .pipe(tapResponse(this.fetchReceiptsDone, this.fetchReceiptsFailed)),
      ),
    ),
  );

  private beforeFetchReceipts = () => {
    this.patchState({ fetchingReceipts: true });
  };

  private fetchReceiptsDone = (
    res: ResponseArgsOfIEnumerableOfValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO,
  ) => {
    const receipts = res.result.map((r) => r.item3?.data).filter((f) => !!f);
    this.patchState({ receipts, fetchingReceipts: false });
  };

  private fetchReceiptsFailed = (error: any) => {
    this._modal.error('Fehler beim Laden der Receipts', error);
    this.patchState({ fetchingReceipts: false });
  };

  fetchOrder = this.effect((trigger$: Observable<{ orderId: number }>) =>
    trigger$.pipe(
      switchMap(({ orderId }) => from(this.beforeFetchOrder(orderId)).pipe(map(() => ({ orderId })))),
      switchMap(({ orderId }) =>
        this._pickupShelfService
          .getOrderByOrderId(orderId)
          .pipe(tapResponse(this.fetchOrderSuccess, this.fetchOrderFailed)),
      ),
    ),
  );

  private beforeFetchOrder = async (orderId) => {
    const order = (await this._cacheService.get<OrderDTO>({
      name: 'order',
      orderId,
      store: 'PickupShelfDetailsStore',
    })) ?? { id: orderId };
    const customer = await this._cacheService.get<CustomerInfoDTO>({
      name: 'customer',
      orderId,
      store: 'PickupShelfDetailsStore',
    });

    this.patchState({ fetchingOrder: true, order, customer });
  };

  private fetchOrderSuccess = (res: ResponseArgsOfOrderDTO) => {
    this.patchState({ fetchingOrder: false, order: res.result });

    this._cacheService.set<OrderDTO>(
      { name: 'order', orderId: res.result.id, store: 'PickupShelfDetailsStore' },
      res.result,
      {
        ttl: 3600000,
      },
    );

    this.fetchCustomer({ buyerNumber: res.result.buyer.buyerNumber });
    this._runCheckTrigger.next();
  };

  private fetchOrderFailed = (error: any) => {
    this._modal.error('Fehler beim Laden der Bestellung', error);
    this.patchState({ fetchingOrder: false });
  };

  fetchOrderItems = this.effect(
    (
      trigger$: Observable<{
        orderNumber?: string;
        compartmentCode?: string;
        compartmentInfo?: string;
        orderItemProcessingStatus?: OrderItemProcessingStatusValue;
        orderItemSubsetId?: number;
        orderDate?: string;
        done?: { resolve: (items: DBHOrderItemListItemDTO[]) => void; reject: (err?) => void };
      }>,
    ) =>
      trigger$.pipe(
        switchMap((data) => from(this.beforeFetchOrderItems(data)).pipe(map(() => data))),
        withLatestFrom(this._listStore.filter$),
        switchMap(([{ compartmentCode, orderNumber, compartmentInfo, orderItemProcessingStatus, done }, filter]) =>
          this._pickupShelfIOService
            .getOrderItemsByOrderNumberOrCompartmentCode({ compartmentCode, orderNumber, filter })
            .pipe(
              tapResponse(
                (r) =>
                  this.fetchOrderItemsSuccess(
                    { compartmentCode, compartmentInfo, orderItemProcessingStatus },
                    done?.resolve,
                  )(r),
                (e) => this.fetchOrderItemsFailed(done?.reject)(e),
              ),
            ),
        ),
      ),
  );

  private beforeFetchOrderItems = async ({
    compartmentCode,
    compartmentInfo,
    orderItemProcessingStatus,
    orderItemSubsetId,
  }: {
    orderNumber?: string;
    compartmentCode?: string;
    compartmentInfo?: string;
    orderItemProcessingStatus?: OrderItemProcessingStatusValue;
    orderItemSubsetId?: number;
  }) => {
    const orderItems =
      (await this._cacheService.get<DBHOrderItemListItemDTO[]>({
        name: 'orderItems',
        orderId: this.order?.id,
        compartmentCode,
        compartmentInfo,
        orderItemProcessingStatus,
        store: 'PickupShelfDetailsStore',
      })) ?? [];

    this.patchState({
      fetchingOrderItems: true,
      orderItems,
      displayedCompartmentCode: compartmentCode,
      displayedCompartmentInfo: compartmentInfo,
      displayedOrderItemProcessingStatus: orderItemProcessingStatus,
      displayedOrderItemSubsetId: orderItemSubsetId,
      orderItemSubsetTasks: {},
      fetchingOrderItemSubsetTasks: {},
    });
  };

  private fetchOrderItemsSuccess =
    (
      {
        compartmentCode,
        compartmentInfo,
        orderItemProcessingStatus,
      }: {
        compartmentCode?: string;
        compartmentInfo?: string;
        orderItemProcessingStatus?: OrderItemProcessingStatusValue;
      },
      resolve?: (items: DBHOrderItemListItemDTO[]) => void,
    ) =>
    (res: ListResponseArgsOfDBHOrderItemListItemDTO) => {
      // // Ticket #4348
      // check if order items belong to the same customer
      // if (buyerNumbers.length > 1) {
      //   this._modal.error('Fehler beim Laden der Bestellpositionen', new Error('Die Bestellpositionen gehören zu unterschiedlichen Kunden.'));
      //   return;
      // }

      this._cacheService.set<DBHOrderItemListItemDTO[]>(
        {
          name: 'orderItems',
          orderId: this.order?.id,
          compartmentCode,
          compartmentInfo,
          orderItemProcessingStatus,
          store: 'PickupShelfDetailsStore',
        },
        res.result,
      );

      this.patchState({ fetchingOrderItems: false, orderItems: res.result });
      this._runCheckTrigger.next();
      resolve?.(res.result);
    };

  private fetchOrderItemsFailed = (reject?: (err?) => void) => (err: any) => {
    this._modal.error('Fehler beim Laden der Bestellpositionen', err);
    this.patchState({ fetchingOrderItems: false });
    reject?.(err);
  };

  fetchCustomer = this.effect((trigger$: Observable<{ buyerNumber: string }>) =>
    trigger$.pipe(
      filter(({ buyerNumber }) => this.customer?.customerNumber !== buyerNumber),
      switchMap(({ buyerNumber }) => from(this.beforeFetchCustomer()).pipe(map(() => ({ buyerNumber })))),
      switchMap(({ buyerNumber }) =>
        this._customerService
          .getCustomers(buyerNumber)
          .pipe(tapResponse(this.fetchCustomerSuccess, this.fetchCustomerFailed)),
      ),
    ),
  );

  beforeFetchCustomer = async () => {
    const customer = await this._cacheService.get<CustomerInfoDTO>({
      name: 'customer',
      orderId: this.order.id,
      store: 'PickupShelfDetailsStore',
    });
    this.patchState({ fetchingCustomer: !customer, customer: customer });
  };

  fetchCustomerSuccess = (res: ListResponseArgsOfCustomerInfoDTO) => {
    const customers = res.result?.filter((res) => res.customerNumber === this.order.buyer.buyerNumber);

    // check if response contains exactly one customer
    if (customers.length > 1) {
      this._modal.error('Fehler beim Laden des Kunden', new Error('Es wurde mehr als ein Kunde gefunden.'));
      this.patchState({ fetchingCustomer: false });
      return;
    }

    const customer = customers[0];

    if (!customer) {
      this.patchState({ fetchingCustomer: false });
      return;
    }

    const isKulturpass = this.order?.features?.orderSource === 'KulturPass';

    // check if the customer is the same as the order's buyer
    // also check if the order is a KulturPass order, then there may be no customer
    if (!isKulturpass && customer?.customerNumber !== this.order.buyer.buyerNumber) {
      this._modal.error('Fehler beim Laden des Kunden', new Error('Der Kunde ist nicht der Bestellung zugeordnet.'));
      this.patchState({ fetchingCustomer: false });
      return;
    }

    this._cacheService.set<CustomerInfoDTO>(
      {
        name: 'customer',
        orderId: this.order.id,
        store: 'PickupShelfDetailsStore',
      },
      customer,
    );

    this.patchState({ fetchingCustomer: false, customer });
    this._runCheckTrigger.next();
  };

  fetchCustomerFailed = (err: any) => {
    this._modal.error('Fehler beim Laden des Kunden', err);
    this.patchState({ fetchingCustomer: false });
  };

  patchOrderItemSubset = this.effect(
    ($: Observable<{ item: DBHOrderItemListItemDTO; changes: Partial<OrderItemSubsetDTO> }>) =>
      $.pipe(
        mergeMap((data) =>
          this._pickupShelfService.patchOrderItemSubset(data.item, data.changes).pipe(
            tapResponse(
              (res) => this.patchOrderItemSubsetDone(data.item)(res),
              (err) => this.patchOrderItemSubsetError(err),
            ),
          ),
        ),
      ),
  );

  private patchOrderItemSubsetDone = (item: DBHOrderItemListItemDTO) => (res: ResponseArgsOfOrderItemSubsetDTO) => {
    this.patchOrderItemSubsetInState({
      orderItemSubsetId: item.orderItemSubsetId,
      changes: {
        specialComment: res?.result?.specialComment ?? item.specialComment,
        estimatedShippingDate: res.result?.estimatedShippingDate ?? item.estimatedShippingDate,
        estimatedDelivery: res.result?.estimatedDelivery ?? item.estimatedDelivery,
        pickUpDeadline: res.result?.compartmentStop ?? item.pickUpDeadline,
      },
    });

    if (res.result.preferredPickUpDate) {
      this.patchPreferredPickUpDateOnOrderSubsetItemInState({
        item,
        newPreferredPickUpDate: res.result.preferredPickUpDate,
      });
    }

    this.updateOrderItemSubsetLoading(false);
  };

  private patchOrderItemSubsetError = (err: any) => {
    this._modal.error('Fehler beim Speichern der Position', err);
    console.error(err);
  };

  patchPreferredPickUpDateOnOrderSubsetItemInState({
    item,
    newPreferredPickUpDate,
  }: {
    item: DBHOrderItemListItemDTO;
    newPreferredPickUpDate: string;
  }) {
    // Filter selected order subset items from order
    const items = this.order.items;
    const subsetItems: EntityDTOContainerOfOrderItemSubsetDTO[] = items.reduce((acc, item) => {
      return [...acc, ...item.data.subsetItems];
    }, []);
    // #4487 - RD // Abholfach - ändern des vsl. Lieferdatums und "zurückgelegt bis"-Datum wirft Fehler
    // .filter((item) => this.selectedOrderItemIds.find((id) => id === item.data.id));

    // Update preferredPickUpDate on subsetItem from order and patch the state
    const subsetItem = subsetItems.find((subsetItem) => subsetItem.data.id === item.orderItemSubsetId);
    subsetItem.data.preferredPickUpDate = newPreferredPickUpDate;

    this.patchState({
      order: {
        ...this.order,
        items: items,
      },
    });
  }

  patchOrderItemSubsetInState = this.updater(
    (
      state,
      { orderItemSubsetId, changes }: { orderItemSubsetId: number; changes: Partial<DBHOrderItemListItemDTO> },
    ) => {
      return {
        ...state,
        orderItems:
          state.orderItems?.map((i) => {
            if (i.orderItemSubsetId === orderItemSubsetId) {
              return { ...i, ...changes };
            }
            return i;
          }) ?? [],
      };
    },
  );

  fetchOrderItemSubsetTasks = this.effect((item$: Observable<DBHOrderItemListItemDTO>) =>
    item$.pipe(
      tap((item) => this.beforeFetchOrderItemSubsetTasks(item)),
      mergeMap((item) =>
        this._pickupShelfService
          .getOrderItemSubsetTasks(item)
          .pipe(tapResponse(this.fetchOrderItemSubsetTasksDone(item), this.fetchOrderItemSubsetTasksFailed(item))),
      ),
    ),
  );

  private beforeFetchOrderItemSubsetTasks = (item: DBHOrderItemListItemDTO) => {
    this.setOrderItemSubsetTaskFetching({ orderItemSubsetId: item.orderItemSubsetId, fetching: true });
  };

  private fetchOrderItemSubsetTasksDone =
    (item: DBHOrderItemListItemDTO) => (res: ListResponseArgsOfOrderItemSubsetTaskListItemDTO) => {
      this.setOrderItemSubsetTaskFetching({ orderItemSubsetId: item.orderItemSubsetId, fetching: false });
      this.setOrderItemSubsetTasks({ orderItemSubsetId: item.orderItemSubsetId, tasks: res.result });
    };

  private fetchOrderItemSubsetTasksFailed = (item: DBHOrderItemListItemDTO) => (err: any) => {
    this.setOrderItemSubsetTaskFetching({ orderItemSubsetId: item.orderItemSubsetId, fetching: false });
  };

  setOrderItemSubsetTaskFetching = this.updater((state, data: { orderItemSubsetId: number; fetching: boolean }) => {
    return {
      ...state,
      fetchingOrderItemSubsetTasks: {
        ...state.fetchingOrderItemSubsetTasks,
        [data.orderItemSubsetId]: data.fetching,
      },
    };
  });

  getOrderItemSubsetTaskFetching = (orderItemSubsetId: number) => {
    return this.select(Selectors.selectFetchingOrderItemSubsetTasks(orderItemSubsetId));
  };

  setOrderItemSubsetTasks = this.updater(
    (state, data: { orderItemSubsetId: number; tasks: OrderItemSubsetTaskListItemDTO[] }) => {
      return {
        ...state,
        orderItemSubsetTasks: {
          ...state.orderItemSubsetTasks,
          [data.orderItemSubsetId]: data.tasks,
        },
      };
    },
  );

  getOrderItemSubsetTasks$ = (orderItemSubsetId: number) => {
    return this.select(Selectors.selectOrderItemSubsetTasks(orderItemSubsetId));
  };

  getNotifications$ = (orderItemSubsetId: number) => {
    return this.select(Selectors.selectNotifications(orderItemSubsetId));
  };

  getEmailNotificationDate$ = (orderItemSubsetId: number) => {
    return this.select(Selectors.selectLatestEmailNotificationDates(orderItemSubsetId));
  };

  getSmsNotificationDate$ = (orderItemSubsetId: number) => {
    return this.select(Selectors.selectLatestSmsNotificationDate2(orderItemSubsetId));
  };

  fetchCoverOrderItems = this.effect((trigger$: Observable<string>) =>
    trigger$.pipe(
      tap(() => this.beforeFetchCoverOrderItems()),
      switchMap((customerNumber) =>
        this._pickupShelfIOService
          .getOrderItemsByCustomerNumber({
            customerNumber,
          })
          .pipe(
            tapResponse(
              (res) => this.fetchCoverOrderItemsDone(res),
              (err) => this.fetchCoverOrderItemsFailed(err),
            ),
          ),
      ),
    ),
  );

  private beforeFetchCoverOrderItems = () => {
    this.patchState({ fetchingCoverOrderItems: true, coverOrderItems: [] });
  };

  updateOrderItemSubsetLoading(orderItemSubsetLoading: boolean) {
    this.patchState({ orderItemSubsetLoading });
  }

  private fetchCoverOrderItemsDone = (res: ListResponseArgsOfDBHOrderItemListItemDTO) => {
    this.patchState({ fetchingCoverOrderItems: false, coverOrderItems: res.result });
  };

  private fetchCoverOrderItemsFailed = (err: any) => {
    this._modal.error('Fehler beim Laden der Cover Order Items', err);
    this.patchState({ fetchingCoverOrderItems: false });
  };

  setSelectedCompartmentInfo(selectedCompartmentInfo: string) {
    this.patchState({ selectedCompartmentInfo });
  }
}
