import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, ViewChild, inject, AfterContentInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { CustomerSearchStore } from '../store/customer-search.store';
import { Subscription, BehaviorSubject, combineLatest, Subject, race } from 'rxjs';
import { delay, filter, map, take, takeUntil } from 'rxjs/operators';
import { Filter } from '@shared/components/filter';
import { CustomerResultListComponent } from '../../components/customer-result-list/customer-result-list.component';
import { isEmpty } from 'lodash';
import { CustomerSearchNavigation } from '@shared/services/navigation';
import { Location } from '@angular/common';
import { injectCancelSearch } from '@shared/services/cancel-subject';

@Component({
  selector: 'page-customer-results-side-view',
  templateUrl: 'results-side-view.component.html',
  styleUrls: ['results-side-view.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: false,
})
export class CustomerResultsSideViewComponent implements OnInit, OnDestroy, AfterContentInit {
  private _store = inject(CustomerSearchStore);
  private _router = inject(Router);
  private _navigation = inject(CustomerSearchNavigation);
  private _location = inject(Location);

  cancelSearch = injectCancelSearch();

  processId$ = this._store.processId$;

  currentUrl$ = new BehaviorSubject<string>(this._router.url);

  filterRoute$ = combineLatest([this.processId$, this.currentUrl$]).pipe(
    map(([processId, url]) => {
      const route = this._navigation.filterRoute({ processId, comingFrom: url.split('?')[0] });
      const routeTree = this._router.createUrlTree(route.path, { queryParams: route.queryParams });
      const currentlyActive = this._router.isActive(routeTree, {
        fragment: 'ignored',
        matrixParams: 'ignored',
        paths: 'exact',
        queryParams: 'ignored',
      });

      if (currentlyActive) {
        return undefined;
      }

      return route;
    }),
  );

  get isFilterRouteActive() {
    return this._router.isActive(this._navigation.filterRoute({ processId: this._store.processId }).urlTree, {
      fragment: 'ignored',
      matrixParams: 'ignored',
      paths: 'exact',
      queryParams: 'ignored',
    });
  }

  routerEventsSubscription: Subscription;

  filter$ = this._store.filter$;

  hasFilter$ = this.filter$.pipe(
    map((filter) => {
      if (!filter) return false;
      const qt = filter.getQueryToken();
      return !isEmpty(qt.filter);
    }),
  );

  message$ = this._store.message$;

  fetching$ = this._store.fetchingCustomerList$;

  hits$ = this._store.customerListCount$;

  customers$ = this._store.customerList$;

  @ViewChild(CustomerResultListComponent, { static: true }) customerResultListComponent: CustomerResultListComponent;

  private _onDestroy$ = new Subject<void>();

  ngOnInit(): void {
    this.routerEventsSubscription = this._router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.currentUrl$.next(event.url);
      }
    });
  }

  ngOnDestroy(): void {
    this.routerEventsSubscription?.unsubscribe();

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

  ngAfterContentInit(): void {
    const scrollIndex = this._store.restoreScrollIndex();

    if (typeof scrollIndex === 'number') {
      const hasCustomerList$ = this._store.customerList$.pipe(filter((customers) => customers?.length > 0));
      race(hasCustomerList$, this._store.customerListRestored$, this._store.customerListResponse$)
        .pipe(takeUntil(this._onDestroy$), delay(100), take(1))
        .subscribe(() => {
          this.customerResultListComponent.scrollToIndex(Number(scrollIndex));
        });
    }
  }

  closeFilter() {
    this._location.back();
  }

  search(filter: Filter) {
    this._store.setFilter(filter);
    this._store.search({ resetScrollIndex: true, ignoreRestore: true });
  }

  paginate() {
    this._store.paginate();
  }

  scrollIndexChange(index: number) {
    this._store.storeScrollIndex(index);
  }
}
