package space.nstart.pcp.pcp_coverage_scheme_service.service

import org.junit.jupiter.api.Test
import space.nstart.pcp.pcp_coverage_scheme_service.client.CoverageBallisticsClient
import space.nstart.pcp.pcp_coverage_scheme_service.client.CoverageSatelliteClient
import space.nstart.pcp.pcp_coverage_scheme_service.configuration.CoverageSchemeProperties
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ExactTimePositionRequestDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.ObjViewRequestDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.PointViewParamDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.SquareViewParamDTO
import space.nstart.pcp.pcp_types_lib.dto.coverage.CoverageSchemeCalculateRequestDTO
import space.nstart.pcp.pcp_types_lib.dto.satellite.SatelliteInfoDTO
import java.time.LocalDateTime
import kotlin.test.assertEquals

class CoverageSchemeMultiContourTest {

    private val service = CoverageSchemeCalculationService(
        ballisticsClient = FakeBallisticsClient(),
        coverageSchemeBuilderService = CoverageSchemeBuilderService(FakeBallisticsClient(), FakeSatelliteClient(), GeometrySupport()),
        geometrySupport = GeometrySupport(),
        properties = CoverageSchemeProperties(flightLinePaddingSeconds = 0)
    )

    @Test
    fun `calculate splits multipolygon intersection into separate contours`() {
        val response = service.calculate(
            CoverageSchemeCalculateRequestDTO(
                polygonWkt = "MULTIPOLYGON (((195 0, 196 0, 196 2, 195 2, 195 0)), ((197 0, 198 0, 198 2, 197 2, 197 0)))",
                satelliteIds = listOf(11L),
                timeStart = LocalDateTime.of(2026, 4, 14, 9, 55),
                timeEnd = LocalDateTime.of(2026, 4, 14, 10, 10)
            )
        )

        assertEquals(1, response.observations.size)
        assertEquals(2, response.observations.first().intersectionContourWkts.size)
        assertEquals(1, response.coverageScheme.size)
    }

    private class FakeBallisticsClient : CoverageBallisticsClient {
        override fun mplSquare(req: ObjViewRequestDTO): List<SquareViewParamDTO> =
            listOf(
                SquareViewParamDTO(
                    noradId = 11L,
                    timeBegin = LocalDateTime.of(2026, 4, 14, 10, 0),
                    timeEnd = LocalDateTime.of(2026, 4, 14, 10, 5)
                )
            )

        override fun mplPoint(req: ObjViewRequestDTO): List<PointViewParamDTO> = emptyList()

        override fun flightLine(
            satelliteId: Long,
            timeStart: LocalDateTime,
            timeStop: LocalDateTime
        ): List<FlightLineDTO> = listOf(
            FlightLineDTO(
                time = LocalDateTime.of(2026, 4, 14, 10, 0),
                lat = 0.0,
                long = 196.5,
                latLeft = 0.0,
                longLeft = 195.5,
                latRight = 0.0,
                longRight = 197.5
            ),
            FlightLineDTO(
                time = LocalDateTime.of(2026, 4, 14, 10, 5),
                lat = 2.0,
                long = 196.5,
                latLeft = 2.0,
                longLeft = 195.5,
                latRight = 2.0,
                longRight = 197.5
            )
        )

        override fun exactTime(
            satelliteId: Long,
            request: ExactTimePositionRequestDTO
        ): List<OrbPointDTO> = listOf(
            OrbPointDTO(
                time = LocalDateTime.of(2026, 4, 14, 10, 0),
                revolution = 1L,
                vx = -401.529,
                vy = 1413.431,
                vz = 7547.696,
                x = -6603039.949,
                y = -1870023.148,
                z = 0.0
            ),
            OrbPointDTO(
                time = LocalDateTime.of(2026, 4, 14, 10, 1),
                revolution = 1L,
                vx = -420.0,
                vy = 1390.0,
                vz = 7540.0,
                x = -6595000.0,
                y = -1860000.0,
                z = 452000.0
            )
        )
    }

    private class FakeSatelliteClient : CoverageSatelliteClient {
        override fun satellite(satelliteId: Long): SatelliteInfoDTO =
            SatelliteInfoDTO(noradId = satelliteId, captureAngle = 1.5)
    }
}
