package space.nstart.pcp.pcp_mission_planing_service.service.catalog

import org.springframework.beans.factory.ObjectProvider
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.function.client.bodyToMono
import reactor.core.publisher.Mono
import space.nstart.pcp.pcp_types_lib.configuration.CustomErrorException
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDTO
import tools.jackson.databind.ObjectMapper

@Service
class SatelliteCatalogClient(webClientBuilderProvider: ObjectProvider<WebClient.Builder>) {
    private val webClientBuilder: WebClient.Builder = webClientBuilderProvider.ifAvailable ?: WebClient.builder()

    @Value("\${settings.satellite-catalog-service:pcp-satellite-catalog-service}")
    private val url: String = ""

    private fun client() = webClientBuilder.baseUrl(url).build()

    fun getSatellite(satelliteId: Long): SatelliteDTO =
        client()
            .get()
            .uri("/api/satellites/{satelliteId}", satelliteId)
            .retrieve()
            .onStatus({ status -> status.isError }) { response ->
                response.bodyToMono<String>()
                    .defaultIfEmpty("error")
                    .flatMap { body -> Mono.error(CustomErrorException(extractErrorMessage(body))) }
            }
            .bodyToMono(SatelliteDTO::class.java)
            .block()
            ?: throw CustomErrorException("Satellite $satelliteId not found in satellite-catalog-service")

    private fun extractErrorMessage(body: String): String {
        val text = body.trim()
        if (text.isEmpty()) return "error"

        return runCatching {
            val node = ObjectMapper().readTree(text)
            when {
                node.hasNonNull("error") -> node["error"].asText()
                node.hasNonNull("message") -> node["message"].asText()
                else -> text
            }
        }.getOrDefault(text)
    }
}
