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

import { DeleteDropdownComponent } from '@libs/ui';

@Component({
  selector: 'app-take-now-cart-row',
  templateUrl: './take-now-cart-row.component.html',
  styleUrls: ['./take-now-cart-row.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TakeNowCartRowComponent 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);
  }

  _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 productService: ProductService,
    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;
      const options = this.item.quantity < 9 ? this.item.quantity : 9;

      this.deactivateTenPlus = options < 9;
    }
  }

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

  validateSelectedQuantity(): Observable<number> {
    return this.productService.getItemById(this.item.book.id).pipe(
      map((book) => (isNullOrUndefined(book.stockInfos[0]) ? 0 : book.stockInfos[0].inStock)),
      take(1),
      switchMap((productStock: number) => {
        return this.availabilityService.getStockInfo([this.item.branch.id], [this.item.book.id]).pipe(
          map((stockInfo) => {
            if (stockInfo) {
              const items = stockInfo.map((t) => t.inStock).reduce((q1, q2) => q1 + q2);
              if (items) {
                return items < 1000 ? items : 1000;
              }
              return 0;
            }
            return productStock;
          })
        );
      })
    );
  }

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