package com.zibaldone.cats
package ch_01

import cats.data.EitherT
import cats.instances.future.*
import scala.concurrent.ExecutionContext.Implicits.global

import scala.concurrent.Future

// ex. request spike
final case class AsyncService(bandwidths: Map[String, Int]):

  opaque type AsyncResponse[T] = EitherT[Future, String, T] // Future[Either[String, T]]

  private def bandwidth(server: String): AsyncResponse[Int] = bandwidths.get(server) match
    case None        => EitherT.left { Future.successful("absent") }
    case Some(value) => EitherT.right { Future.successful(value) }

  private def canWithstandSurge(a: String, b: String): AsyncResponse[Boolean] =
    for
      aBandwidth <- bandwidth(a)
      bBandwidth <- bandwidth(b)
    yield aBandwidth + bBandwidth > 250

  def report(a: String, b: String): AsyncResponse[String] = canWithstandSurge(a, b).transform {
    case Left(rootCause) => Left(rootCause)
    case Right(true)     => Right("enough bandwidth")
    case Right(false)    => Left("not enough bandwidth")
  }