import { Component, ChangeDetectionStrategy, OnInit, OnDestroy, ViewChild, Output, EventEmitter } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { BreadcrumbService } from '@core/breadcrumb';
import { isEqual } from 'lodash';
import { combineLatest, Observable, Subscription } from 'rxjs';
import { debounceTime, filter, first, map, switchMap, take } from 'rxjs/operators';
import { CustomerOrderSearchStore } from '../customer-order-search.store';
import { EnvironmentService } from '@core/environment';
import { Filter, FilterInputGroupMainComponent } from '@shared/components/filter';
import { CustomerOrdersNavigationService } from '@shared/services/navigation';
import { ApplicationService } from '@core/application';

@Component({
  selector: 'page-customer-order-search-main',
  templateUrl: 'customer-order-search-main.component.html',
  styleUrls: ['customer-order-search-main.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class CustomerOrderSearchMainComponent implements OnInit, OnDestroy {
  filter$ = this._customerOrderSearchStore.filter$.pipe(filter((f) => !!f));

  loading$ = this._customerOrderSearchStore.fetching$;

  message$ = this._customerOrderSearchStore.message$;

  lastProcessId: number | undefined;

  private _subscriptions = new Subscription();

  readonly history$: Observable<string[]> = this._customerOrderSearchStore.searchHistory$;

  get processId() {
    return +this._activatedRoute.parent.parent.snapshot.data.processId;
  }

  hasFilter$ = combineLatest([
    this._customerOrderSearchStore.filter$,
    this._customerOrderSearchStore.defaultSettings$,
  ]).pipe(
    map(([filter, defaultFilter]) => !isEqual(filter?.getQueryParams(), Filter.create(defaultFilter).getQueryParams())),
  );

  processId$ = this._activatedRoute.parent.parent.data.pipe(map((data) => +data.processId));

  get isDesktop$() {
    return this._environment.matchDesktopLarge$;
  }

  @Output() showFilter = new EventEmitter<void>();

  @ViewChild(FilterInputGroupMainComponent, { static: false })
  filterInputGroup: FilterInputGroupMainComponent;

  constructor(
    private _customerOrderSearchStore: CustomerOrderSearchStore,
    private _router: Router,
    private _activatedRoute: ActivatedRoute,
    private _breadcrumb: BreadcrumbService,
    private _environment: EnvironmentService,
    private _navigationService: CustomerOrdersNavigationService,
    private _application: ApplicationService,
  ) {}

  ngOnInit() {
    this._subscriptions.add(
      combineLatest([this.processId$, this._activatedRoute.queryParams])
        .pipe(debounceTime(50))
        .subscribe(([processId, queryParams]) => {
          this.removeBreadcrumbs(processId);
          this.updateBreadcrumb(queryParams);
        }),
    );

    this._subscriptions.add(
      this._application.activatedProcessId$
        .pipe(
          debounceTime(0),
          switchMap((processId) => this._application.getSelectedBranch$(processId)),
        )
        .subscribe((selectedBranch) => {
          const branchChanged = selectedBranch?.id !== this._customerOrderSearchStore?.selectedBranch?.id;
          if (branchChanged) {
            this._customerOrderSearchStore.setBranch(selectedBranch);
          }
        }),
    );

    // Im Zuge des Tickets #4256 auskommentiert, da es zu Problemen geführt hat
    // In der Filter Komponente wird dies schon gemacht

    // // #4143 To make Splitscreen Search and Filter work combined
    // this._subscriptions.add(
    //   this._customerOrderSearchStore.searchStarted.subscribe(async (_) => {
    //     const queryParams = {
    //       ...this.cleanupQueryParams(this._customerOrderSearchStore.filter.getQueryParams()),
    //       main_qs: this.filterInputGroup?.uiInput?.value,
    //     };
    //     this._customerOrderSearchStore.setQueryParams(queryParams);
    //   })
    // );
  }

  ngOnDestroy() {
    this._subscriptions.unsubscribe();
  }

  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 removeBreadcrumbs(processId: number) {
    const resultCrumbs = await this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'results'])
      .pipe(first())
      .toPromise();
    const detailsCrumbs = await this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'details'])
      .pipe(first())
      .toPromise();

    const editCrumbs = await this._breadcrumb
      .getBreadcrumbsByKeyAndTags$(processId, ['customer-order', 'edit'])
      .pipe(first())
      .toPromise();

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

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

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

  async search(filter: Filter) {
    this._customerOrderSearchStore.setMessage('');
    this.filterInputGroup?.cancelAutocomplete();

    const queryParams = filter.getQueryParams();
    this._customerOrderSearchStore.setQueryParams(queryParams);
    await this.updateQueryParams(queryParams);

    this._customerOrderSearchStore.search({ clear: true });
  }

  async updateBreadcrumb(params: Record<string, string>) {
    await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
      key: this.processId,
      name: 'Kundenbestellung',
      path: this._navigationService.getCustomerOrdersBasePath(this.processId).path,
      tags: ['customer-order', 'main', 'filter'],
      section: 'customer',
      params,
    });
  }

  setQueryHistory(filter: Filter, query: string) {
    filter.fromQueryParams({ main_qs: query });
    const queryParams = filter.getQueryParams();
    this._customerOrderSearchStore.setQueryParams(queryParams);
  }

  async updateQueryParams(queryParams: Record<string, string>) {
    await this._router.navigate([], { queryParams });
    await this.updateBreadcrumb(queryParams);
  }
}
