import { ChangeDetectionStrategy, Component } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore } from '@ngrx/component-store';
import { AvailabilityDTO2, OrderItemListItemDTO } from '@swagger/oms';
import { UiModalRef } from '@ui/modal';
import { BehaviorSubject, combineLatest } from 'rxjs';
import { catchError, map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { ReorderResult } from './reorder.result';

interface GoodsInListReorderModalState {
  orderItem: OrderItemListItemDTO;
  checkedAvailability: AvailabilityDTO2;
  takeAwayAvailabilityError: boolean;
  storeAvailabilityError: boolean;
  ctaDisabled: boolean;
  showReasons: boolean;
}

@Component({
  selector: 'modal-reorder',
  templateUrl: 'reorder.component.html',
  styleUrls: ['reorder.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ReorderModalComponent extends ComponentStore<GoodsInListReorderModalState> {
  readonly orderItem$ = this.select((s) => s.orderItem);
  get orderItem() {
    return this.get((s) => s.orderItem);
  }

  get checkedAvailability() {
    return this.get((s) => s.checkedAvailability);
  }
  set checkedAvailability(checkedAvailability: AvailabilityDTO2) {
    if (this.checkedAvailability !== checkedAvailability) {
      this.patchState({ checkedAvailability });
      this.checkedSupplier = this.checkedAvailability?.supplier;
    }
  }

  readonly checkedAvailability$ = this.select((s) => s.checkedAvailability);

  get ctaDisabled() {
    return this.get((s) => s.ctaDisabled);
  }
  set ctaDisabled(ctaDisabled: boolean) {
    if (this.ctaDisabled !== ctaDisabled) {
      this.patchState({ ctaDisabled: ctaDisabled });
    }
  }
  readonly ctaDisabled$ = this.select((s) => s.ctaDisabled);

  readonly reorderReasons$ = this._omsService.getReorderReasons();

  readonly storeAvailabilityError$ = this.select((s) => s.storeAvailabilityError).pipe(shareReplay());
  readonly takeAwayAvailabilityError$ = this.select((s) => s.takeAwayAvailabilityError).pipe(shareReplay());

  readonly ctaReorderDisabled$ = combineLatest([
    this.ctaDisabled$,
    this.storeAvailabilityError$,
    this.takeAwayAvailabilityError$,
    this.checkedAvailability$,
  ]).pipe(
    map(
      ([ctaDisabled, storeAvailabilityError, takeAwayAvailabilityError, checkedAvailability]) =>
        ctaDisabled || !checkedAvailability || (storeAvailabilityError && takeAwayAvailabilityError)
    )
  );

  readonly currentBranch$ = this.domainAvailabilityService.getCurrentBranch();

  readonly storeAvailabilities$ = combineLatest([this.orderItem$, this.currentBranch$]).pipe(
    switchMap(([item, branch]) =>
      this.domainAvailabilityService
        .getPickUpAvailabilities([
          {
            qty: item.quantity,
            ean: item.product.ean,
            itemId: item.product?.catalogProductNumber,
            shopId: branch.id,
            price: item.retailPrice,
          },
        ])
        .pipe(
          catchError(() => {
            this.patchState({ storeAvailabilityError: true });
            return [undefined];
          })
        )
    ),
    tap((availabilities) => (this.checkedAvailability = availabilities?.find((a) => a.preferred)))
  );

  readonly takeAwayAvailability$ = this.orderItem$.pipe(
    switchMap((item) =>
      this.domainAvailabilityService
        .getTakeAwayAvailabilityByEan({
          eans: [item.product.ean],
          quantity: item.quantity,
          price: item.retailPrice,
        })
        .pipe(
          catchError(() => {
            this.patchState({ takeAwayAvailabilityError: true });
            return [undefined];
          }),
          map((availability) => {
            return availability
              ? {
                  ...availability,
                  status: availability.availabilityType,
                  supplierId: availability.supplier.id,
                  supplier: 'F',
                  qty: availability.inStock,
                }
              : undefined;
          })
        )
    )
  );

  readonly availabilities$ = combineLatest([this.storeAvailabilities$, this.takeAwayAvailability$]).pipe(
    map(([storeAvailabilities, takeAwayAvailability]) => [...(storeAvailabilities ?? []), takeAwayAvailability])
  );

  showReasons$ = this.select((s) => s.showReasons);

  get showReasons() {
    return this.get((s) => s.showReasons);
  }

  showReasonError$ = new BehaviorSubject<boolean>(false);

  isChecked: boolean;
  checkedSupplier: string;
  storeAvailabilityError: boolean;
  takeAwayAvailabilityError: boolean;
  selectedReason: string;

  constructor(
    public modalRef: UiModalRef<ReorderResult, { item: OrderItemListItemDTO; showReasons: boolean }>,
    private domainAvailabilityService: DomainAvailabilityService,
    private _omsService: DomainOmsService
  ) {
    super({
      orderItem: modalRef.data?.item,
      checkedAvailability: undefined,
      storeAvailabilityError: false,
      takeAwayAvailabilityError: false,
      ctaDisabled: false,
      showReasons: modalRef.data?.showReasons,
    });
  }

  checked(event: string, availability: AvailabilityDTO2) {
    this.checkedAvailability = event ? availability : undefined;
  }

  reorder() {
    if (this.showReasons && !this.selectedReason) {
      this.showReasonError$.next(true);
      return;
    }

    if (this.checkedAvailability) {
      this.ctaDisabled = true;
      this.modalRef.close({
        item: this.orderItem,
        comment: this.selectedReason,
        availability: this.checkedAvailability,
        action: 'REORDER',
      });
    }
  }

  notAvailable() {
    this.ctaDisabled = true;
    this.modalRef.close({
      item: this.orderItem,
      action: 'NOTAVAILABLE',
    });
  }
}
