import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { AvailabilityDTO, ShoppingCartItemDTO } from '@swagger/checkout';
import { combineLatest } from 'rxjs';
import { filter, map, shareReplay, withLatestFrom } from 'rxjs/operators';
import { PurchasingOptionsListModalStore } from '../purchasing-options-list-modal.store';

@Component({
  selector: 'page-purchasing-options-list-item',
  templateUrl: 'purchasing-options-list-item.component.html',
  styleUrls: ['purchasing-options-list-item.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PurchasingOptionsListItemComponent {
  @Input()
  item: ShoppingCartItemDTO;

  isSelected$ = this._store.selectedShoppingCartItems$.pipe(
    map((selectedShoppingCartItems) => !!selectedShoppingCartItems?.find((item) => item.id === this.item.id))
  );

  fetchingAvailabilities$ = combineLatest([
    this._store.takeAwayAvailabilities$,
    this._store.pickUpAvailabilities$,
    this._store.deliveryAvailabilities$,
    this._store.deliveryDigAvailabilities$,
    this._store.deliveryB2bAvailabilities$,
  ]).pipe(
    map(
      ([takeAway, pickUp, delivery, digDelivery, b2bDelivery]) =>
        !takeAway ||
        takeAway[this.item.product.catalogProductNumber] === true ||
        !pickUp ||
        pickUp[this.item.product.catalogProductNumber] === true ||
        !delivery ||
        delivery[this.item.product.catalogProductNumber] === true ||
        !digDelivery ||
        digDelivery[this.item.product.catalogProductNumber] === true ||
        !b2bDelivery ||
        b2bDelivery[this.item.product.catalogProductNumber] === true
    )
  );

  takeAwayAvailabilities$ = this._store.takeAwayAvailabilities$.pipe(
    map((takeAwayAvailabilities) => (!!takeAwayAvailabilities ? takeAwayAvailabilities[this.item.product?.catalogProductNumber] : [])),
    shareReplay()
  );

  pickUpAvailabilities$ = this._store.pickUpAvailabilities$.pipe(
    map((pickUpAvailabilities) => (!!pickUpAvailabilities ? pickUpAvailabilities[this.item.product?.catalogProductNumber] : [])),
    shareReplay()
  );

  deliveryAvailabilities$ = this._store.deliveryAvailabilities$.pipe(
    map((shippingAvailabilities) => (!!shippingAvailabilities ? shippingAvailabilities[this.item.product?.catalogProductNumber] : [])),
    shareReplay()
  );

  deliveryDigAvailabilities$ = this._store.deliveryDigAvailabilities$.pipe(
    map((shippingAvailabilities) => (!!shippingAvailabilities ? shippingAvailabilities[this.item.product?.catalogProductNumber] : [])),
    shareReplay()
  );

  deliveryB2bAvailabilities$ = this._store.deliveryB2bAvailabilities$.pipe(
    map((shippingAvailabilities) => (!!shippingAvailabilities ? shippingAvailabilities[this.item.product?.catalogProductNumber] : [])),
    shareReplay()
  );

  notAvailable$ = combineLatest([
    this.fetchingAvailabilities$,
    this.takeAwayAvailabilities$,
    this.pickUpAvailabilities$,
    this.deliveryAvailabilities$,
    this.deliveryDigAvailabilities$,
    this.deliveryB2bAvailabilities$,
  ]).pipe(
    map(
      ([fetching, takeAway, store, delivery, deliveryDig, deliveryB2b]) =>
        !fetching && !takeAway && !store && !delivery && !deliveryDig && !deliveryB2b
    )
  );

  showTooltip$ = this._store.selectedFilterOption$.pipe(
    withLatestFrom(this.deliveryAvailabilities$, this.deliveryDigAvailabilities$),
    map(([option, delivery, deliveryDig]) => {
      if (option === 'delivery') {
        const deliveryAvailability = (deliveryDig as AvailabilityDTO) || (delivery as AvailabilityDTO);

        const shippingPrice = deliveryAvailability?.price?.value?.value;
        const catalogPrice = this.item?.availability?.price?.value?.value;
        return catalogPrice < shippingPrice;
      }
      return false;
    })
  );

  price$ = combineLatest([this.fetchingAvailabilities$, this._store.selectedFilterOption$]).pipe(
    filter(([fetching]) => !fetching),
    withLatestFrom(
      this.takeAwayAvailabilities$,
      this.pickUpAvailabilities$,
      this.deliveryAvailabilities$,
      this.deliveryDigAvailabilities$,
      this.deliveryB2bAvailabilities$
    ),
    map(([[_, option], takeAway, pickUp, delivery, deliveryDig, deliveryB2b]) => {
      let availability;
      switch (option) {
        case 'take-away':
          availability = takeAway;
          break;
        case 'pick-up':
          availability = pickUp;
          break;
        case 'delivery':
          if (deliveryDig || delivery) {
            availability = deliveryDig || delivery;
          } else {
            availability = deliveryB2b;
            option = 'b2b-delivery';
          }
          break;
        default:
          return this.item.availability?.price;
      }

      return this._availabilityService.getPriceForAvailability(option, this.item.availability, availability);
    })
  );

  selectDisabled$ = this._store.selectedFilterOption$.pipe(map((selectedFilterOption) => !selectedFilterOption));

  selectVisible$ = combineLatest([this._store.canAdd$, this._store.selectedShoppingCartItems$]).pipe(
    withLatestFrom(
      this._store.selectedFilterOption$,
      this._store.deliveryAvailabilities$,
      this._store.deliveryDigAvailabilities$,
      this._store.deliveryB2bAvailabilities$,
      this._store.fetchingAvailabilities$
    ),
    map(([[canAdd, items], option, delivery, deliveryDig, deliveryB2b, fetching]) => {
      if (!option || fetching) {
        return false;
      }

      // Select immer sichtbar bei ausgewählten Items
      if (items?.find((item) => item.product?.catalogProductNumber === this.item.product?.catalogProductNumber)) {
        return true;
      }

      // Select nur anzeigen, wenn ein anderes ausgewähltes Item die gleiche Verfügbarkeit hat (B2B Versand z.B.)
      if (items?.length > 0 && option === 'delivery' && canAdd[this.item.product.catalogProductNumber]?.status < 2) {
        if (items.every((item) => delivery[item.product?.catalogProductNumber]) && delivery[this.item.product?.catalogProductNumber]) {
          return true;
        }

        if (
          items.every((item) => deliveryDig[item.product?.catalogProductNumber]) &&
          deliveryDig[this.item.product?.catalogProductNumber]
        ) {
          return true;
        }

        if (
          items.every((item) => deliveryB2b[item.product?.catalogProductNumber]) &&
          deliveryB2b[this.item.product?.catalogProductNumber]
        ) {
          return true;
        }
        return false;
      }

      return canAdd && canAdd[this.item.product.catalogProductNumber]?.status < 2;
    })
  );

  canAdd$ = this._store.canAdd$.pipe(
    filter((canAdd) => !!this.item && !!canAdd),
    map((canAdd) => canAdd[this.item.product.catalogProductNumber]?.message)
  );

  quantityRange$ = combineLatest([this._store.selectedFilterOption$, this.takeAwayAvailabilities$]).pipe(
    map(([option, availability]) => (option === 'take-away' ? (availability as AvailabilityDTO)?.inStock : 999))
  );

  constructor(private _store: PurchasingOptionsListModalStore, private _availabilityService: DomainAvailabilityService) {}

  selected(value: boolean) {
    this._store.selectShoppingCartItem([this.item], value);
  }

  changeQuantity(quantity: number) {
    if (quantity === 0) {
      this._store.removeShoppingCartItem(this.item);
    } else {
      this._store.updateItemQuantity({ itemId: this.item.id, quantity });
      this._store.loadAvailabilities({ items: [{ ...this.item, quantity }] });
    }
  }
}
