package springfive.airline.airlineecommerce.domain.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import springfive.airline.airlineecommerce.domain.FlightSearch;
import springfive.airline.airlineecommerce.domain.booking.TotalBooked;
import springfive.airline.airlineecommerce.domain.flight.Flight;
import springfive.airline.airlineecommerce.infra.oauth.Credentials;

@Service
public class BookingService {

  private final WebClient webClient;

  private final String bookingsService;

  private final DiscoveryService discoveryService;

  private final TokenService tokenService;

  private final Credentials bookingsCredentials;

  public BookingService(WebClient webClient, DiscoveryService discoveryService,TokenService tokenService,
      @Value("${bookings.service}") String bookingsService,@Qualifier("bookingsCredentials") Credentials bookingsCredentials) {
    this.webClient = webClient;
    this.discoveryService = discoveryService;
    this.bookingsService = bookingsService;
    this.tokenService = tokenService;
    this.bookingsCredentials = bookingsCredentials;
  }

  @HystrixCommand(commandKey = "bookings-total",groupKey = "airline-bookings-total",commandProperties = {
      @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
      @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "10"),
      @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "800"),
      @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000")
  })
  public Mono<TotalBooked> totalBooked(@NonNull String flightId){
    return discoveryService.serviceAddressFor(this.bookingsService).next()
        .flatMap(address -> Mono
            .just(this.webClient.mutate().baseUrl(address + "/" + flightId +"/total").build().get()))
        .flatMap(requestHeadersUriSpec ->
            Flux.combineLatest(Flux.just(requestHeadersUriSpec),Flux.from(tokenService.token(this.bookingsCredentials)),(reqSpec, token) ->{
              reqSpec.header("Authorization","Bearer" + token.getToken());
              return reqSpec;
            })
                .next())
        .map(RequestHeadersSpec::retrieve)
        .flatMap(res -> res.bodyToMono(TotalBooked.class));
  }

}