import { Injectable } from '@angular/core';
import { StockRequest, StockInfoDTO, ItemDTO, StockService } from '@swagger/cat';
import { AvailabilityRequestDTO, AvailabilityDTO, ResponseArgsOfIEnumerableOfAvailabilityDTO } from '@swagger/availability';
import { map, catchError } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
import { CheckoutType } from '../models/checkout-type.enum';
import { AvailabilityService } from '@swagger/availability';

@Injectable({
  providedIn: 'root',
})
export class ProductAvailabilityService {
  constructor(private availabilityService: AvailabilityService, private stockService: StockService) {}

  getStoreAvailability(
    item: ItemDTO,
    ean: string,
    branchNumber: number,
    quantity: number = 1
  ): Observable<{ branchId: number; type: CheckoutType; av: AvailabilityDTO[] }> {
    const price = item.catalogAvailability && item.catalogAvailability.price ? item.catalogAvailability.price : undefined;
    const params = [
      <AvailabilityRequestDTO>{
        itemId: item.id.toString(),
        ean: ean,
        shopId: branchNumber,
        qty: quantity,
        price: price,
      },
    ];
    return this.availabilityService.AvailabilityStoreAvailability(params).pipe(
      map((response) => {
        if (response.error) {
          console.error(response.message);
        }
        return { branchId: branchNumber, type: CheckoutType.store, av: response.result };
      })
    );
  }

  getShippingAvailability(
    item: ItemDTO,
    ean: string,
    branchNumber: number,
    quantity: number = 1
  ): Observable<{ branchId: number; type: CheckoutType; av: AvailabilityDTO[] }> {
    const price = item.catalogAvailability && item.catalogAvailability.price ? item.catalogAvailability.price : undefined;
    const params = [
      <AvailabilityRequestDTO>{
        itemId: item.id.toString(),
        ean: ean,
        qty: quantity,
        price: price,
      },
    ];
    return this.availabilityService.AvailabilityShippingAvailability(params).pipe(
      map((response) => {
        if (response.error) {
          console.error(response.message);
        }
        return { branchId: branchNumber, type: CheckoutType.delivery, av: response.result };
      })
    );
  }

  getStockInfo(branchIds: number[], itemIds: number[]): Observable<StockInfoDTO[]> {
    const params = <StockRequest>{
      branchIds,
      itemIds,
    };
    return this.stockService.StockInStock(params).pipe(
      map((response) => {
        if (response.error) {
          throw new Error(response.message);
        }
        return response.result;
      })
    );
  }

  getStoreAvailabilityWithCheck(
    item: ItemDTO,
    ean: string,
    branchNumber: number,
    quantity: number = 1
  ): Observable<{ branchId: number; type: CheckoutType; av: AvailabilityDTO[] } | { error: boolean; message: string; type: CheckoutType }> {
    const price = item.catalogAvailability && item.catalogAvailability.price ? item.catalogAvailability.price : undefined;
    const params = [
      <AvailabilityRequestDTO>{
        itemId: item.id.toString(),
        ean: ean,
        shopId: branchNumber,
        qty: quantity,
        price: price,
      },
    ];
    return this.availabilityService.AvailabilityStoreAvailability(params).pipe(
      catchError((error) => {
        return of({ error: error, message: error.message, type: CheckoutType.store });
      }),
      map((response) => {
        if (response.error) {
          console.error(response.message);
          return { error: response.error, message: response.message, type: CheckoutType.store };
        }
        const succesResp = response as ResponseArgsOfIEnumerableOfAvailabilityDTO;
        return { branchId: branchNumber, type: CheckoutType.store, av: succesResp.result };
      })
    );
  }

  getShippingAvailabilityWithCheck(
    item: ItemDTO,
    ean: string,
    branchNumber: number,
    quantity: number = 1
  ): Observable<{ branchId: number; type: CheckoutType; av: AvailabilityDTO[] } | { error: boolean; message: string; type: CheckoutType }> {
    const price = item.catalogAvailability && item.catalogAvailability.price ? item.catalogAvailability.price : undefined;
    const params = [
      <AvailabilityRequestDTO>{
        itemId: item.id.toString(),
        ean: ean,
        qty: quantity,
        price: price,
      },
    ];
    return this.availabilityService.AvailabilityShippingAvailability(params).pipe(
      catchError((error) => {
        return of({ error: error, message: error.message, type: CheckoutType.delivery });
      }),
      map((response) => {
        if (response.error) {
          console.error(response.message);
          return { error: response.error, message: response.message, type: CheckoutType.delivery };
        }
        const succesResp = response as ResponseArgsOfIEnumerableOfAvailabilityDTO;
        return { branchId: branchNumber, type: CheckoutType.delivery, av: succesResp.result };
      })
    );
  }
}
