import { Component, ChangeDetectionStrategy, Host, ChangeDetectorRef, Output, EventEmitter } from '@angular/core';
import { CrmCustomerService } from '@domain/crm';
import { DomainOmsService } from '@domain/oms';
import { KeyValueDTOOfStringAndString, OrderItemListItemDTO } from '@swagger/oms';
import { DateAdapter } from '@ui/common';
import { cloneDeep } from 'lodash';
import { BehaviorSubject, combineLatest, of } from 'rxjs';
import { catchError, filter, first, map, shareReplay, switchMap } from 'rxjs/operators';
import { SharedGoodsInOutOrderDetailsComponent } from '../goods-in-out-order-details.component';

@Component({
  selector: 'shared-goods-in-out-order-details-header',
  templateUrl: 'goods-in-out-order-details-header.component.html',
  styleUrls: ['goods-in-out-order-details-header.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SharedGoodsInOutOrderDetailsHeaderComponent {
  @Output()
  editClick = new EventEmitter<OrderItemListItemDTO>();

  minDateDatepicker = this.dateAdapter.addCalendarDays(this.dateAdapter.today(), -1);

  selectedOrderItemCount$ = this.host.selectedeOrderItemSubsetIds$.pipe(map((ids) => ids?.length ?? 0));

  orderItemCount$ = this.host.orderItems$.pipe(map((items) => items?.length ?? 0));

  orderItem$ = this.host.orderItems$.pipe(map((orderItems) => orderItems[0]));

  notificationsChannel$ = this.orderItem$.pipe(
    switchMap((oi) => {
      if (oi?.orderId) {
        return this.omsService.getNotifications(oi?.orderId).pipe(
          map((res) => res.selected),
          catchError(() => of(0))
        );
      }

      return of({ selected: 0 });
    })
  );

  changeDateLoader$ = new BehaviorSubject<boolean>(false);
  changeStatusLoader$ = new BehaviorSubject<boolean>(false);
  changeStatusDisabled$ = this.host.changeActionDisabled$;
  changeDateDisabled$ = this.changeStatusDisabled$;

  features$ = this.orderItem$.pipe(
    filter((orderItem) => !!orderItem),
    switchMap((orderItem) =>
      this.customerService.getCustomers(orderItem.buyerNumber).pipe(
        map((res) => res.result.find((c) => c.customerNumber === orderItem.buyerNumber)),
        map((customer) => customer?.features || []),
        map((features) => features.filter((f) => f.enabled && !!f.description))
      )
    ),
    shareReplay()
  );

  statusActions$ = this.orderItem$.pipe(map((orderItem) => orderItem?.actions?.filter((action) => action.enabled === false)));

  showMultiselect$ = combineLatest([this.host.orderItems$, this.host.fetchPartial$, this.host.itemsSelectable$]).pipe(
    map(([orderItems, fetchPartial, multiSelect]) => multiSelect && fetchPartial && orderItems?.length > 1)
  );

  constructor(
    @Host() private host: SharedGoodsInOutOrderDetailsComponent,
    private customerService: CrmCustomerService,
    private dateAdapter: DateAdapter,
    private omsService: DomainOmsService,
    private cdr: ChangeDetectorRef
  ) {}

  async updatePickupDeadline(deadline: Date) {
    this.changeDateLoader$.next(true);
    this.changeStatusDisabled$.next(true);
    const orderItems = cloneDeep(this.host.orderItems);
    for (const item of orderItems) {
      if (this.dateAdapter.compareDate(deadline, new Date(item.pickUpDeadline)) !== 0) {
        try {
          const res = await this.omsService
            .setPickUpDeadline(item.orderId, item.orderItemId, item.orderItemSubsetId, deadline?.toISOString())
            .pipe(first())
            .toPromise();
          item.pickUpDeadline = deadline.toISOString();
        } catch (error) {
          console.error(error);
        }
      }
    }
    this.changeDateLoader$.next(false);
    this.changeStatusDisabled$.next(false);
    this.host.updateOrderItems(orderItems);
  }

  async updateEstimatedShippingDate(estimatedShippingDate: Date) {
    this.changeDateLoader$.next(true);
    this.changeStatusDisabled$.next(true);
    const orderItems = cloneDeep(this.host.orderItems);
    for (const item of orderItems) {
      if (this.dateAdapter.compareDate(estimatedShippingDate, new Date(item.pickUpDeadline)) !== 0) {
        try {
          const res = await this.omsService
            .setEstimatedShippingDate(item.orderId, item.orderItemId, item.orderItemSubsetId, estimatedShippingDate?.toISOString())
            .pipe(first())
            .toPromise();
          item.estimatedShippingDate = res.estimatedShippingDate;
        } catch (error) {
          console.error(error);
        }
      }
    }
    this.changeDateLoader$.next(false);
    this.changeStatusDisabled$.next(false);
    this.host.updateOrderItems(orderItems);
  }

  async handleAction(action: KeyValueDTOOfStringAndString) {
    this.changeStatusLoader$.next(true);
    try {
      await this.host.handleAction(action);
    } catch (error) {
      console.error(error);
    }

    setTimeout(() => this.changeStatusLoader$.next(false), 1000);
    this.cdr.markForCheck();
  }

  selectAll() {
    this.host.selectAllOrderItems();
  }
}
