package space.nstart.pcp.slots_service.controller

import org.springframework.stereotype.Controller
import org.springframework.ui.Model
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.ResponseBody
import org.springframework.web.bind.annotation.RestController
import space.nstart.pcp.pcp_types_lib.dto.ballistics.StationDTO
import space.nstart.pcp.slots_service.service.ComplexMissionService
import space.nstart.pcp.slots_service.service.SlotService
import space.nstart.pcp.slots_service.service.StationService

@Controller
class RvaPageController(
    private val complexMissionService: ComplexMissionService,
    private val stationService: StationService
) {

    @GetMapping("/rva")
    fun rvaPage(model: Model): String {
        model.addAttribute("satellites", complexMissionService.satellites().collectList().block() ?: emptyList<Any>())
        model.addAttribute("stations", stationService.stations().collectList().block() ?: emptyList<Any>())
        return "rva"
    }
}

@RestController
@RequestMapping("/api/rva")
class RvaRestController(
    private val slotService: SlotService
) {

    @PostMapping("/common/{satelliteId}/{duration}")
    @ResponseBody
    fun rvaCommon(
        @PathVariable satelliteId: Long,
        @PathVariable duration: Long,
        @RequestBody stations: List<StationDTO>
    ) = slotService.rvaCommon(satelliteId, duration, stations)

    @PostMapping("/merge/{satelliteId}/{duration}")
    @ResponseBody
    fun rvaMerge(
        @PathVariable satelliteId: Long,
        @PathVariable duration: Long,
        @RequestBody stations: List<StationDTO>
    ) = slotService.rvaMerge(satelliteId, duration, stations)

    @PostMapping("/merge-on-rev/{satelliteId}/{duration}")
    @ResponseBody
    fun rvaMergeOnRev(
        @PathVariable satelliteId: Long,
        @PathVariable duration: Long,
        @RequestBody stations: List<StationDTO>
    ) = slotService.rvaMergeOnRev(satelliteId, duration, stations)

    @PostMapping("/average/{satelliteId}/{duration}")
    @ResponseBody
    fun rvaAverage(
        @PathVariable satelliteId: Long,
        @PathVariable duration: Long,
        @RequestBody stations: List<StationDTO>
    ): List<RvaAverageDTO> {
        val days = duration.coerceAtLeast(1).toDouble()
        val zonesByStation = slotService.rvaCommon(satelliteId, duration, stations)
            .groupBy { it.stationId }

        return stations
            .sortedBy { it.number }
            .map { station ->
                val zones = zonesByStation[station.number.toLong()].orEmpty()
                val zoneCount = zones.size
                val totalDurationSec = zones.sumOf { it.duration }
                RvaAverageDTO(
                    ppiNumber = station.number.toLong(),
                    ppiLatitude = station.position.lat,
                    averageCount = zoneCount / days,
                    averageDurationSec = if (zoneCount == 0) 0.0 else totalDurationSec / zoneCount
                )
            }
    }
}

data class RvaAverageDTO(
    val ppiNumber: Long,
    val ppiLatitude: Double,
    val averageCount: Double,
    val averageDurationSec: Double
)
