import { ChangeDetectionStrategy, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { SearchComponentStoreService } from '@store/search-component-store';
import { UiScrollContainerComponent } from '@ui/scroll-container';
import { Observable, Subject } from 'rxjs';
import { bufferCount, debounceTime, filter, first, map, switchMap, takeUntil, withLatestFrom } from 'rxjs/operators';

@Component({
  selector: 'page-customer-search-result',
  templateUrl: './search-results.component.html',
  styleUrls: ['./search-results.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerSearchResultComponent implements OnInit, OnDestroy {
  @ViewChild('scrollContainer', { static: false })
  scrollContainer: UiScrollContainerComponent;

  private _onDestroy$ = new Subject();

  processId$: Observable<number>;

  constructor(public store: SearchComponentStoreService, private _breadcrumb: BreadcrumbService, private _activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    this.processId$ = this._activatedRoute.parent.parent.data.pipe(map((data) => +data.processId));
    this._activatedRoute.queryParams
      .pipe(takeUntil(this._onDestroy$), withLatestFrom(this.processId$))
      .subscribe(([queryParams, processId]) => this.handleBreadcrumbs(processId, queryParams));
    this.store.filter$
      .pipe(
        takeUntil(this._onDestroy$),
        filter((filter) => !!filter),
        debounceTime(10),
        withLatestFrom(this.store.items$, this.store.fetching$)
      )
      .subscribe(([_, items, fetching]) => {
        if (items?.length === 0 && !fetching) {
          this.store.search({ clear: true });
        }
      });

    this.processId$
      .pipe(
        takeUntil(this._onDestroy$),
        switchMap((_) =>
          this.store.items$.pipe(
            filter((items) => items?.length > 0),
            debounceTime(10),
            first()
          )
        ),
        withLatestFrom(this._activatedRoute.queryParams)
      )
      .subscribe(([_, queryParams]) => {
        setTimeout(() => this.scrollContainer.scrollTo(Number(queryParams.scrollPos ?? 0)));
      });

    this.processId$
      .pipe(takeUntil(this._onDestroy$), bufferCount(2, 1))
      .subscribe((processIds) => this.updateScrollPosition(processIds[0]));
  }

  async addOrUpdateBreadcrumb(processId: number, queryParams: Record<string, string>) {
    await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
      key: processId,
      name: queryParams.main_qs ?? 'Alle Kunden',
      path: `/kunde/${processId}/customer/search/result`,
      params: queryParams,
      tags: ['customer', 'search', 'result', 'filter'],
      section: 'customer',
    });
  }

  removeDetailBreadcrumbs(processId: number) {
    this._breadcrumb.removeBreadcrumbsByKeyAndTags(processId, ['customer', 'details']);
  }

  handleBreadcrumbs(processId: number, queryParams: Record<string, string>) {
    this.addOrUpdateBreadcrumb(processId, queryParams);
    this.removeDetailBreadcrumbs(processId);
  }

  async ngOnDestroy() {
    const processId = await this.processId$.pipe(first()).toPromise();
    this.updateScrollPosition(processId);

    this._onDestroy$.next();
    this._onDestroy$.complete();
  }

  updateScrollPosition(processId: number) {
    const scrollPos = `${this.scrollContainer.scrollPos}`;
    this.addOrUpdateBreadcrumb(processId, { ...this.store.filter.getQueryParams(), scrollPos });
  }

  triggerSearch() {
    if (this.store?.hits > this.store?.items?.length && !this.store?.fetching) {
      this.store.search({});
    }
  }
}
