import { UpdateCartEntryQuantity } from './../../../../core/store/actions/cart-entry.actions';
import { CartReviewItem } from '../../pages/cart-review/cart-review.component';
import { ProductAvailabilityService } from '../../../../core/services/product-availability.service';
import { BranchSelectors } from '../../../../core/store/selectors/branch.selector';
import { map, tap, take } from 'rxjs/operators';
import {
  ChangeDetectionStrategy,
  Component,
  Input,
  OnInit,
  Output,
  EventEmitter,
  ChangeDetectorRef,
  ViewChild,
  ViewRef,
} from '@angular/core';
import { Store } from '@ngxs/store';
import { DeleteProductFromCart } from '../../../../core/store/actions/cart.actions';
import { of, Observable } from 'rxjs';
import { ChangeOrderTypeComponent } from '../change-order-type/change-order-type.component';

import { DeleteDropdownComponent } from '@libs/ui';
import { allowedAvailabilityStatusCodes } from 'apps/sales/src/app/core/utils/product.util';
import { DeliveryOption } from 'apps/sales/src/app/core/models/delivery-option.model';
import { isNullOrUndefined } from 'util';
import { AvailabilityDTO } from '@swagger/cat';

@Component({
  selector: 'app-delivery-cart-row',
  templateUrl: './delivery-cart-row.component.html',
  styleUrls: ['./delivery-cart-row.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DeliveryCartRowComponent implements OnInit {
  @ViewChild('changeOrder') changeOrderDialog: ChangeOrderTypeComponent;
  @ViewChild('ref') deleteDropdown: DeleteDropdownComponent;
  @Input() item: CartReviewItem;
  @Output() details = new EventEmitter();
  @Output() editAdress = new EventEmitter();
  @Output() quantity = new EventEmitter();
  @Output() modalVisible = new EventEmitter();
  @Output() delete = new EventEmitter();
  loadingBtn = false;
  deactivateTenPlus = false;

  _open = false;
  get open$() {
    return of(this._open);
  }

  get price(): number {
    if (this.item) {
      if (this.item.deliveryType === DeliveryOption.PICK_UP) {
        return this.item.pickUpPrice ? this.item.pickUpPrice : this.item.price;
      } else if (this.item.deliveryType === DeliveryOption.DELIVERY) {
        return this.item.deliveryPrice ? this.item.deliveryPrice : this.item.price;
      } else {
        return this.item.price;
      }
    }
    return 0;
  }

  _btnBlocked: boolean;
  @Input() set changeItemBtnBlocked(blockedItemId: number) {
    this._btnBlocked = blockedItemId && blockedItemId !== this.item.cartEntryId ? true : false;
  }

  quantityError;
  availableQuantity = Array(9)
    .fill(0)
    .map((_, i) => i + 1);

  constructor(private availabilityService: ProductAvailabilityService, private store: Store, private cdRef: ChangeDetectorRef) {}

  ngOnInit() {
    if (this.item.orderTypeChanged) {
      this.onQuantityChanged(this.item.quantity, true);
    }

    if (this.item.avaMessage) {
      this.quantityError = this.item.avaMessage;
      this.quantityError = this.item.avaMessage;
      const options = this.item.quantity < 9 ? this.item.quantity : 9;

      this.deactivateTenPlus = options < 9;
    }
  }

  onQuantityChanged(quantity: number, showError: boolean = false) {
    this.validateSelectedQuantity(quantity).subscribe((av) => {
      if (quantity > av.qty) {
        this.store.dispatch(
          new UpdateCartEntryQuantity(av.qty, this.item.cartEntryId, av.av, `Achtung, Maximal ${av.qty} Exemplare bestellbar.`)
        );
      } else {
        this.setQuantityError(null);
        this.store.dispatch(new UpdateCartEntryQuantity(quantity, this.item.cartEntryId, av.av));
      }
      if (this.deleteDropdown) {
        this.deleteDropdown.stopLoading();
      }
      this.detectChanges();
    });
  }

  validateSelectedQuantity(quantity: number): Observable<{ qty: number; av: AvailabilityDTO }> {
    const userBranchNumber = this.store.selectSnapshot(BranchSelectors.getUserBranch);
    const branchobj = this.store.selectSnapshot(BranchSelectors.getBranchesIterable).find((t) => t.branchNumber === userBranchNumber);
    const book = this.item.book;
    return this.availabilityService.getShippingAvailabilityWithCheck(book, book.product.ean, branchobj.id, quantity).pipe(
      map((response: any) => {
        if (response.error) {
          return { qty: 0, av: null };
        }
        if (response && response.av) {
          const preferedAv = response.av.find((t) => t && t.preferred === 1);
          let preferredQty = 0;
          if (preferedAv) {
            if (allowedAvailabilityStatusCodes(preferedAv.status)) {
              preferredQty = 999;
            }
          }
          if (preferredQty) {
            return { qty: preferredQty, av: preferedAv as AvailabilityDTO };
          }
          return { qty: 0, av: null };
        }
        return { qty: 0, av: null };
      }),
      take(1)
    );
  }

  setQuantityError(limit: number) {
    if (limit == null) {
      this.quantityError = null;
    } else {
      this.quantityError = `Achtung, Maximal ${limit} Exemplare bestellbar.`;
    }
  }

  deleteItem() {
    if (this.item) {
      this.delete.emit(this.item);
    }
  }

  openChangeOrderItemDialog() {
    if (!this._btnBlocked) {
      this._open = true;
      this.loadingBtn = true;
      this.modalVisible.emit(this.item.cartEntryId);
      this.detectChanges();
    }
  }

  modalReady() {
    this.loadingBtn = false;
    this.changeOrderDialog.openDialog();
  }

  modalClosed() {
    this.loadingBtn = false;
    this.modalVisible.emit(null);
    this._open = false;
    this.detectChanges();
  }

  // This method is needed because of the console error ViewDestroyedError: Attempt to use a destroyed view
  detectChanges() {
    setTimeout(() => {
      if (this.cdRef !== null && this.cdRef !== undefined && !(this.cdRef as ViewRef).destroyed) {
        this.cdRef.detectChanges();
      }
    }, 0);
  }
}
