import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Select, Store } from '@ngxs/store';
import { Observable, Subject } from 'rxjs';
import { User, Address } from '../../../../core/models/user.model';
import { BookData } from '../../../../core/models/book-data.model';
import { takeUntil, take, filter, tap, distinctUntilChanged } from 'rxjs/operators';
import { SharedSelectors } from '../../../../core/store/selectors/shared.selectors';
import { PopBreadcrumbsBeforeCurrent, UpdateCurrentBreadcrumbName } from '../../../../core/store/actions/breadcrumb.actions';
import { DeleteCart, SetCartToProcess } from '../../../../core/store/actions/cart.actions';
import { ResetProcess, EmptyFinishedOrders } from '../../../../core/store/actions/process.actions';
import { shrinkTitleAnimation, shrinkSecondaryAnimation, shrinkMainCard } from '../cart-confirmation/shrink.animation';
import { OrderItem } from '../../../../core/models/order-item';
import { ProcessCartConfirmed } from '../../../../core/models/process-cart-confirmed.model';
import { PrinterService } from '../../../../core/services/printer.service';
import { isArrayOfMinLengthDefined, undefinedToEmptyStringOrValue } from '../../../../core/utils/app.utils';
import { PrinterSelectionComponent } from '../../../../components/printer-selection/printer-selection.component';
import { DeliveryType } from '../../../../core/models/delivery-option.model';
import { isNullOrUndefined } from 'util';

export interface OrderData {
  orderId: number;
  orderNumber: string;
  isDelivery: boolean;
  isDownload: boolean;
  items: OrderItem[];
  orderDate: string;
  targetBranchName: string;
  targetBranchAddress: string;
}

@Component({
  selector: 'app-cart-confirmation',
  templateUrl: './cart-confirmation.component.html',
  styleUrls: ['./cart-confirmation.component.scss'],
  animations: [shrinkTitleAnimation, shrinkSecondaryAnimation, shrinkMainCard],
})
export class CartConfirmationComponent implements OnInit, OnDestroy {
  @Select(SharedSelectors.getConfirmedCart) cartData$: Observable<ProcessCartConfirmed>;
  @Select(SharedSelectors.getFinishedOrderCustomer) customer$: Observable<User>;
  @ViewChild('printModal') printModal: PrinterSelectionComponent;

  destroy$ = new Subject();
  customer: User;
  deliveryAddress = '';
  books: BookData[] = [];
  currentNumberOfItems = 1;
  displayItemsNumber = 0;
  currentPrice = '';
  currentPoints = 0;
  booksTotalSum = 0;
  processId: number;
  expanded = true;
  targetBranchName = '';
  targetBranchAddress = '';
  isPickUpOnly = false;
  isTakeNowOnly = false;
  customerId: number;
  customerName = '';
  email = '';

  booksFromOrder: OrderItem[] = [];
  orderIds: string[] = [];
  title = 'Bestellbestätigung';
  orders: OrderData[] = [];
  failedItemsIds: { id: number; type: number }[] = [];
  printOrderId: number;
  loading = true;
  showOverviewTaxMessage = false;
  firstLoad = true;

  constructor(private store: Store, private printer: PrinterService) {}

  ngOnInit() {
    this.customer$
      .pipe(
        filter((data) => !isNullOrUndefined(data)),
        takeUntil(this.destroy$)
      )
      .subscribe((customerData: User) => {
        if (customerData) {
          this.processCustomerAddress(customerData);
        }
      });

    this.cartData$
      .pipe(
        takeUntil(this.destroy$),
        filter((data) => isArrayOfMinLengthDefined(data, 'cart', 0)),
        distinctUntilChanged((prev, curr) => prev && curr && JSON.stringify(prev) === JSON.stringify(curr))
      )
      .subscribe((processCart: ProcessCartConfirmed) => this.processOrder(processCart));
  }

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

  expand() {
    this.expanded = !this.expanded;
    this.store.dispatch(new UpdateCurrentBreadcrumbName(this.expanded ? this.title : 'Empfehlungen', 'shoppingCart'));
  }

  private processOrder(processCart: ProcessCartConfirmed) {
    this.orders = [];
    if (processCart) {
      this.failedItemsIds = processCart.failedItemIds;
      this.isPickUpOnly = processCart.isPickUpOnly;
      this.isTakeNowOnly = processCart.isTakeNowOnly;
      this.orderIds = processCart.orderIds;
      this.booksFromOrder = processCart.cart;
      this.displayItemsNumber = processCart.totalQuantity;
      this.currentPoints = processCart.promotionPoints;
      this.booksTotalSum = processCart.totalSum;

      this.orderIds.forEach((orderNumber: string) => {
        const order = this.booksFromOrder.find((itemInOrder: OrderItem) => itemInOrder.orderNumber === orderNumber);

        const isDownload = order.book.format === 'EB' || order.book.format === 'DL';
        this.orders.push({
          orderId: order.orderId,
          orderNumber: order.orderNumber,
          isDelivery: order.orderType === DeliveryType['ShippingAddress'] && !isDownload,
          isDownload: order.orderType === DeliveryType['Download'] || isDownload,
          items: this.booksFromOrder.filter((itemInOrder: OrderItem) => itemInOrder.orderNumber === orderNumber),
          orderDate: order.orderDate,
          targetBranchName: order.targetBranchName,
          targetBranchAddress: order.targetBranchAddress,
        });

        if (order.orderType === DeliveryType['ShippingAddress']) {
          this.showOverviewTaxMessage = true;
        }
      });

      this.loading = false;

      if (this.firstLoad) {
        this.cleanUpState(processCart.cartId);
        this.firstLoad = false;
      }
    }
  }

  private cleanUpState(cartId: number) {
    // this.store.dispatch(new PopBreadcrumbsBeforeCurrent('checkout'));
    this.store
      .dispatch(new DeleteCart(cartId))
      .toPromise()
      .then(() => {
        this.store.dispatch(new SetCartToProcess());
      });
    this.store.dispatch(new ResetProcess());
  }

  private processCustomerAddress(customer: User) {
    this.customerId = customer.id;
    this.customerName = `${customer.first_name} ${customer.last_name}`;
    this.email = customer.email;
    let delAddress = '';

    if (this.isAddressSet(customer.delivery_addres)) {
      // tslint:disable-next-line: max-line-length
      delAddress = `${undefinedToEmptyStringOrValue(customer.delivery_addres.street)} ${undefinedToEmptyStringOrValue(
        customer.delivery_addres.streetNo + ''
      )}, ${undefinedToEmptyStringOrValue(customer.delivery_addres.zip + '')} ${undefinedToEmptyStringOrValue(
        customer.delivery_addres.city
      )}`;
    }

    delAddress = delAddress ? delAddress : '';

    this.deliveryAddress = delAddress ? delAddress : '';

    this.customer = customer;
  }

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

  async print(printer: string) {
    const printResponse = await this.printer.printOrder([this.printOrderId], printer);

    if (!printResponse.error) {
      this.printModal.closeModal();
    } else {
      this.printModal.setError(printResponse.message);
    }
  }

  printerSelect(orderId: number) {
    this.printOrderId = orderId;
    this.printModal.openDialog();
  }
}
