package space.nstart.pcp.complan.spacecraft

import org.locationtech.jts.geom.Coordinate
import space.nstart.pcp.pcp_types_lib.dto.ballistics.FlightLineDTO
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RevolutionSign
import java.time.LocalDateTime
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class SpaceCraftTest {

    @Test
    fun `spacecraft has default planning constraints`() {
        val spacecraft = SpaceCraft(56756)

        assertEquals(SCConstraints(), spacecraft.constraints)
    }

    @Test
    fun `create flight line selects full passes split by revolution`() {
        val spacecraft = SpaceCraft(56756)
        spacecraft.flightLine.addAll(
            listOf(
                point(RevolutionSign.ASC, 1, -70.0, 150.0),
                point(RevolutionSign.ASC, 1, 82.0, 20.0),
                point(RevolutionSign.DESC, 1, 82.0, 20.0),
                point(RevolutionSign.DESC, 1, 30.0, 5.0),
                point(RevolutionSign.DESC, 2, -82.0, 350.0),
                point(RevolutionSign.ASC, 2, -82.0, 350.0),
                point(RevolutionSign.ASC, 2, 30.0, 20.0),
                point(RevolutionSign.ASC, 2, 82.0, 50.0),
            )
        )

        val (desc, asc) = spacecraft.createFlightLine()

        assertTrue(desc.coordinates.minOf { it.y } <= -80.0)
        assertTrue(desc.coordinates.maxOf { it.y } >= 80.0)
        assertTrue(asc.coordinates.minOf { it.y } <= -80.0)
        assertTrue(asc.coordinates.maxOf { it.y } >= 80.0)
    }

    @Test
    fun `line correction unwraps longitude jumps in both directions`() {
        val spacecraft = SpaceCraft(56756)

        val corrected = spacecraft.lineCorrection(
            listOf(
                Coordinate(350.0, 0.0),
                Coordinate(10.0, 1.0),
                Coordinate(340.0, 2.0),
            )
        )

        assertTrue(corrected[1].x > 350.0)
        assertTrue(corrected[2].x < corrected[1].x)
        assertTrue(kotlin.math.abs(corrected[1].x - corrected[0].x) < 180.0)
        assertTrue(kotlin.math.abs(corrected[2].x - corrected[1].x) < 180.0)
    }

    private fun point(
        revSign: RevolutionSign,
        revolution: Long,
        lat: Double,
        long: Double
    ): FlightLineDTO =
        FlightLineDTO(
            time = LocalDateTime.of(2026, 4, 30, 0, 0),
            revolution = revolution,
            lat = lat,
            long = long,
            revSign = revSign
        )
}
