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

@Component({
  selector: 'app-pick-up-cart',
  templateUrl: './pick-up-cart.component.html',
  styleUrls: ['./pick-up-cart.component.scss'],
  animations: [cartItem],
})
export class PickUpCartComponent implements OnInit, OnDestroy {
  @Select(SharedSelectors.getCart) cartData$: Observable<ProcessCart>;
  @Output() editItem = new EventEmitter<boolean>();
  pickUp$: Observable<CartReviewItem[]>;
  affiliates$: Observable<{ branches: { [id: number]: BranchInfoDTO }; items: { [id: number]: CartReviewItem[] } }>;
  customer: User;
  blockingItem: number;
  lastDeletedItemIndex = -1;
  destroy$ = new Subject();

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

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

    this.affiliates$ = this.pickUp$.pipe(
      takeUntil(this.destroy$),
      filter((c) => !isNullOrUndefined(c) && c.length > 0),
      map((carts) => {
        const groups = this.groupByBranch(carts);
        return groups;
      })
    );
  }

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

  branchItemTrackBy(index: number, item: BranchInfoDTO) {
    return item.id;
  }

  productItemTrackBy(index: number, item: CartReviewItem) {
    return item.id;
  }

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

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

  groupByBranch(cartItems: CartReviewItem[]) {
    const branches: { [id: number]: BranchInfoDTO } = {};
    const items = cartItems.reduce((rv, x) => {
      if (!!x.branch) {
        (rv[x.branch.id] = rv[x.branch.id] || []).push(x);
        branches[x.branch.id] = { ...x.branch };
      }
      return rv;
    }, {}) as { [id: number]: CartReviewItem[] };
    return { branches, items };
  }

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