import { Component, ChangeDetectionStrategy, inject, ViewChild } from '@angular/core';
import { PickupShelfDetailsBaseComponent } from '../../pickup-shelf-details-base.component';
import { AsyncPipe } from '@angular/common';
import { PickUpShelfDetailsHeaderComponent } from '../../shared/pickup-shelf-details-header/pickup-shelf-details-header.component';
import { PickUpShelfDetailsItemComponent } from '../../shared/pickup-shelf-details-item/pickup-shelf-details-item.component';
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@generated/swagger/oms-api';
import { PickUpShelfOutNavigationService } from '@shared/services/navigation';
import { BehaviorSubject, Observable, asapScheduler, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { PickUpShelfDetailsTagsComponent } from '../../shared/pickup-shelf-details-tags/pickup-shelf-details-tags.component';
import { UiSpinnerModule } from '@ui/spinner';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { OnInitDirective } from '@shared/directives/element-lifecycle';
import { FormsModule } from '@angular/forms';
import { RunCheckTrigger } from '../../trigger';
import { PickUpShelfDetailsItemsGroupComponent } from '../../shared/pickup-shelf-details-items-group/pickup-shelf-details-items-group.component';
import { MatomoModule } from 'ngx-matomo-client';

@Component({
  selector: 'page-pickup-shelf-out-details',
  templateUrl: 'pickup-shelf-out-details.component.html',
  styleUrls: ['pickup-shelf-out-details.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: { class: 'page-pickup-shelf-out-details' },
  imports: [
    AsyncPipe,
    PickUpShelfDetailsHeaderComponent,
    PickUpShelfDetailsItemComponent,
    PickUpShelfDetailsTagsComponent,
    PickUpShelfDetailsItemsGroupComponent,
    UiSpinnerModule,
    OnInitDirective,
    FormsModule,
    MatomoModule
],
  providers: [],
})
export class PickupShelfOutDetailsComponent extends PickupShelfDetailsBaseComponent {
  runCheckTrigger = inject(RunCheckTrigger);

  @ViewChild(PickUpShelfDetailsTagsComponent, { static: false })
  pickUpShelfDetailsTags: PickUpShelfDetailsTagsComponent;

  private _pickupShelfOutNavigationService = inject(PickUpShelfOutNavigationService);

  order$ = this.store.order$;

  orderItems$ = this.store.orderItems$;

  groupedItems$: Observable<Array<{ type: string; items: DBHOrderItemListItemDTO[] }>> = this.orderItems$.pipe(
    map((items) => {
      const groups: Array<{ type: string; items: DBHOrderItemListItemDTO[] }> = [];

      // New Set to remove duplicates
      const types = Array.from(new Set(items.map((item) => item?.features?.orderType)));

      for (let type of types) {
        const filteredItemsByType = items.filter((item) => item?.features?.orderType === type);

        if (!!type && filteredItemsByType.length > 0) {
          // Add items to matching orderType group
          groups.push({ type, items: filteredItemsByType });
        }
      }

      return groups;
    }),
  );

  fetchingOrder$ = this.store.fetchingOrder$;
  fetchingItems$ = this.store.fetchingOrderItems$;

  viewFetching$ = combineLatest([this.orderItems$, this.fetchingItems$]).pipe(
    map(([orderItems, fetchingItems]) => orderItems?.length === 0 && fetchingItems),
  );

  showTagsComponent$ = this.store.showTagsComponent$;

  changeActionLoader$ = new BehaviorSubject<string>(undefined);
  changeActionDisabled$ = this.store.disableHeaderStatusDropdown$;

  actionsDisabled$ = this.store.canSelectAction$.pipe(map((canSelectAction) => !canSelectAction));

  addToPreviousCompartmentAction$ = this.store.addToPreviousCompartmentAction$;

  mainActions$ = this.store.mainShelfOutActions$;

  trackByFnGroupDBHOrderItemListItemDTO = (index: number, group: { type: string; items: DBHOrderItemListItemDTO[] }) =>
    group.type;

  trackByFnDBHOrderItemListItemDTO = (index: number, item: DBHOrderItemListItemDTO) => item.orderItemSubsetId;

  get processId() {
    return this.listStore.processId;
  }

  constructor(private _uiModal: UiModalService) {
    super();
  }

  async handleAction(action: KeyValueDTOOfStringAndString) {
    try {
      this.changeActionLoader$.next(action.command);
      this.store.setDisableHeaderStatusDropdown(true);
      const context = await this.execAction({ action });

      if (context) {
        if (
          action.command.includes('ARRIVED') ||
          action.command.includes('PRINT_PRICEDIFFQRCODELABEL') ||
          action.command.includes('BACKTOSTOCK')
        ) {
          const nav = this._pickupShelfOutNavigationService.defaultRoute({ processId: this.processId });
          await this.router.navigate(nav.path, { queryParams: nav.queryParams, queryParamsHandling: 'preserve' });
        } else {
          const item = context?.items.find((_) => true);
          await this.router.navigate(
            this._pickupShelfOutNavigationService.detailRoute({
              processId: this.processId,
              item: {
                compartmentCode: item.compartmentCode,
                orderId: item.orderId,
                orderNumber: item.orderNumber,
                processingStatus: item.processingStatus,
                compartmentInfo: item.compartmentInfo,
              },
            }).path,
            { queryParamsHandling: 'preserve' },
          );
        }
      }
    } catch (error) {
      console.error(error);
      this._uiModal.open({
        content: UiErrorModalComponent,
        data: error,
      });
    }

    asapScheduler.schedule(() => {
      this.runCheckTrigger.next();
    }, 100);

    setTimeout(() => {
      this.store.setDisableHeaderStatusDropdown(false);
      this.changeActionLoader$.next(undefined);
    }, 1000);
  }

  updateDate({ date, type }: { date: Date; type?: 'delivery' | 'pickup' | 'preferred' }) {
    this.store.updateOrderItemSubsetLoading(true);
    switch (type) {
      case 'delivery': // vsl. Lieferdatum
        this.store.orderItems.forEach((item) =>
          this.store.patchOrderItemSubset({ item, changes: { estimatedShippingDate: date.toISOString() } }),
        );
        break;
      case 'pickup': // Abholfrist
        this.store.orderItems.forEach((item) =>
          this.store.patchOrderItemSubset({ item, changes: { compartmentStop: date.toISOString() } }),
        );
        break;
      case 'preferred': // Zurücklegen bis
        this.store.orderItems.forEach((item) =>
          this.store.patchOrderItemSubset({ item, changes: { preferredPickUpDate: date.toISOString() } }),
        );
        break;
      default:
        break;
    }
  }

  updateSpecialComment(item: DBHOrderItemListItemDTO, specialComment: string) {
    this.store.patchOrderItemSubset({ item, changes: { specialComment } });
    this.listStore.patchOrderItem({ orderItemSubsetId: item.orderItemSubsetId, changes: { specialComment } });
  }

  async navigateToEditPage(orderItem: DBHOrderItemListItemDTO) {
    await this.router.navigate(
      this._pickupShelfOutNavigationService.editRoute({
        processId: this.processId,
        item: {
          compartmentCode: orderItem.compartmentCode,
          orderId: orderItem.orderId,
          orderNumber: orderItem.orderNumber,
          processingStatus: orderItem.processingStatus,
          compartmentInfo: orderItem.compartmentInfo,
        },
      }).path,
      { queryParams: { buyerNumber: orderItem?.buyerNumber }, queryParamsHandling: 'merge' },
    );
  }

  async navigateToHistoryPage(orderItem: DBHOrderItemListItemDTO) {
    await this.router.navigate(
      this._pickupShelfOutNavigationService.historyRoute({
        processId: this.processId,
        item: {
          compartmentCode: orderItem.compartmentCode,
          orderId: orderItem.orderId,
          orderNumber: orderItem.orderNumber,
          processingStatus: orderItem.processingStatus,
          compartmentInfo: orderItem.compartmentInfo,
        },
      }).path,
      { queryParams: { orderItemSubsetId: orderItem.orderItemSubsetId }, queryParamsHandling: 'merge' },
    );
  }

  fetchNotifications(item: DBHOrderItemListItemDTO) {
    this.store.fetchOrderItemSubsetTasks(item);
  }

  setSelectedCompartmentInfo(compartmentInfo: string) {
    this.store.setSelectedCompartmentInfo(compartmentInfo);
  }
}
