import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, OnInit, OnDestroy } from '@angular/core';
import { ComponentStore } from '@ngrx/component-store';
import { OrderItemListItemDTO } from '@swagger/oms';
import { DateAdapter, Group, groupBy } from '@ui/common';
import { isEqual } from 'lodash';
import { Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { SharedGoodsInOutOrderDetailsStore } from '../goods-in-out-order-details.store';

export interface SharedGoodsInOutOrderDetailsCoversState {
  orderItems: OrderItemListItemDTO[];
  selectedOrderItem: OrderItemListItemDTO;
  fetching: boolean;
}

@Component({
  selector: 'shared-goods-in-out-order-details-covers',
  templateUrl: 'goods-in-out-order-details-covers.component.html',
  styleUrls: ['goods-in-out-order-details-covers.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SharedGoodsInOutOrderDetailsCoversComponent extends ComponentStore<SharedGoodsInOutOrderDetailsCoversState>
  implements OnInit, OnDestroy {
  @Input()
  get orderItems() {
    return this.get((s) => s.orderItems);
  }
  set orderItems(orderItems: OrderItemListItemDTO[]) {
    if (!isEqual(this.orderItems, orderItems)) {
      this.patchState({ orderItems });
    }
  }

  @Input()
  get selectedOrderItem() {
    return this.get((s) => s.selectedOrderItem);
  }
  set selectedOrderItem(selectedOrderItem: OrderItemListItemDTO) {
    if (!isEqual(this.selectedOrderItem, selectedOrderItem)) {
      this.patchState({ selectedOrderItem });
    }
  }

  @Input()
  get fetching() {
    return this.get((s) => s.fetching);
  }
  set fetching(fetching: boolean) {
    this.patchState({ fetching });
  }
  fetching$ = this.select((s) => s.fetching);

  @Output()
  coverClick = new EventEmitter<OrderItemListItemDTO[]>();

  readonly orderItems$ = this.select((s) => s.orderItems);

  groupedItems$ = this.orderItems$.pipe(
    map((orderItems) => {
      let groupedItems = groupBy(orderItems, this.groupByProcessingStatus);

      // Nach Gruppierung das Group property für die Gesamtsumme der Menge nehmen
      groupedItems.forEach((group) => (group.group = `${group.items.reduce((sum, item) => sum + item.quantity, 0)}`));

      // Sortierung nach der Menge
      groupedItems.sort(this.sortByQuantity);

      // Summe der overallQuantity hinzufügen
      groupedItems.forEach((group) => (group.group += ` / ${group.items[0]?.overallQuantity}`));

      // Items einer Gruppe anhand des readyForPickup Datums sortieren
      groupedItems.forEach(
        (group) => (group.items = group.items.sort((a, b) => new Date(b.readyForPickUp).getTime() - new Date(a.readyForPickUp).getTime()))
      );

      return groupedItems;
    })
  );

  private subscriptions = new Subscription();

  constructor(private host: SharedGoodsInOutOrderDetailsStore, private dateAdapter: DateAdapter) {
    super({
      orderItems: [],
      selectedOrderItem: undefined,
      fetching: false,
    });
  }

  ngOnInit() {
    this.subscriptions.add(
      this.orderItems$
        .pipe(
          map((orderItems) =>
            orderItems
              ?.filter((a) => a.processingStatus === 128)
              ?.filter((a) => {
                if (a.readyForPickUp) {
                  const readyForPickUp = new Date(a.readyForPickUp);
                  return this.dateAdapter.compareDate(readyForPickUp, this.dateAdapter.today()) === 0;
                }
                return false;
              })
              ?.sort((a, b) => new Date(b.readyForPickUp).getTime() - new Date(a.readyForPickUp).getTime())
              ?.find((_) => true)
          )
        )
        .subscribe((orderItem) => {
          this.host.latestCompartmentCode = orderItem?.compartmentCode;
          this.host.latestCompartmentInfo = orderItem?.compartmentInfo;
        })
    );
  }

  ngOnDestroy() {
    this.subscriptions.unsubscribe();
    this.host.latestCompartmentCode = undefined;
  }

  groupByProcessingStatus(item: OrderItemListItemDTO) {
    // Eingetroffene anhand compartmentCode und EAN gruppieren
    if (item.processingStatus === 128) {
      return `${item.processingStatus}_${item.compartmentCode}_${item.product.ean}_${item.orderItemId}`;
    }

    if ([256, 512, 1024, 2048, 4096, 262144, 524288, 1048576].includes(item.processingStatus)) {
      return `${item.processingStatus}_${item.product.ean}_${item.orderItemId}`;
    }

    return `${item.orderItemSubsetId}_${item.product.ean}`;
  }

  sortByQuantity(a: Group<string, OrderItemListItemDTO>, b: Group<string, OrderItemListItemDTO>) {
    if (+a.group < +b.group) {
      return -1;
    }
    if (+a.group > +b.group) {
      return 1;
    }
    return 0;
  }
}
