import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { first, map, shareReplay, takeUntil } from 'rxjs/operators';
import { OrderItemListItemDTO } from '@swagger/oms';
import { ActivatedRoute, Router } from '@angular/router';
import { GoodsInSearchStore } from '../goods-in-search.store';
import { combineLatest, Subject } from 'rxjs';
import { BreadcrumbService } from '@core/breadcrumb';
import { UiScrollContainerComponent } from '@ui/scroll-container';
import { Config } from '@core/config';

@Component({
  selector: 'page-goods-in-search-results',
  templateUrl: 'goods-in-search-results.component.html',
  styleUrls: ['goods-in-search-results.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class GoodsInSearchResultsComponent implements OnInit, OnDestroy {
  @ViewChild(UiScrollContainerComponent) scrollContainer: UiScrollContainerComponent;

  items$ = this._goodsInSearchStore.results$.pipe(shareReplay());

  hits$ = this._goodsInSearchStore.hits$;

  loading$ = this._goodsInSearchStore.fetching$.pipe(shareReplay());

  listEmpty$ = combineLatest([this.loading$, this.hits$]).pipe(
    map(([loading, hits]) => !loading && hits === 0),
    shareReplay()
  );

  byBuyerNumberFn = (item: OrderItemListItemDTO) => item.buyerNumber;

  byOrderNumberFn = (item: OrderItemListItemDTO) => item.orderNumber;

  byProcessingStatusFn = (item: OrderItemListItemDTO) => item.processingStatus;

  byCompartmentCodeFn = (item: OrderItemListItemDTO) => item.compartmentCode;

  private _onDestroy$ = new Subject();

  constructor(
    private _goodsInSearchStore: GoodsInSearchStore,
    private _router: Router,
    private _activatedRoute: ActivatedRoute,
    private _breadcrumb: BreadcrumbService,
    private readonly _config: Config
  ) {}

  ngOnInit() {
    this._goodsInSearchStore.setQueryParams(this._activatedRoute.snapshot.queryParams);
    this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$)).subscribe((queryParams) => {
      this.updateBreadcrumb(queryParams);
    });

    this.initInitialSearch();
    this.createBreadcrumb();
    this.removeBreadcrumbs();
  }

  ngOnDestroy() {
    this._onDestroy$.next();
    this._onDestroy$.complete();

    this.updateBreadcrumb(this._goodsInSearchStore.filter?.getQueryParams());
  }

  async removeBreadcrumbs() {
    const detailsCrumbs = await this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(this._config.get('process.ids.goodsIn'), ['goods-in', 'details'])
      .pipe(first())
      .toPromise();
    const editCrumbs = await this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(this._config.get('process.ids.goodsIn'), ['goods-in', 'edit'])
      .pipe(first())
      .toPromise();

    detailsCrumbs.forEach((crumb) => {
      this._breadcrumb.removeBreadcrumb(crumb.id, true);
    });

    editCrumbs.forEach((crumb) => {
      this._breadcrumb.removeBreadcrumb(crumb.id, true);
    });
  }

  async createBreadcrumb() {
    await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
      key: this._config.get('process.ids.goodsIn'),
      name: this.getBreadcrumbName(),
      path: '/filiale/goods/in/results',
      section: 'branch',
      params: this._goodsInSearchStore.filter?.getQueryParams(),
      tags: ['goods-in', 'results', 'filter'],
    });
  }

  async updateBreadcrumb(queryParams: Record<string, string> = this._goodsInSearchStore.filter?.getQueryParams()) {
    const scroll_position = this.scrollContainer?.scrollPos;
    const take = this._goodsInSearchStore.results?.length;

    if (queryParams) {
      const crumbs = await this._breadcrumb
        .getBreadcrumbsByKeyAndTags$(this._config.get('process.ids.goodsIn'), ['goods-in', 'results', 'filter'])
        .pipe(first())
        .toPromise();

      const name = queryParams.main_qs ? queryParams.main_qs : 'Alle Artikel';
      const params = { ...queryParams, scroll_position, take };

      for (const crumb of crumbs) {
        this._breadcrumb.patchBreadcrumb(crumb.id, {
          name,
          params,
        });
      }
    }
  }

  getBreadcrumbName() {
    const input = this._goodsInSearchStore.filter?.getQueryParams()?.main_qs;

    return input?.replace('ORD:', '') ?? 'Alle';
  }

  initInitialSearch() {
    if (this._goodsInSearchStore.hits === 0) {
      this._goodsInSearchStore.searchResult$.pipe(takeUntil(this._onDestroy$)).subscribe(async (result) => {
        if (result.hits === 0) {
          await this._router.navigate(['/filiale/goods/in'], { queryParams: this._goodsInSearchStore.filter.getQueryParams() });
        } else {
          await this.createBreadcrumb();
          if (result.hits === 1) {
            await this.navigateToDetails(result.result[0]);
          } else {
            if (!!this._goodsInSearchStore.searchOptions?.take) {
              this._goodsInSearchStore.searchOptions = undefined;
              this.scrollContainer.scrollTo(Number(scroll_position ?? 0));
            }
          }
        }
      });
      this._goodsInSearchStore.search();
    }

    const { scroll_position, take } = this._goodsInSearchStore.queryParams;
    if (!!take && !!scroll_position) {
      this._goodsInSearchStore.searchOptions = { take: Number(take) };
    }
  }

  async loadMore() {
    if (this._goodsInSearchStore.hits > this._goodsInSearchStore.results.length && !this._goodsInSearchStore.fetching) {
      this._goodsInSearchStore.search();
    }
  }

  navigateToDetails(orderItem: OrderItemListItemDTO) {
    const customerNumber = orderItem.buyerNumber;
    const orderNumber = orderItem.orderNumber;
    const processingStatus = orderItem.processingStatus;
    const orderItemId = orderItem.orderItemSubsetId;

    this._router.navigate([
      `/filiale/goods/in/details/customer/${encodeURIComponent(customerNumber)}/order/${encodeURIComponent(
        orderNumber
      )}/item/${orderItemId}/${processingStatus}`,
    ]);
  }
}
