import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { BreadcrumbService } from '@core/breadcrumb';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import {
  SearchComponentStoreService,
  SearchState,
  SEARCH_STATE_SEARCH_SERVICE,
  SEARCH_STATE_SETTINGS_LOADER,
} from '@store/search-component-store';
import { CustomerSearchStateSettingsLoader } from './services/customer.search-state-settings-loader';
import { CustomerSearchStateSearchService } from './services/customer.search-state-search-service';
import { ActivatedRoute, Router } from '@angular/router';
import { isEqual } from 'lodash';
import { filter, first, map, takeUntil, withLatestFrom } from 'rxjs/operators';
import { CustomerInfoDTO } from '@swagger/crm';
import { UiFilterAutocompleteProvider } from '@ui/filter';
import { CustomerSearchMainAutocompleteProvider } from './providers/customer-search-main-autocomplete.provider';
import { UiErrorModalComponent, UiModalService } from '@ui/modal';

@Component({
  selector: 'page-customer-search',
  templateUrl: 'customer-search.component.html',
  styleUrls: ['customer-search.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  providers: [
    SearchComponentStoreService,
    {
      provide: SEARCH_STATE_SETTINGS_LOADER,
      useClass: CustomerSearchStateSettingsLoader,
    },
    {
      provide: SEARCH_STATE_SEARCH_SERVICE,
      useClass: CustomerSearchStateSearchService,
    },
    {
      provide: UiFilterAutocompleteProvider,
      useClass: CustomerSearchMainAutocompleteProvider,
      multi: true,
    },
  ],
})
export class CustomerSearchComponent implements OnInit, OnDestroy {
  private _onDestroy$ = new Subject();

  private _processId$: Observable<number>;

  initialFilter$ = this._store.filter$.pipe(
    filter((filter) => !!filter),
    first()
  );

  hasFilter$ = this._store.filter$.pipe(
    withLatestFrom(this.initialFilter$),
    map(([filter, initialFilter]) => !isEqual(filter?.getQueryParams(), initialFilter?.getQueryParams()))
  );

  filterActive$ = new BehaviorSubject<boolean>(false);

  constructor(
    private _breadcrumb: BreadcrumbService,
    private _store: SearchComponentStoreService,
    private _router: Router,
    private _activatedRoute: ActivatedRoute,
    private _modal: UiModalService
  ) {}

  ngOnInit() {
    this.initProcessId();
    this.initFilter();
  }

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

  initFilter() {
    this._activatedRoute.url
      .pipe(takeUntil(this._onDestroy$), withLatestFrom(this._activatedRoute.queryParams, this._processId$))
      .subscribe(([_, queryParams, processId]) => {
        this.resetFilter(queryParams);
        this.addOrUpdateBreadcrumb(processId, queryParams);
      });

    this._store.searchCompleted
      .pipe(takeUntil(this._onDestroy$), withLatestFrom(this._processId$))
      .subscribe(([state, processId]) => this.handleSearchCompleted(state, processId));
  }

  async initProcessId() {
    this._processId$ = this._activatedRoute.parent.data.pipe(map((data) => Number(data.processId)));
  }

  handleSearchCompleted(state: SearchState<CustomerInfoDTO>, processId: number) {
    const queryParams = state.filter?.getQueryParams();

    if (state.hits === 1) {
      const customer = state.items[0];
      if (!customer) {
        this._modal.open({ content: UiErrorModalComponent, title: 'Kundendatensatz nicht vorhanden' });
        return;
      }

      const id = Number(customer?.id);
      if (id < 0) {
        this.navigateToCreateCustomer(processId, state.items[0]);
      } else {
        this.navigateToDetails(processId, id);
      }
    } else if (state.hits > 0) {
      this.navigateToResults(processId, queryParams);
    } else {
      this.updateQueryParamsInCurrentUrl(queryParams);
    }
    this.patchBradcrumb(processId, queryParams);
  }

  resetFilter(queryParams: Record<string, string>) {
    const currentQueryParams = this._store.filter?.getQueryParams();
    if (!isEqual(currentQueryParams, queryParams)) {
      this._store.resetFilter(queryParams);
    }
  }

  navigateToResults(processId: number, queryParams: Record<string, string>) {
    this._router.navigate(['/kunde', processId, 'customer', 'search', 'result'], {
      queryParams,
    });
  }

  navigateToCreateCustomer(processId: number, customer: CustomerInfoDTO) {
    const feature = customer?.features?.find((feature) => feature.key === 'webshop') ? 'webshop' : 'store';
    const customerCreateQueryParams = {
      gender: customer?.gender,
      title: customer?.title,
      firstName: customer?.firstName,
      lastName: customer?.lastName,
      email: customer?.communicationDetails?.email,
      phone: customer?.communicationDetails?.phone,
      mobile: customer?.communicationDetails?.mobile,
      street: customer?.address?.street,
      streetNumber: customer?.address?.streetNumber,
      zipCode: customer?.address?.zipCode,
      city: customer?.address?.city,
      country: customer?.address?.country,
      info: customer?.address?.info,
      name: customer?.organisation?.name,
      department: customer?.organisation?.department,
      vatId: customer?.organisation?.vatId,
      dateOfBirth: customer?.dateOfBirth,
      card: encodeURIComponent(JSON.stringify(customer?.features[0])),
      cardFeature: feature,
    };
    this._router.navigate(
      ['/kunde', processId, 'customer', 'create', customer?.features?.find((feature) => feature.key === 'webshop') ? 'webshop' : 'store'],
      {
        queryParams: customerCreateQueryParams,
      }
    );
  }

  navigateToDetails(processId: number, customerId: number) {
    this._router.navigate(['/kunde', processId, 'customer', customerId]);
  }

  addOrUpdateBreadcrumb(processId: number, queryParams: Record<string, string>) {
    this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
      key: processId,
      name: 'Kundensuche',
      path: `/kunde/${processId}/customer/search`,
      params: queryParams,
      section: 'customer',
      tags: ['customer', 'filter', 'main'],
    });
  }

  patchBradcrumb(processId: number, queryParams: Record<string, string>) {
    this._breadcrumb.patchBreadcrumbByKeyAndTags(processId, ['customer', 'filter'], { params: queryParams });
  }

  updateQueryParamsInCurrentUrl(queryParams: Record<string, string>) {
    this._router.navigate([], { queryParams });
  }
}
