import { Component, ChangeDetectionStrategy, inject, OnInit, ViewChild, effect, untracked } 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 { PickUpShelfDetailsTagsComponent } from '../../shared/pickup-shelf-details-tags/pickup-shelf-details-tags.component';
import { PickUpShelfDetailsCoversComponent } from '../../shared/pickup-shelf-details-covers/pickup-shelf-details-covers.component';
import { PickupShelfAddToPreviousCompartmentCodeLabelPipe } from '../../shared/pipes/add-to-prevoius-compartment-code-label.pipe';
import { UiSpinnerModule } from '@ui/spinner';
import { OnInitDirective } from '@shared/directives/element-lifecycle';
import { PickupShelfInNavigationService } from '@shared/services/navigation';
import { BehaviorSubject, asapScheduler, combineLatest } from 'rxjs';
import { distinctUntilChanged, filter, map, shareReplay, tap, throttleTime } from 'rxjs/operators';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@generated/swagger/oms-api';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';
import { ActivatedRoute } from '@angular/router';
import { RunCheckTrigger } from '../../trigger';
import { PickUpShelfDetailsItemsGroupComponent } from '../../shared/pickup-shelf-details-items-group/pickup-shelf-details-items-group.component';
import { isEqual } from 'lodash';
import { SkeletonLoaderComponent } from '@shared/components/loader';
import { MatomoModule } from 'ngx-matomo-client';

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

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

  private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);

  order$ = this.store.order$;

  $customerNumber = toSignal(this.store.customerNumber$.pipe(distinctUntilChanged()));

  orderItems$ = this.store.orderItems$.pipe(shareReplay(1));

  $orderItems = toSignal(this.orderItems$);

  noOrderItemsFound$ = this.store.noOrderItemsFound$;

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

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

  selectedCompartmentInfo = this.store.selectedCompartmentInfo;

  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.mainActions$;

  selectedItem$ = this.store.selectedOrderItem$;

  selectedItemOrderType$ = this.selectedItem$.pipe(map((item) => item?.features?.orderType));

  coverOrderItems$ = this.store.coverOrderItems$;

  displayedCompartmentInfo$ = this.store.compartmentInfo$;

  latestCompartmentInfos$ = this.store.latestCompartmentCodeAndInfoForOrder$;

  latestDisplayedCompartmentInfos$ = this.latestCompartmentInfos$.pipe(
    map((latestCompartmentInfos) => {
      if (latestCompartmentInfos?.latestCompartmentInfo) {
        return `${latestCompartmentInfos?.latestCompartmentCode}_${latestCompartmentInfos?.latestCompartmentInfo}`;
      }
      return latestCompartmentInfos?.latestCompartmentCode;
    }),
  );

  addToPreviousCompartmentActionDisabled$ = combineLatest([
    this.displayedCompartmentInfo$,
    this.changeActionDisabled$,
  ]).pipe(map(([compartmentInfo, changeActionDisabled]) => !!compartmentInfo || changeActionDisabled));

  customerNumberAndSelevtedOrderItemIdsChanges$ = combineLatest([
    this.store.customerNumber$,
    this.store.selectedOrderItem$,
  ]).pipe(
    filter(([_, selectedOrderItem]) => !!selectedOrderItem),
    distinctUntilChanged((a, b) => isEqual(a, b)),
    map(([customerNumber, selectedOrderItem]) => ({ customerNumber, selectedOrderItem })),
  );

  $customerNumberAndSelevtedOrderItemIdsChanges = toSignal(this.customerNumberAndSelevtedOrderItemIdsChanges$);

  constructor(
    private _uiModal: UiModalService,
    private _activatedRoute: ActivatedRoute,
  ) {
    super();

    effect(() => {
      const changes = this.$customerNumberAndSelevtedOrderItemIdsChanges();

      if (changes?.customerNumber) {
        untracked(() => {
          this.store.fetchCoverOrderItems(changes.customerNumber);
        });
      }
    });
  }

  ngOnInit() {
    combineLatest([
      this._activatedRoute.params.pipe(distinctUntilChanged(isEqual)),
      this.orderItems$.pipe(distinctUntilChanged(isEqual)),
    ])
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(([params, items]) => {
        const orderItemSubsetId = +params?.orderItemSubsetId;
        const selectedItem: DBHOrderItemListItemDTO = items?.find(
          (item: DBHOrderItemListItemDTO) => item?.orderItemSubsetId === orderItemSubsetId,
        );

        // Trigger functions only if a new item gets selected
        if (!!selectedItem && this.store.selectPreviousSelectedOrderItemSubsetId !== orderItemSubsetId) {
          this.store.setPreviousSelectedOrderItemSubsetId(orderItemSubsetId); // Wichtig das die ID im Store vorhanden bleibt um z.B. für die Filter eine zurücknavigation zu ermöglichen
          this.store.selectOrderItem(selectedItem, true); // Wird automatisch unselected wenn die Details Seite verlassen wird
        }
      });

    // Fix #4696 - Always Fetch Cover Order Items
    // this._activatedRoute.params.pipe(distinctUntilChanged(isEqual), takeUntilDestroyed(this.destroyRef)).subscribe((_) => {
    //   if (!this.store.coverOrderItems || this.store.coverOrderItems.length === 0) {
    //     this.store.fetchCoverOrderItems();
    //   }
    // });
  }

  changeSelectedCompartmentInfo(compartmentInfo: string) {
    this.store.selectedCompartmentInfo = compartmentInfo;
  }

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

      if (context) {
        if (
          action.command.includes('ARRIVED') ||
          action.command.includes('PRINT_PRICEDIFFQRCODELABEL') ||
          action.command.includes('BACKTOSTOCK')
        ) {
          asapScheduler.schedule(async () => {
            await this.navigateBasedOnCurrentView();
          }, 100);
        } else {
          const item = context?.items.find((_) => true);
          if (item) {
            await this.router.navigate(
              this._pickupShelfInNavigationService.detailRoute({
                item: {
                  compartmentCode: item.compartmentCode,
                  orderId: item.orderId,
                  orderNumber: item.orderNumber,
                  processingStatus: item.processingStatus,
                  orderItemSubsetId: item.orderItemSubsetId,
                  compartmentInfo: item.compartmentInfo,
                },
                side: false,
              }).path,
              { queryParamsHandling: 'preserve' },
            );
            this.listStore.patchOrderItem({
              orderItemSubsetId: item.orderItemSubsetId,
              changes: { processingStatus: item.processingStatus },
            });
          }
        }
      }
    } 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);
  }

  async navigateBasedOnCurrentView() {
    const currentView = await this._activatedRoute?.snapshot?.queryParams?.view;
    switch (currentView) {
      case 'reservation':
        return this.router.navigate(['/filiale', 'goods', 'in', 'reservation'], { queryParamsHandling: 'preserve' });
      case 'cleanup':
        return this.router.navigate(['/filiale', 'goods', 'in', 'cleanup'], { queryParamsHandling: 'preserve' });
      case 'remission':
        return this.router.navigate(['/filiale', 'goods', 'in', 'preview'], { queryParamsHandling: 'preserve' });
      case 'wareneingangsliste':
        return this.router.navigate(['/filiale', 'goods', 'in', 'list'], { queryParamsHandling: 'preserve' });
      default:
        return this.router.navigate(this._pickupShelfInNavigationService.defaultRoute().path);
    }
  }

  updateDate({ date, type }: { date: Date; type?: 'delivery' | 'pickup' | 'preferred' }) {
    this.store.updateOrderItemSubsetLoading(true);
    switch (type) {
      case 'delivery':
        this.store.selectedOrderItems.forEach((item) =>
          this.store.patchOrderItemSubset({ item, changes: { estimatedShippingDate: date.toISOString() } }),
        );
        break;
      case 'pickup':
        this.store.selectedOrderItems.forEach((item) =>
          this.store.patchOrderItemSubset({ item, changes: { compartmentStop: date.toISOString() } }),
        );
        break;
      case 'preferred':
        this.store.selectedOrderItems.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._pickupShelfInNavigationService.editRoute(
        {
          compartmentCode: orderItem.compartmentCode,
          orderId: orderItem.orderId,
          orderNumber: orderItem.orderNumber,
          processingStatus: orderItem.processingStatus,
          orderItemSubsetId: orderItem.orderItemSubsetId,
          compartmentInfo: orderItem.compartmentInfo,
        },
        { side: this.side },
      ).path,
      { queryParams: { buyerNumber: orderItem?.buyerNumber }, queryParamsHandling: 'merge' },
    );
  }

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

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

  async coverClick(orderItems: DBHOrderItemListItemDTO[]) {
    if (orderItems.length === 1) {
      const item = orderItems.find((_) => true);

      await this.router.navigate(
        this._pickupShelfInNavigationService.detailRoute({
          item: {
            compartmentCode: item.compartmentCode,
            compartmentInfo: item.compartmentInfo,
            orderId: item.orderId,
            orderNumber: item.orderNumber,
            processingStatus: item.processingStatus,
            orderItemSubsetId: item.orderItemSubsetId,
          },
          side: this.side,
        }).path,
        { queryParamsHandling: 'preserve' },
      );
    } else {
      if (orderItems.every((item) => item.processingStatus === 128)) {
        // Search by processingStatus and compartmentCode
        const queryParams = {
          main_qs: encodeURIComponent(orderItems.find((_) => true).compartmentCode),
          filter_orderitemprocessingstatus: orderItems.find((_) => true).processingStatus,
        };
        await this.router.navigate(this._pickupShelfInNavigationService.listRoute().path, { queryParams });
      } else {
        // Search by processingStatus and orderNumber
        const queryParams = {
          main_qs: encodeURIComponent(orderItems.find((_) => true).orderNumber),
          filter_orderitemprocessingstatus: orderItems
            .map((item) => item.processingStatus)
            .filter((v, i, a) => a.indexOf(v) === i)
            .join(';'),
        };
        await this.router.navigate(this._pickupShelfInNavigationService.listRoute().path, { queryParams });
      }
    }
  }
}
