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

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

  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) {
        const urlTree = this._router.parseUrl(url);
        const comingFrom = urlTree.queryParamMap.get('comingFrom');
        return { path: [comingFrom], urlTree } as NavigationRoute;
      }

      return route;
    }),
  );

  routerEventsSubscription: Subscription;

  filter$ = this._store.filter$;

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

  fetching$ = this._store.fetchingCustomerList$;

  hits$ = this._store.customerListCount$;

  customers$ = this._store.customerList$;

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

  isTablet$ = this._environment.matchTablet$;

  isDesktopSmall$ = this._environment.matchDesktopSmall$;

  message$ = this._store.message$;

  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));
        });
    }
  }

  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);
  }
}
