import { Component, OnInit, ChangeDetectorRef, OnDestroy, Output, EventEmitter, Input, ViewRef } from '@angular/core';
import { Cart } from '../../../../core/models/cart.model';
import { DeliveryOption } from '../../../../core/models/delivery-option.model';
import {
  UpdateCustomerFormState,
  ChangeCurrentRoute,
  SetDetailsCustomer,
  RemoveSelectedItem,
} from '../../../../core/store/actions/process.actions';
import { CustomerFormState } from '../../../../core/models/process.model';
import { Store, Select } from '@ngxs/store';
import { Router } from '@angular/router';
import { Breadcrumb } from '../../../../core/models/breadcrumb.model';
import { AddBreadcrumb } from '../../../../core/store/actions/breadcrumb.actions';
import { SharedSelectors } from '../../../../core/store/selectors/shared.selectors';
import { Observable, Subject } from 'rxjs';
import { ProcessCart } from '../../../../core/models/process-cart.model';
import { map, filter, takeUntil } from 'rxjs/operators';
import { deliveryFilter, CartReviewItem, cartToCartReviewArray } from '../../pages/cart-review/cart-review.component';
import { Address } from '../../../../core/models/user.model';
import { isArrayMinLength } from '../../../../core/utils/app.utils';
import { DeleteProductFromCart } from 'apps/sales/src/app/core/store/actions/cart.actions';
import { cartItem } from 'apps/sales/src/app/shared/animations/cart-item.animation';

@Component({
  selector: 'app-delivery-cart',
  templateUrl: './delivery-cart.component.html',
  styleUrls: ['./delivery-cart.component.scss'],
  animations: [cartItem],
})
export class DeliveryCartComponent implements OnInit, OnDestroy {
  @Select(SharedSelectors.getCart) cartData$: Observable<ProcessCart>;
  @Output() editItem = new EventEmitter<boolean>();
  @Input() disableAddressChanging: boolean;
  delivery$: Observable<CartReviewItem[]>;
  deliveryAddress: string;
  customer: any;
  blockingItem: number;
  lastDeletedItemIndex = -1;
  destroy$ = new Subject();

  constructor(private store: Store, private router: Router, private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    this.delivery$ = this.cartData$.pipe(
      filter((c) => isArrayMinLength(c, 'cart', 0)),
      map((review) => review.cart),
      map(deliveryFilter(DeliveryOption.DELIVERY)),
      map((cart) => cartToCartReviewArray(cart))
    );

    this.cartData$
      .pipe(
        filter((cart) => !!cart),
        takeUntil(this.destroy$)
      )
      .subscribe((cart) => {
        if (!this.validateDeliveryAddress(cart)) {
          this.destroy$.next();
          return;
        }
        this.parseDeliveryAddress(cart);
      });
  }

  ngOnDestroy() {
    this.destroy$.next();
  }

  parseDeliveryAddress(cart: ProcessCart) {
    if (!cart.customer) {
      return null;
    }
    if (!this.validateDeliveryAddress(cart)) {
      this.destroy$.next();
      return;
    }
    const customer = cart.customer;
    if (customer.delivery_addres) {
      const { first_name, last_name, street, streetNo, zip, city } = customer.delivery_addres;
      this.deliveryAddress = `${first_name} ${last_name} | ${street} ${streetNo}, ${zip} ${city}`;
    }
    this.detectChanges();
  }

  redirectToBilling() {
    const cart = this.store.selectSnapshot(SharedSelectors.getCart);
    if (!cart.customer) {
      return null;
    }
    const customerId = cart.customer.id;
    if (customerId) {
      const currentRoute = '/customer/edit/' + customerId + '/delivery';

      const newBread: Breadcrumb = {
        name: 'Lieferadresse',
        path: currentRoute,
        queryParams: { cart: true, notEditable: true },
      };

      this.store.dispatch(new SetDetailsCustomer(customerId));
      this.store.dispatch(new ChangeCurrentRoute(currentRoute));
      this.store.dispatch(new AddBreadcrumb(newBread, 'shoppingCart'));
      this.router.navigate([currentRoute], {
        queryParams: { cart: true, notEditable: true },
      });
    }
  }

  productDetails(item) {
    if (item) {
      this.store.dispatch(
        new AddBreadcrumb(
          {
            name: item.product.name ? item.product.name.substring(0, 12) + (item.product.name.length > 12 ? '...' : '') : '',
            path: '/product/details/' + item.id,
          },
          'product'
        )
      );
      this.store.dispatch(new RemoveSelectedItem());
      this.store.dispatch(new ChangeCurrentRoute(`product/details/${item.id}`));
      this.router.navigate([`product/details/${item.id}`]);
    }
  }

  validateDeliveryAddress(processCart) {
    const deliveryExist = processCart.cart.some((item: Cart) => item.deliveryType === DeliveryOption.DELIVERY);
    const missingAddress =
      processCart.customer && (!this.isAddressSet(processCart.customer.delivery_addres) || !processCart.customer.email);

    if (deliveryExist && missingAddress) {
      this.store.dispatch(new UpdateCustomerFormState(CustomerFormState.MISSING_DELIVERY));
      const currentRoute = `customer/search/missing-data/${processCart.customer.id}`;
      this.store.dispatch(new ChangeCurrentRoute(currentRoute));
      this.router.navigate([currentRoute], { queryParams: { card: 'create' } });
      return false;
    }
    return true;
  }

  isAddressSet(deliveryAddress: Address) {
    const error =
      !deliveryAddress ||
      !deliveryAddress.street ||
      !deliveryAddress.streetNo ||
      !deliveryAddress.zip ||
      !deliveryAddress.country ||
      !deliveryAddress.city;
    return !error;
  }

  blockModal(blockItemId?: number) {
    if (!blockItemId) {
      this.blockingItem = null;
      this.editItem.emit(false);
    } else {
      this.editItem.emit(true);
      this.blockingItem = blockItemId;
    }
  }

  getDeleteAnimation(index: number) {
    const animation = index >= this.lastDeletedItemIndex && this.lastDeletedItemIndex !== -1 ? 'delete' : '';
    return animation;
  }

  deleteItem(item: CartReviewItem, index: number) {
    this.lastDeletedItemIndex = index;
    if (item) {
      this.store.dispatch(new DeleteProductFromCart(item.cartId, item.cartEntryId));
    }
  }

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