import { Component, ChangeDetectionStrategy, OnDestroy } from '@angular/core';
import { DomainCheckoutService } from '@domain/checkout';
import { UiModalService } from '@ui/modal';
import { PrintModalComponent, PrintModalData } from '@modal/printer';
import { debounceTime, first, map, shareReplay, switchMap } from 'rxjs/operators';
import { CrmCustomerService } from '@domain/crm';
import { ActivatedRoute, Router } from '@angular/router';
import { DomainOmsService } from '@domain/oms';
import { DomainCatalogService } from '@domain/catalog';
import { DisplayOrderDTO, DisplayOrderItemDTO } from '@swagger/oms';
import { BreadcrumbService } from '@core/breadcrumb';
import { ApplicationService } from '@core/application';
import { DomainPrinterService } from '@domain/printer';
import { combineLatest, NEVER } from 'rxjs';

@Component({
  selector: 'page-checkout-summary',
  templateUrl: 'checkout-summary.component.html',
  styleUrls: ['checkout-summary.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CheckoutSummaryComponent implements OnDestroy {
  processId = Date.now();

  displayOrders$ = combineLatest([this.domainCheckoutService.getOrders(), this._route.params]).pipe(
    map(([orders, params]) => {
      let filteredOrders: DisplayOrderDTO[] = [];
      if (params?.orderIds) {
        const orderIds: String[] = params.orderIds.split(',');
        filteredOrders = orders.filter((order) => orderIds.find((id) => Number(id) === order.id));
      } else {
        return filteredOrders;
      }
      return filteredOrders?.map((order) => {
        return {
          ...order,
          items: [...order.items]?.sort((a, b) => a.product?.name.localeCompare(b.product?.name)),
        };
      });
    }),
    shareReplay()
  );

  totalItemCount$ = this.displayOrders$.pipe(
    map((displayOrders) =>
      displayOrders.reduce(
        (total, displayOrder) => total + displayOrder?.items?.reduce((subTotal, order) => subTotal + order?.quantity, 0),
        0
      )
    )
  );

  totalReadingPoints$ = this.displayOrders$.pipe(
    switchMap((displayOrders) => {
      const items = displayOrders
        .reduce<DisplayOrderItemDTO[]>((items, order) => [...items, ...order.items], [])
        .map((i) => {
          if (i?.product?.catalogProductNumber) {
            return {
              id: Number(i.product?.catalogProductNumber),
              quantity: i.quantity,
              price: i.price?.value?.value,
            };
          }
        })
        .filter((item) => item !== undefined);
      if (items.length !== 0) {
        return this.domainCatalogService
          .getPromotionPoints({ items })
          .pipe(map((response) => Object.values(response.result).reduce((sum, points) => sum + points, 0)));
      } else {
        return NEVER;
      }
    })
  );

  totalPrice$ = this.displayOrders$.pipe(
    map((displayOrders) =>
      displayOrders.reduce(
        (total, displayOrder) =>
          total + displayOrder?.items?.reduce((subTotal, order) => subTotal + order?.price?.value?.value * order.quantity, 0),
        0
      )
    )
  );

  totalPriceCurrency$ = this.displayOrders$.pipe(map((displayOrders) => displayOrders[0]?.items[0]?.price?.value?.currency));

  containsDeliveryOrder$ = this.displayOrders$.pipe(
    map(
      (displayOrders) =>
        displayOrders.filter((o) => ['Versand', 'B2B-Versand', 'DIG-Versand'].indexOf(o.features?.orderType) > -1)?.length > 0
    )
  );

  isB2BCustomer$ = this.displayOrders$.pipe(
    switchMap((o) =>
      this.customerService
        .getCustomers(o[0].buyerNumber, { take: 5 })
        .pipe(map((customers) => customers.result[0].features?.find((f) => f.enabled && f.key === 'b2b') != null))
    )
  );

  takeNowOrders$ = this.displayOrders$.pipe(
    map((displayOrders) => displayOrders.filter((o) => o.items.find((oi) => oi.features?.orderType === 'Rücklage') != null))
  );

  constructor(
    private domainCheckoutService: DomainCheckoutService,
    private customerService: CrmCustomerService,
    private domainCatalogService: DomainCatalogService,
    private router: Router,
    private _route: ActivatedRoute,
    private omsService: DomainOmsService,
    private uiModal: UiModalService,
    private breadcrumb: BreadcrumbService,
    public applicationService: ApplicationService,
    private domainPrinterService: DomainPrinterService
  ) {
    this.breadcrumb
      .getBreadcrumbsByKeyAndTags$(this.applicationService.activatedProcessId, ['checkout'])
      .pipe(first())
      .subscribe(async (crumbs) => {
        for await (const crumb of crumbs) {
          this.breadcrumb.removeBreadcrumb(crumb.id);
        }
        this.breadcrumb.addBreadcrumbIfNotExists({
          key: this.applicationService.activatedProcessId,
          name: 'Bestellbestätigung',
          path: `/kunde/${this.applicationService.activatedProcessId}/cart/summary/${this._route.snapshot.params.orderIds}`,
          tags: ['checkout', 'cart'],
          section: 'customer',
        });
      });
  }

  async ngOnDestroy() {
    const checkoutProcess = await this.applicationService
      .getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
      .pipe(first())
      .toPromise();

    // Wenn es keine Bestellabschluss Prozesse mehr gibt, werden alle Orders aus dem Store removed um die Performance zu verbessern
    if (!checkoutProcess) {
      this.domainCheckoutService.removeAllOrders();
    }
  }

  openPrintModal(id: number) {
    this.uiModal.open({
      content: PrintModalComponent,
      data: {
        printerType: 'Label',
        print: (printer) => this.domainPrinterService.printOrder({ orderIds: [id], printer }).toPromise(),
      } as PrintModalData,
      config: {
        panelClass: [],
        showScrollbarY: false,
      },
    });
  }

  async navigateToGoodsOut() {
    let takeNowOrders = await this.takeNowOrders$.pipe(first()).toPromise();
    if (takeNowOrders.length != 1) return;

    try {
      for (const takeNowOrder of takeNowOrders) {
        for (const orderItem of takeNowOrder.items.filter((item) => item.features?.orderType === 'Rücklage')) {
          await this.omsService
            .changeOrderStatus(takeNowOrder.id, orderItem.id, orderItem.subsetItems[0]?.id, {
              processingStatus: 128,
            })
            .toPromise();
        }
      }

      this.router.navigate(['/kunde', 'goods', 'out', 'details', 'order', takeNowOrders[0].orderNumber, 128]);
    } catch (e) {
      console.error(e);
    }
  }
}
