import { Component, ChangeDetectionStrategy, inject } from '@angular/core';
import { BreadcrumbModule } from '@shared/components/breadcrumb';
import { SharedSplitscreenComponent } from '@shared/components/splitscreen';
import { PickupShelfStore, PickupShelfDetailsStore } from '../store';
import { provideComponentStore } from '@ngrx/component-store';
import { PickupShelfIOService, PickupShelfOutService } from '@domain/pickup-shelf';
import {
  GetNameForBreadcrumbData,
  GetPathForBreadcrumbData,
  PickupShelfBaseComponent,
} from '../pickup-shelf-base.component';
import { NavigationRoute, PickUpShelfOutNavigationService } from '@shared/services/navigation';
import { AsyncPipe } from '@angular/common';
import { DBHOrderItemListItemDTO } from '@generated/swagger/oms-api';
import { Observable, of } from 'rxjs';
import { take } from 'rxjs/operators';
import { provideActionHandlers } from '@core/command';
import { ActionHandlerServices } from '@domain/oms';
import { ActionHandlerService } from '../services/action-handler.service';
import { FilterAutocompleteProvider } from '@shared/components/filter';
import { PickUpShelfOutAutocompleteProvider } from './providers/pickup-shelf-out-autocomplete.provider';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { provideCancelSearchSubject } from '@shared/services/cancel-subject';

@Component({
  selector: 'page-pickup-shelf-out',
  templateUrl: 'pickup-shelf-out.component.html',
  styleUrls: ['pickup-shelf-out.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: { class: 'page-pickup-shelf-out' },
  imports: [BreadcrumbModule, SharedSplitscreenComponent, AsyncPipe],
  providers: [
    {
      provide: FilterAutocompleteProvider,
      useClass: PickUpShelfOutAutocompleteProvider,
      multi: true,
    },
    provideComponentStore(PickupShelfStore),
    provideComponentStore(PickupShelfDetailsStore),
    provideCancelSearchSubject(),
    { provide: PickupShelfIOService, useClass: PickupShelfOutService },
    ActionHandlerService,
    provideActionHandlers(ActionHandlerServices),
  ],
})
export class PickupShelfOutComponent extends PickupShelfBaseComponent {
  private _pickupShelfOutNavigationService = inject(PickUpShelfOutNavigationService);

  constructor() {
    super();
  }

  getProcessId(): number {
    const processIdStr = this.activatedRoute.snapshot.params.processId;

    return Number(processIdStr);
  }

  getSection(): 'customer' | 'branch' {
    return 'customer';
  }

  getNameForMainBreadcrumb(data: { processId: number; queryParams: Record<string, string> }): string | Promise<string> {
    return 'Warenausgabe';
  }

  getPathForMainBreadcrumb(data: {
    processId: number;
    queryParams: Record<string, string>;
  }): NavigationRoute | Promise<NavigationRoute> {
    return this._pickupShelfOutNavigationService.defaultRoute({ processId: data.processId });
  }

  getNameForListBreadcrumb(data: GetNameForBreadcrumbData): string | Promise<string> {
    if (data.queryParams?.main_qs) {
      return data.queryParams.main_qs;
    }

    return 'Alle';
  }

  getPathFoListBreadcrumb(data: GetPathForBreadcrumbData): NavigationRoute | Promise<NavigationRoute> {
    return this._pickupShelfOutNavigationService.listRoute({ processId: data.processId });
  }

  getNameForFilterBreadcrumb(data: GetNameForBreadcrumbData): string | Promise<string> {
    return 'Filter';
  }

  getPathForFilter(data: GetPathForBreadcrumbData): NavigationRoute | Promise<NavigationRoute> {
    return this._pickupShelfOutNavigationService.filterRoute({ processId: data.processId });
  }

  async getNameForDetailBreadcrumb(data: GetNameForBreadcrumbData): Promise<string> {
    const compartmentCode = await this.detailsStore.compartmentCode$.pipe(take(1)).toPromise();

    if (compartmentCode) {
      return compartmentCode;
    }

    const order = await this.detailsStore.order$.pipe(take(1)).toPromise();

    if (order?.orderNumber) {
      return order?.orderNumber;
    }

    return 'Details';
  }

  async getPathForDetailForDetailBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = await this.detailsStore.compartmentCode$.pipe(take(1)).toPromise();
    const order = await this.detailsStore.order$.pipe(take(1)).toPromise();
    const processingStatus = await this.detailsStore.processingStatus$.pipe(take(1)).toPromise();

    return this._pickupShelfOutNavigationService.detailRoute({
      processId: data.processId,
      item: {
        orderId: order?.id,
        compartmentCode,
        orderNumber: order?.orderNumber,
        processingStatus: processingStatus,
        compartmentInfo: this.detailsStore.compartmentInfo,
      },
    });
  }

  getPathForDetail(item: DBHOrderItemListItemDTO): Observable<NavigationRoute> {
    return of(
      this._pickupShelfOutNavigationService.detailRoute({
        processId: this.listStore.processId,
        item: {
          compartmentCode: item.compartmentCode,
          orderId: item.orderId,
          orderNumber: item.orderNumber,
          processingStatus: item.processingStatus,
          compartmentInfo: item.compartmentInfo,
        },
      }),
    );
  }

  getPathForEdit(item: DBHOrderItemListItemDTO): Observable<NavigationRoute> {
    return of(
      this._pickupShelfOutNavigationService.editRoute({
        processId: this.listStore.processId,
        item: {
          compartmentCode: item.compartmentCode,
          orderId: item.orderId,
          orderNumber: item.orderNumber,
          processingStatus: item.processingStatus,
          compartmentInfo: item.compartmentInfo,
        },
      }),
    );
  }

  async getPathForEditBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = await this.detailsStore.compartmentCode$.pipe(take(1)).toPromise();
    const order = await this.detailsStore.order$.pipe(take(1)).toPromise();
    const processingStatus = await this.detailsStore.processingStatus$.pipe(take(1)).toPromise();
    const compartmentInfo = await this.detailsStore.compartmentInfo$.pipe(take(1)).toPromise();

    return this._pickupShelfOutNavigationService.editRoute({
      processId: data.processId,
      item: {
        orderId: order?.id,
        compartmentCode,
        orderNumber: order?.orderNumber,
        processingStatus: processingStatus,
        compartmentInfo,
      },
    });
  }

  async getNameForEditBreadcrumb(data: GetNameForBreadcrumbData): Promise<string> {
    return 'Bearbeiten';
  }

  getPathForHistory(item: DBHOrderItemListItemDTO): Observable<NavigationRoute> {
    return of(
      this._pickupShelfOutNavigationService.historyRoute({
        processId: this.listStore.processId,
        item: {
          compartmentCode: item.compartmentCode,
          orderId: item.orderId,
          orderNumber: item.orderNumber,
          processingStatus: item.processingStatus,
          compartmentInfo: item.compartmentInfo,
        },
      }),
    );
  }

  async getPathForHistoryBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = await this.detailsStore.compartmentCode$.pipe(take(1)).toPromise();
    const order = await this.detailsStore.order$.pipe(take(1)).toPromise();
    const processingStatus = await this.detailsStore.processingStatus$.pipe(take(1)).toPromise();
    const compartmentInfo = await this.detailsStore.compartmentInfo$.pipe(take(1)).toPromise();

    return this._pickupShelfOutNavigationService.historyRoute({
      processId: data.processId,
      item: {
        orderId: order?.id,
        compartmentCode,
        orderNumber: order?.orderNumber,
        processingStatus: processingStatus,
        compartmentInfo,
      },
    });
  }

  async getNameForHistoryBreadcrumb(data: GetNameForBreadcrumbData): Promise<string> {
    return 'Historie';
  }

  async regsiterFetchListResponseHandler() {
    this.listStore.fetchListResponse$
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(async ({ processId, queryParams, response }) => {
        /**
         * Wenn die Suche erfolgreich war, wird der Benutzer auf die Liste oder Detailseite des gefundenen Artikels weitergeleitet.
         */
        const filterQueryParams = this.listStore.filter.getQueryParams();

        if (response.hits === 1) {
          const detailsPath = await this.getPathForDetail(response.result[0]).pipe(take(1)).toPromise();
          await this.router.navigate(detailsPath.path, {
            queryParams: { ...queryParams, ...filterQueryParams, ...detailsPath.queryParams },
          });
        } else if (response.hits > 1) {
          const listPath = await this.getPathFoListBreadcrumb({ processId, queryParams });
          await this.router.navigate(listPath.path, {
            queryParams: { ...queryParams, ...filterQueryParams, ...listPath.queryParams },
          });
        } else {
          await this.router.navigate([], { queryParams: { ...queryParams, ...filterQueryParams } });
        }
      });
  }

  // Ticket 4720 WA // Trefferliste wird übersprungen - Bei mehreren Bestellposten pro Bestellung soll IMMER auf Trefferliste navigiert werden
  // Damit werden #4684 und #4688 überflüssig

  // REMOVED: Fix Ticket #4684 Navigate on Details if items contain same OrderNumber
  // private _hasSameOrderNumber(response: ListResponseArgsOfDBHOrderItemListItemDTO) {
  //   if (response.hits === 0) return false;
  //   const orderNumbers = new Set(response.result.map((item) => item.orderNumber));
  //   return orderNumbers.size === 1;
  // }
}
