import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { ApplicationService } from '@core/application';
import { DomainCatalogService } from '@domain/catalog';
import { UiFilter } from '@ui/filter';
import { combineLatest, NEVER, Subscription } from 'rxjs';
import { catchError, debounceTime, first } from 'rxjs/operators';
import { FocusSearchboxEvent } from '../focus-searchbox.event';
import { ArticleSearchService } from '../article-search.store';
import { isEmpty, isEqual } from 'lodash';

@Component({
  selector: 'page-article-search-main',
  templateUrl: 'search-main.component.html',
  styleUrls: ['search-main.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ArticleSearchMainComponent implements OnInit, OnDestroy {
  readonly history$ = this.catalog.getSearchHistory({ take: 5 }).pipe(catchError(() => NEVER));

  fetching$ = this.searchService.fetching$;

  filter$ = this.searchService.filter$;

  searchboxHint$ = this.searchService.searchboxHint$;

  subscriptions = new Subscription();

  constructor(
    private searchService: ArticleSearchService,
    private catalog: DomainCatalogService,
    private route: ActivatedRoute,
    private application: ApplicationService,
    private breadcrumb: BreadcrumbService,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.subscriptions.add(
      combineLatest([this.application.activatedProcessId$, this.route.queryParams])
        .pipe(debounceTime(0))
        .subscribe(async ([processId, queryParams]) => {
          if (!(this.searchService.filter instanceof UiFilter)) {
            await this.searchService.setDefaultFilter();
          }

          if (processId !== this.searchService.processId) {
            this.updateBreadcrumb(this.searchService.processId, this.searchService.filter.getQueryParams());

            this.searchService.setProcess(processId);
          }

          const cleanQueryParams = this.cleanupQueryParams(queryParams);

          if (!isEqual(cleanQueryParams, this.cleanupQueryParams(this.searchService.filter.getQueryParams()))) {
            await this.searchService.setDefaultFilter(queryParams);
          }

          this.removeResultsAndDetailsBreadcrumbs(processId);
        })
    );
  }

  ngOnDestroy() {
    this.subscriptions.unsubscribe();

    this.updateBreadcrumb(this.searchService.processId, this.searchService.filter.getQueryParams());
  }

  search(filter: UiFilter) {
    this.searchService.setFilter(filter);
    this.searchService.search({ clear: true });
  }

  setQueryHistory(filter: UiFilter, query: string) {
    filter.fromQueryParams({ main_qs: query });
  }

  cleanupQueryParams(params: Record<string, string> = {}) {
    const clean = { ...params };

    for (const key in clean) {
      if (Object.prototype.hasOwnProperty.call(clean, key)) {
        if (clean[key] == undefined) {
          delete clean[key];
        }
      }
    }

    return clean;
  }

  async updateBreadcrumb(processId: number, queryParams: Record<string, string>) {
    const crumbs = await this.breadcrumb.getBreadcrumbsByKeyAndTags$(processId, ['catalog', 'main']).pipe(first()).toPromise();

    crumbs.forEach((crumb) => {
      this.breadcrumb.patchBreadcrumb(crumb.id, {
        params: queryParams,
      });
    });
  }

  async removeResultsAndDetailsBreadcrumbs(processId: number) {
    const resultsCrumbs = await this.breadcrumb.getBreadcrumbsByKeyAndTags$(processId, ['catalog', 'results']).pipe(first()).toPromise();
    const detailCrumbs = await this.breadcrumb.getBreadcrumbsByKeyAndTags$(processId, ['catalog', 'details']).pipe(first()).toPromise();

    resultsCrumbs?.forEach((crumb) => {
      this.breadcrumb.removeBreadcrumb(crumb.id);
    });

    detailCrumbs?.forEach((crumb) => {
      this.breadcrumb.removeBreadcrumb(crumb.id);
    });
  }
}
