import { ChangeDetectionStrategy, Component } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { ItemDTO } from '@swagger/cat';
import { BranchDTO } from '@swagger/checkout';
import { UiModalRef } from '@ui/modal';
import { combineLatest } from 'rxjs';
import { filter, map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { geoDistance } from '@utils/common';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'modal-availabilities',
  templateUrl: 'availabilities.component.html',
  styleUrls: ['availabilities.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ModalAvailabilitiesComponent {
  search$ = new BehaviorSubject('');
  branchesFetching$ = new BehaviorSubject(false);
  stockFetching$ = new BehaviorSubject(true);
  item = this.modalRef.data.item;
  itemId = this.modalRef.data.itemId || this.modalRef.data.item.id;
  userbranch$ = this.domainAvailabilityService.getCurrentBranch();
  branches$ = this.domainAvailabilityService.getBranches();

  filteredBranches$ = combineLatest([this.branches$, this.userbranch$, this.search$]).pipe(
    tap(() => this.branchesFetching$.next(true)),
    filter(([branches, _]) => branches && branches?.length > 0),
    map(([branches, userbranch, search]) =>
      branches
        .filter(
          (branch) => branch && branch?.isOnline && branch?.isShippingEnabled && branch?.isOrderingEnabled && branch.id !== userbranch.id
        )
        .filter((b) => b.name?.toLowerCase()?.indexOf(search?.toLowerCase()) > -1 || b.address?.zipCode.indexOf(search) > -1)
        .sort((a, b) =>
          this.branchSorterFn(
            a,
            b,
            branches.find((b) => b.id === userbranch.id)
          )
        )
        .splice(0, 15)
    ),
    tap(() => this.branchesFetching$.next(false))
  );

  inStock$ = this.filteredBranches$.pipe(
    tap(() => this.stockFetching$.next(true)),
    switchMap((branches) =>
      this.domainAvailabilityService.getTakeAwayAvailabilityByBranches({
        branchIds: branches.map((branch) => branch.id),
        itemId: this.itemId,
        price: this.item?.catalogAvailability?.price,
        quantity: 1,
      })
    ),
    tap(() => this.stockFetching$.next(false)),
    shareReplay()
  );

  constructor(
    private modalRef: UiModalRef<BranchDTO, { item: ItemDTO; itemId: number }>,
    private domainAvailabilityService: DomainAvailabilityService
  ) {}

  filter(query: string) {
    this.search$.next(query);
  }

  reserve(branch: BranchDTO) {
    this.modalRef.close(branch);
  }

  close() {
    this.modalRef.close();
  }

  private branchSorterFn(a: BranchDTO, b: BranchDTO, userBranch: BranchDTO) {
    return (
      geoDistance(userBranch?.address?.geoLocation, a?.address?.geoLocation) -
      geoDistance(userBranch?.address?.geoLocation, b?.address?.geoLocation)
    );
  }
}
