import { Component, OnInit, AfterViewInit, ViewChild, ChangeDetectorRef, ChangeDetectionStrategy, ViewRef } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { User, Address } from '../../../../core/models/user.model';
import {
  ChangeCurrentRoute,
  UpdateCustomerFormState,
  CustomerOrdersVisited,
  SetDetailsCustomer,
} from '../../../../core/store/actions/process.actions';
import { Router, ActivatedRoute } from '@angular/router';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import { AddBreadcrumb } from '../../../../core/store/actions/breadcrumb.actions';
import { SetActiveUser } from '../../../../core/store/actions/customer.actions';
import { filter, take, tap, switchMap } from 'rxjs/operators';
import { SharedSelectors } from '../../../../core/store/selectors/shared.selectors';
import { ProcessCart } from '../../../../core/models/process-cart.model';
import { CustomerSearchResult } from '../../../../core/models/customer-search-result.model';
import { CustomerFormState } from '../../../../core/models/process.model';
import { ProcessSelectors } from '../../../../core/store/selectors/process.selectors';
import { CustomerSearch } from '../../../../core/models/customer-search.model';
import { CustomerSearchDataSource } from './customer-data.datasource';
import { CustomerService } from '../../../../core/services/customer.service';
import { isNullOrUndefined } from 'util';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { CUSTOMER_SCROLL_INDEX } from '../../../../core/utils/app.constants';
import { AppState } from 'apps/sales/src/app/core/store/state/app.state';
import { DeliveryOption } from 'apps/sales/src/app/core/models/delivery-option.model';

import { Side } from '@libs/ui/lib/small-double-choice-switch';

export interface CustomerFilters {
  guestaccount: boolean;
  onlineshop: boolean;
  bonuscard: boolean;
}

@Component({
  selector: 'app-search-customer-result',
  templateUrl: './customer-search-result.component.html',
  styleUrls: ['./customer-search-result.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomerSearchResultComponent implements OnInit {
  @ViewChild(CdkVirtualScrollViewport)
  viewport: CdkVirtualScrollViewport;
  @Select(SharedSelectors.getSearchedCustomers) customers$: Observable<CustomerSearchResult>;
  @Select(SharedSelectors.getCart) cartData$: Observable<ProcessCart>;
  customerSearch: CustomerSearch;
  customers: User[] = [];
  cartExist = false;
  selectedCustomer: User;
  ds: CustomerSearchDataSource;
  isScan = false;
  cartHasItemsForDownload = false;
  cartHasItemsForDelivery = false;
  selectedFilterMode: Side = Side.RIGHT;

  filters: CustomerFilters = {
    guestaccount: undefined,
    onlineshop: undefined,
    bonuscard: undefined,
  };

  constructor(
    private store: Store,
    private router: Router,
    private customerService: CustomerService,
    private route: ActivatedRoute,
    private cdrf: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.cartData$
      .pipe(
        filter((c) => !isNullOrUndefined(c)),
        take(1),
        tap((processCart: ProcessCart) => {
          if (processCart && processCart.cart && processCart.cart.length > 0) {
            const count = processCart.cart.map((t) => t.quantity).reduce((t1, t2) => t1 + t2);
            this.cartExist = count > 0 ? true : false;
          } else {
            this.cartExist = false;
          }
        }),
        switchMap(() => {
          return this.route.queryParams;
        })
      )
      .subscribe((params) => {
        const isScan = params && params['scan'] && params['scan'] === 'true';
        this.isScan = isScan;
        this.filters = {
          guestaccount: this.selectedFilterMode === Side.RIGHT ? false : undefined,
          bonuscard: undefined,
          onlineshop: undefined,
        };
        this.loadDataSource(isScan, true);
      });
  }

  loadDataSource(isScan: boolean, firstLoad = false) {
    this.customerSearch = this.store.selectSnapshot(ProcessSelectors.getCustomerSearch);
    if (!!this.customerSearch) {
      this.ds = new CustomerSearchDataSource(
        this.customerSearch.query,
        this.store,
        this.customerService,
        this.filters,
        0,
        isScan,
        firstLoad
      );
    }
    this.detectChanges();
    this.scrollToIndex();
  }

  details(user: User, index: number): void {
    const cartHasItemFor = this.store.selectSnapshot(SharedSelectors.cartHasItemsFor);
    this.cartHasItemsForDownload = cartHasItemFor && cartHasItemFor(DeliveryOption.DOWNLOAD);
    this.cartHasItemsForDelivery = cartHasItemFor && cartHasItemFor(DeliveryOption.DELIVERY);

    const hasOnlineAccount = this.hasOnlineAccount(user);
    const hasAllRequiredData = this.hasAllRequiredData(user);

    if ((this.cartHasItemsForDownload || this.cartHasItemsForDelivery) && (!hasOnlineAccount || !hasAllRequiredData)) {
      this.redirectToCustomerUpdate(user);
      return;
    }

    const processId = this.store.selectSnapshot(AppState.getCurrentProcessId);
    sessionStorage.setItem(CUSTOMER_SCROLL_INDEX, index + ':' + processId);
    this.store.dispatch(new SetDetailsCustomer(user.id));
    this.store.dispatch(new CustomerOrdersVisited(false));
    const currentRoute = '/customer/edit/' + user.id;
    this.store.dispatch(
      new AddBreadcrumb(
        {
          name: 'Kundendetails',
          path: currentRoute,
        },
        'customer'
      )
    );
    this.store.dispatch(new ChangeCurrentRoute(currentRoute));
    this.router.navigate([currentRoute]);
  }

  hasAllRequiredData = (user: User): boolean => {
    if (!user.gender || !user.first_name || !user.last_name || !user.email) {
      return false;
    }

    return true;
  };

  hasOnlineAccount = (user: User) => {
    const found = user.features.filter((feature) => feature.key === 'onlineshop');

    if (!found || found.length < 1) {
      return false;
    } else {
      return true;
    }
  };

  processTypes = (cartHasItemsFor: (option: DeliveryOption) => boolean) => {
    this.cartHasItemsForDownload = cartHasItemsFor(DeliveryOption.DOWNLOAD);
  };

  redirectToCustomerCreate() {
    const newBread: Breadcrumb = {
      name: 'Kundendaten erfassen',
      path: '/customer/search/create',
      queryParams: { card: 'create' },
    };

    this.store.dispatch(new UpdateCustomerFormState(CustomerFormState.CREATE));
    this.store.dispatch(new AddBreadcrumb(newBread, 'customer'));
    this.store.dispatch(new ChangeCurrentRoute('/customer/search/create'));
    this.router.navigate(['/customer/search/create'], {
      queryParams: { card: 'create' },
    });
  }

  redirectToCustomerUpdate(user: User) {
    const newBread: Breadcrumb = {
      name: 'Kundendaten erfassen',
      path: '/customer/search/create',
    };

    this.store.dispatch(new SetDetailsCustomer(user.id));
    this.store.dispatch(new UpdateCustomerFormState(CustomerFormState.MISSING_ONLINE));
    this.store.dispatch(new AddBreadcrumb(newBread, 'customer'));
    const currentRoute = `customer/search/missing-data/${user.id}`;
    this.store.dispatch(new ChangeCurrentRoute(currentRoute));
    this.router.navigate([currentRoute], { queryParams: { card: 'create' } });
  }

  updateFilter(val: boolean, type: string) {
    this.filters[type] = val ? (this.selectedFilterMode === Side.LEFT ? true : false) : undefined;
    this.ds = new CustomerSearchDataSource(
      this.customerSearch.query,
      this.store,
      this.customerService,
      this.filters,
      this.ds.allHits,
      this.isScan
    );
  }

  private scrollToIndex() {
    const index = sessionStorage.getItem(CUSTOMER_SCROLL_INDEX);
    if (!isNullOrUndefined(index)) {
      setTimeout(() => {
        const ids = index.split(':');
        const processId = this.store.selectSnapshot(AppState.getCurrentProcessId);
        if (processId === +ids[1]) {
          const idx = +ids[0];
          if (idx) {
            this.viewport.scrollToIndex(idx);
          }
        }
      }, 2500);
    }
  }

  getCustomerDeliveryAddress(user: User) {
    if (!user) {
      return '';
    }
    if (!user.base_addres) {
      return '';
    }
    const address = user.base_addres;
    const plz = address ? (isNullOrUndefined(address.zip) ? '' : address.zip) : '';
    const city = address ? (isNullOrUndefined(address.city) ? '' : address.city) : '';
    return plz + ' ' + city;
  }

  changeSelectedFilterMode(side: Side) {
    this.selectedFilterMode = side;
    const noFilters = filter
      ? isNullOrUndefined(this.filters.bonuscard) &&
        isNullOrUndefined(this.filters.guestaccount) &&
        isNullOrUndefined(this.filters.onlineshop)
        ? true
        : false
      : false;
    this.filters = {
      guestaccount: side === Side.RIGHT ? false : undefined,
      bonuscard: undefined,
      onlineshop: undefined,
    };
    if (!noFilters || side === Side.RIGHT) {
      this.ds = new CustomerSearchDataSource(
        this.customerSearch.query,
        this.store,
        this.customerService,
        this.filters,
        this.ds.allHits,
        this.isScan
      );
    }
    this.detectChanges();
  }

  detectChanges() {
    setTimeout(() => {
      if (this.cdrf !== null && this.cdrf !== undefined && !(this.cdrf as ViewRef).destroyed) {
        this.cdrf.detectChanges();
      }
    }, 0);
  }
}
