package space.nstart.pcp.pcp_request_service.angular

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import space.nstart.pcp.pcp_request_service.configuration.CustomValidationException
import space.nstart.pcp.pcp_request_service.utils.UtcDateTimes
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AngularMotionCalculationRequestDTO
import java.net.URLDecoder
import java.nio.charset.StandardCharsets
import java.time.LocalDateTime
import java.time.format.DateTimeParseException

@RestController
@RequestMapping("/api/angular-motion")
class AngularMotionController(
    private val angularMotionService: AngularMotionService,
) {
    @GetMapping("/satellites")
    fun availableSatellites(
        @RequestParam(required = false) time: String?,
    ): List<AngularMotionSatelliteDTO> = angularMotionService.availableSatellites(parseTime(time, required = false))

    @GetMapping("/satellites/{satelliteId}/flight-line")
    fun flightLine(
        @PathVariable satelliteId: Long,
        @RequestParam time: String,
    ): List<AngularMotionFlightLinePointDTO> = angularMotionService.flightLine(
        satelliteId,
        parseTime(time, required = true) ?: throw CustomValidationException("Не задано время для построения трассы"),
    )

    @PostMapping("/calculate")
    fun calculate(@RequestBody request: AngularMotionCalculationRequestDTO): AngularMotionCalculationResultDTO =
        angularMotionService.calculate(request)

    private fun parseTime(value: String?, required: Boolean): LocalDateTime? {
        val raw = value?.trim().orEmpty()
        if (raw.isEmpty()) {
            if (required) throw CustomValidationException("Не задан параметр time")
            return null
        }
        val decoded = URLDecoder.decode(raw, StandardCharsets.UTF_8)
        return try {
            UtcDateTimes.parse(decoded)
        } catch (_: DateTimeParseException) {
            throw CustomValidationException(
                "Некорректный формат времени '$decoded'. Ожидается ISO-8601 UTC/offset, например 2026-06-17T06:28:27Z, или legacy UTC-naive yyyy-MM-dd'T'HH:mm:ss",
            )
        }
    }
}
