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

@Component({
  selector: 'page-pickup-shelf-in',
  templateUrl: 'pickup-shelf-in.component.html',
  styleUrls: ['pickup-shelf-in.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  host: { class: 'page-pickup-shelf-in' },
  imports: [BreadcrumbModule, SharedSplitscreenComponent],
  providers: [
    {
      provide: FilterAutocompleteProvider,
      useClass: PickUpShelfInAutocompleteProvider,
      multi: true,
    },
    provideComponentStore(PickupShelfStore),
    provideComponentStore(PickupShelfDetailsStore),
    provideCancelSearchSubject(),
    { provide: PickupShelfIOService, useClass: PickupShelfInService },
    ActionHandlerService,
    provideActionHandlers(ActionHandlerServices),
  ],
})
export class PickupShelfInComponent extends PickupShelfBaseComponent {
  application = inject(ApplicationService);

  private _pickupShelfInNavigationService = inject(PickupShelfInNavigationService);

  get pickUpShelfInKey() {
    return this._config.get('process.ids.pickupShelf');
  }

  constructor(private _config: Config) {
    super();
  }

  getProcessId(): number {
    return this.application.activatedProcessId;
  }

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

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

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

  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._pickupShelfInNavigationService.listRoute();
  }

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

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

  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) {
      return;
    }

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

    return 'Details';
  }

  async getPathForDetailForDetailBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = this.detailsStore.compartmentCode;
    const order = this.detailsStore.order;
    const processingStatus = this.detailsStore.processingStatus;
    const orderItemSubsetId = this.detailsStore.orderItemSubsetId;
    const compartmentInfo = this.detailsStore.compartmentInfo;

    // Ticket #4692 - Wenn keine Order vorhanden ist, dann soll Breadcrumb nicht erstellt werden
    // Dies kann z.B. passieren bei Datenbankproblemen wenn das Fetchen der Order sehr lange braucht
    if (!order) {
      return;
    }

    return this._pickupShelfInNavigationService.detailRoute({
      item: {
        orderId: order?.id,
        compartmentCode,
        orderNumber: order?.orderNumber,
        processingStatus: processingStatus,
        orderItemSubsetId,
        compartmentInfo,
      },
      side: data?.queryParams?.side === 'false' ? false : true, // Fix Ticket #4493 - Wenn man von einer anderen Liste aus kommt z.B. Reservieren Liste, dann soll side in der Breadcrumb false sein
    });
  }

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

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

  async getPathForEditBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = this.detailsStore.compartmentCode;
    const order = this.detailsStore.order;
    const processingStatus = this.detailsStore.processingStatus;
    const orderItemSubsetId = this.detailsStore.orderItemSubsetId;
    const compartmentInfo = this.detailsStore.compartmentInfo;

    return this._pickupShelfInNavigationService.editRoute({
      orderId: order?.id,
      compartmentCode,
      orderNumber: order?.orderNumber,
      processingStatus: processingStatus,
      orderItemSubsetId: orderItemSubsetId,
      compartmentInfo,
    });
  }

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

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

  async getPathForHistoryBreadcrumb(data: GetPathForBreadcrumbData): Promise<NavigationRoute> {
    const compartmentCode = this.detailsStore.compartmentCode;
    const order = this.detailsStore.order;
    const processingStatus = this.detailsStore.processingStatus;
    const orderItemSubsetId = this.detailsStore.orderItemSubsetId;
    const compartmentInfo = this.detailsStore.compartmentInfo;

    return this._pickupShelfInNavigationService.historyRoute({
      orderId: order?.id,
      compartmentCode,
      orderNumber: order?.orderNumber,
      processingStatus: processingStatus,
      orderItemSubsetId: orderItemSubsetId,
      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 } });
        }
      });
  }
}
