import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { OrdersService } from '../../../../core/services/order.service';
import { Observable, Subject, of } from 'rxjs';
import { switchMap, filter, take, takeUntil, catchError, tap, map } from 'rxjs/operators';
import { OrderDTO, EntityDTOContainerOfOrderItemDTO, ReceiptListItemDTO, SupplierDTO } from '@swagger/oms';
import { OrderStatus, OrderType, OrderItemStatus } from '../../../../core/models/customer-order.model';
import { BranchSelectors } from '../../../../core/store/selectors/branch.selector';
import { BranchDTO } from '@swagger/crm';
import { Select, Store } from '@ngxs/store';
import { CustomerOrderItem } from '../../../../core/models/customer-order-item';
import { CustomerOrder } from '../../../../core/models/customer-order';
import { objectNotNull } from '../../../../core/utils/app.utils';
import { isNullOrUndefined } from 'util';
import { PrinterService } from 'apps/sales/src/app/core/services/printer.service';
import { PrinterSelectionComponent } from 'apps/sales/src/app/components/printer-selection/printer-selection.component';
import { CollectingShelfService } from 'apps/sales/src/app/core/services/collecting-shelf.service';
import { SupplierState } from 'apps/sales/src/app/core/store/state/supplier.state';
import { Features } from 'apps/sales/src/app/core/models/user.model';
import { CustomerSelectors } from 'apps/sales/src/app/core/store/selectors/customer.selectors';

@Component({
  selector: 'app-customer-order-detail',
  templateUrl: './customer-order-detail.component.html',
  styleUrls: ['./customer-order-detail.component.scss'],
})
export class CustomerOrderDetailComponent implements OnInit, OnDestroy {
  @ViewChild('printModal') printModal: PrinterSelectionComponent;
  @Select(BranchSelectors.getBranches) branches$: Observable<{
    [key: number]: BranchDTO;
  }>;
  @Select(SupplierState.getSuppliers) suppliers$: Observable<{
    [key: number]: SupplierDTO;
  }>;
  destroy$ = new Subject();
  order: CustomerOrder;
  orderDTO: OrderDTO;
  branches: { [key: number]: BranchDTO };
  suppliers: { [key: number]: SupplierDTO };
  takeNowItems = [];
  pickUpItems = [];
  deliveryItems = [];
  isDownload = false;
  customerId: number;
  isPayed = false;
  paymentDataDTO: ReceiptListItemDTO;
  onlineCustomer = false;
  guestCustomer = false;
  orderId: number;
  onlyOneItemAvailable: boolean;
  loadRows$ = new Subject<true>();

  constructor(
    private route: ActivatedRoute,
    private store: Store,
    private orderService: OrdersService,
    private printer: PrinterService,
    private shelfService: CollectingShelfService
  ) {}

  ngOnInit() {
    this.route.params
      .pipe(
        takeUntil(this.destroy$),
        switchMap((params) => {
          this.orderId = +params['orderId'];
          this.customerId = params['id'];
          this.initFeatureEffects(this.customerId);
          return this.branches$;
        }),
        filter((branchData) => objectNotNull(branchData)),
        switchMap((branches: { [key: number]: BranchDTO }) => {
          this.branches = branches;
          return of(undefined);
        }),
        switchMap(() => {
          return this.orderService.getOrder(this.orderId);
        }),
        tap((order: OrderDTO) => {
          this.suppliers = this.store.selectSnapshot(SupplierState.getSuppliers);
          this.processOrderItems(order);
        }),
        switchMap((order: OrderDTO) => {
          return this.getReceiptData(order.id);
        })
      )
      .subscribe(() => this.loadRows$.next(true));
  }

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

  initFeatureEffects(customerId: number) {
    const features: Features[] = this.store.selectSnapshot(CustomerSelectors.getCustomerFeatures)(customerId);
    if (features) {
      this.onlineCustomer = !isNullOrUndefined(features.find((feature) => feature.key === 'onlineshop'));
      this.guestCustomer = !isNullOrUndefined(features.find((feature) => feature.key === 'guestaccount'));
    }
  }

  processOrderItems(order: OrderDTO) {
    this.orderDTO = order;
    const orders: CustomerOrderItem[] = [];
    const branchName = order.orderType === 1 ? this.branches[order.targetBranch.id].name : '-';

    order.items.forEach((item: EntityDTOContainerOfOrderItemDTO) => {
      let ticketNumber = '';

      if (!item.data.subsetItems[0]) {
        return;
      }

      if (item.data.subsetItems[0].data.compartmentCode && item.data.subsetItems[0].data.compartmentInfo) {
        ticketNumber = `${item.data.subsetItems[0].data.compartmentCode} ${item.data.subsetItems[0].data.compartmentInfo}`;
      }

      orders.push({
        id: item.id,
        name: `${item.data.product.contributors} - ${item.data.product.name}`,
        price: item.data.grossPrice.value.value,
        currency: item.data.grossPrice.value.currency,
        status: OrderItemStatus[item.data.subsetItems[0].data.processingStatus],
        isbn: item.data.product.ean,
        note: item.data.subsetItems[0].data.specialComment ? item.data.subsetItems[0].data.specialComment : '-',
        orderType: item.data.subsetItems[0].data.supplier ? item.data.subsetItems[0].data.supplier.data.supplierNumber : '',
        fsk: '-',
        ssc:
          item.data.subsetItems[0].data.ssc && item.data.subsetItems[0].data.sscText
            ? item.data.subsetItems[0].data.ssc + ' - ' + item.data.subsetItems[0].data.sscText
            : '-',
        suplier:
          item.data.subsetItems[0].data.supplier &&
          item.data.subsetItems[0].data.supplier.data &&
          this.suppliers &&
          this.suppliers[item.data.subsetItems[0].data.supplier.data.id]
            ? this.suppliers[item.data.subsetItems[0].data.supplier.data.id].name
            : '-',
        ticketNumber: ticketNumber ? ticketNumber : '-',
        vat: item.data.grossPrice.vat.inPercent,
        quantity: item.data.subsetItems[0].data.quantity,
        estimatedDate: item.data.subsetItems[0].data.estimatedShippingDate ? item.data.subsetItems[0].data.estimatedShippingDate : null,
        shippingAddress: this.getAddress(order.buyer, true),
        billingAddress: this.getAddress(order.payer),
        preordered: item.data.subsetItems[0] && item.data.subsetItems[0].data ? item.data.subsetItems[0].data.isPrebooked : false,
        invoiceText: item.data.invoiceText,
      });
    });

    // Not delivery type of order
    if (order.orderType === 1) {
      this.takeNowItems = orders.filter((item: CustomerOrderItem) => item.orderType === 'F');
      this.pickUpItems = orders.filter((item: CustomerOrderItem) => item.orderType !== 'F');
    }

    this.isDownload = order.items && (order.items[0].data.product.format === 'EB' || order.items[0].data.product.format === 'DL');

    this.order = {
      id: order.id,
      orderNumber: order.orderNumber,
      customerName: `${order.buyer.firstName} ${order.buyer.lastName}`,
      status: OrderStatus[order.processingStatus],
      type: OrderType[order.clientChannel],
      date: order.orderDate,
      branch: branchName,
      items: orders,
      orderType: order.orderType,
    };

    this.onlyOneItemAvailable = this.takeNowItems.length + this.pickUpItems.length === 1 || this.order.items.length === 1;
  }

  getAddress(address: any, isShort: boolean = false): string {
    if (address && (address.address || (address.data && address.data.address))) {
      const addr = isShort ? address.address : address.data.address;
      const street = isNullOrUndefined(addr.street) ? '' : addr.street;
      const streetNumber = isNullOrUndefined(addr.streetNumber) ? '' : addr.streetNumber;
      const zipCode = isNullOrUndefined(addr.zipCode) ? '' : addr.zipCode;
      const city = isNullOrUndefined(addr.city) ? '' : addr.city;
      return `${street} ${streetNumber}, ${zipCode} ${city}`;
    }
    return '-';
  }

  async print(printer: string) {
    if (this.order && this.order.id) {
      const printResponse = await this.printer.printOrder([this.order.id], printer);
      if (!printResponse.error) {
        this.printModal.closeModal();
      } else {
        this.printModal.setError(printResponse.message);
      }
    }
  }

  printerSelect() {
    this.printModal.openDialog();
  }

  getReceiptData(orderId: number) {
    return this.shelfService.getReceipt(orderId).pipe(
      catchError((error) => {
        console.error(error);
        return of(undefined);
      }),
      tap((receiptList: ReceiptListItemDTO[]) => {
        if (receiptList && receiptList.length > 0) {
          const receipt = receiptList[0];
          this.paymentDataDTO = receipt;
          if (receipt.paidAt && !isNullOrUndefined(receipt.paidAt)) {
            this.isPayed = true;
          } else {
            this.isPayed = false;
          }
        } else {
          this.isPayed = false;
        }
      })
    );
  }
}
