package space.nstart.pcp.slots_service.rest

import org.junit.jupiter.api.Test
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.verify
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.test.context.bean.override.mockito.MockitoBean
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.SlotDTO
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.SlotStatus
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteInfoDTO
import space.nstart.pcp.slots_service.service.EarthService
import space.nstart.pcp.slots_service.service.ComplexMissionService
import space.nstart.pcp.slots_service.service.SlotService
import space.nstart.pcp.slots_service.service.StationService
import tools.jackson.databind.ObjectMapper
import java.time.LocalDateTime
import kotlin.test.assertEquals
import kotlin.test.assertNotNull

@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    properties = [
        "spring.cloud.config.enabled=false",
        "spring.cloud.config.import-check.enabled=false",
        "spring.boot.admin.client.enabled=false"
    ]
)
class RequestRestControllerCoverageSunTest {

    @LocalServerPort
    private var port: Int = 0

    @MockitoBean
    private lateinit var earthService: EarthService

    @MockitoBean
    private lateinit var complexMissionService: ComplexMissionService

    @MockitoBean
    private lateinit var stationService: StationService

    @MockitoBean
    private lateinit var slotService: SlotService

    private val objectMapper = ObjectMapper()

    @Test
    fun `request coverage forwards sun parameter to slot service`() {
        val requestId = "req-1"
        val timeStart = LocalDateTime.of(2026, 4, 9, 10, 0)
        val timeStop = LocalDateTime.of(2026, 4, 9, 12, 0)
        val satellites = listOf(11L, 22L)
        val sun = -45.5

        doReturn(Flux.empty<SlotDTO>())
            .`when`(slotService)
            .slots(requestId, timeStart, timeStop, RevolutionSign.ASC, true, satellites, sun)

        val actual = WebClient.create("http://localhost:$port")
            .post()
            .uri(
                "/requests/req-with-covs/$requestId" +
                    "?tn=2026-04-09T10:00:00" +
                    "&tk=2026-04-09T12:00:00" +
                    "&sign=ASC" +
                    "&cov=true" +
                    "&sun=-45.5" +
                    "&satellites=11" +
                    "&satellites=22"
            )
            .retrieve()
            .bodyToMono(String::class.java)
            .map(objectMapper::readTree)
            .block()!!

        assertEquals(0, actual["slots"].size())
        verify(slotService).slots(requestId, timeStart, timeStop, RevolutionSign.ASC, true, satellites, sun)
    }

    @Test
    fun `request coverage uses satellite color for slot polygons`() {
        val requestId = "req-color"
        val timeStart = LocalDateTime.of(2026, 4, 9, 10, 0)
        val timeStop = LocalDateTime.of(2026, 4, 9, 12, 0)
        val slot = SlotDTO(
            cycle = 7,
            satelliteId = 11L,
            tn = timeStart,
            tk = timeStart.plusMinutes(10),
            roll = 12.5,
            contour = "POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))",
            revolution = 3,
            revolutionSign = RevolutionSign.ASC,
            slotNumber = 4,
            state = SlotStatus.BOOKED
        )

        doReturn(Flux.just(slot))
            .`when`(slotService)
            .slots(requestId, timeStart, timeStop, null, true, null, null)

        doReturn(
            Mono.just(
                SatelliteInfoDTO(
                    noradId = 11L,
                    name = "SAT-11",
                    red = 12,
                    green = 34,
                    blue = 56,
                    scanTLE = false
                )
            )
        )
            .`when`(complexMissionService)
            .satellite(11L)

        val actual = WebClient.create("http://localhost:$port")
            .post()
            .uri(
                "/requests/req-with-covs/$requestId" +
                    "?tn=2026-04-09T10:00:00" +
                    "&tk=2026-04-09T12:00:00" +
                    "&cov=true"
            )
            .retrieve()
            .bodyToMono(String::class.java)
            .map(objectMapper::readTree)
            .block()!!

        val slotEntity = actual["cov"]?.get(1)
        assertNotNull(slotEntity)
        assertEquals(listOf(12, 34, 56, 255), slotEntity["polygon"]["outlineColor"]["rgba"].map { it.asInt() })
        assertEquals(
            listOf(12, 34, 56, 150),
            slotEntity["polygon"]["material"]["solidColor"]["color"]["rgba"].map { it.asInt() }
        )
        verify(complexMissionService).satellite(11L)
    }
}
