package space.nstart.pcp.pcp_coverage_scheme_service.client

import org.springframework.beans.factory.ObjectProvider
import org.springframework.http.client.reactive.ReactorClientHttpConnector
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import reactor.netty.http.client.HttpClient
import space.nstart.pcp.pcp_coverage_scheme_service.configuration.CoverageSchemeProperties
import space.nstart.pcp.pcp_coverage_scheme_service.configuration.CustomErrorException
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteDTO
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteInfoDTO
import java.time.Duration

@Service
class ComplexMissionService(
    webClientBuilderProvider: ObjectProvider<WebClient.Builder>,
    private val properties: CoverageSchemeProperties
) : CoverageSatelliteClient {

    private val webClientBuilder: WebClient.Builder = webClientBuilderProvider.ifAvailable ?: WebClient.builder()

    private fun client(): WebClient =
        webClientBuilder
            .baseUrl(properties.satelliteCatalogServiceUrl)
            .clientConnector(
                ReactorClientHttpConnector(
                    HttpClient.create().responseTimeout(Duration.ofSeconds(properties.webClientResponseTimeoutSeconds))
                )
            )
            .codecs { codecs -> codecs.defaultCodecs().maxInMemorySize(properties.webClientInMemorySizeMb * 1024 * 1024) }
            .build()

    override fun satellite(satelliteId: Long): SatelliteInfoDTO =
        client()
            .get()
            .uri("/api/satellites/{satelliteId}", satelliteId)
            .retrieve()
            .bodyToMono(SatelliteDTO::class.java)
            .map { satellite ->
                SatelliteInfoDTO(
                    noradId = satellite.id,
                    name = satellite.name,
                    red = satellite.visualization.red,
                    green = satellite.visualization.green,
                    blue = satellite.visualization.blue,
                    captureAngle = satellite.observationProfile?.captureAngle ?: 1.5,
                    scanTLE = satellite.scanTle,
                    maxSurveyDurationSeconds = satellite.observationProfile?.durationMaxSeconds,
                    mmiSeconds = satellite.observationProfile?.mmiSeconds,
                    code = satellite.code,
                    typeCode = satellite.typeCode,
                    active = satellite.active
                )
            }
            .onErrorMap { error ->
                CustomErrorException("Не удалось получить параметры КА $satelliteId: ${error.message}")
            }
            .block()
            ?: throw CustomErrorException("Не удалось получить параметры КА $satelliteId: пустой ответ satellite-catalog-service")
}
