package space.nstart.pcp.complan.service

import com.sun.net.httpserver.HttpServer
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.springframework.test.util.ReflectionTestUtils
import java.net.InetSocketAddress
import java.net.URI
import java.time.LocalDateTime
import java.util.UUID
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNull

class RequestServiceClientTest {

    private var server: HttpServer? = null

    @AfterEach
    fun tearDown() {
        server?.stop(0)
    }

    @Test
    fun `getRequest calls v1 request endpoint and maps response to request item`() {
        val requestId = UUID.fromString("00000000-0000-0000-0000-000000000001")
        val requestedUris = mutableListOf<URI>()
        server = serverWithRequestResponse(requestedUris, requestId)

        val request = requestServiceClient().getRequest(requestId)!!

        assertEquals("/v1/requests/$requestId", requestedUris.single().path)
        assertFalse(requestedUris.any { uri -> uri.path.startsWith("/api/v1/requests") })
        assertEquals(requestId, request.id)
        assertEquals("Dynamic plan request", request.name)
        assertEquals("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))", request.geometry)
        assertEquals(LocalDateTime.of(2026, 1, 2, 3, 4, 5), request.intervalBegin)
        assertEquals(LocalDateTime.of(2026, 1, 3, 4, 5, 6), request.intervalEnd)
        assertEquals(2.5, request.resolution)
        assertEquals(7.5, request.importance)
    }

    @Test
    fun `getRequest returns null on not found like legacy client`() {
        val requestId = UUID.fromString("00000000-0000-0000-0000-000000000404")
        val requestedUris = mutableListOf<URI>()
        server = HttpServer.create(InetSocketAddress(0), 0).apply {
            createContext("/v1/requests") { exchange ->
                requestedUris += exchange.requestURI
                val responseBody = """{"code":"REQUEST_NOT_FOUND"}"""
                exchange.responseHeaders.add("Content-Type", "application/json")
                exchange.sendResponseHeaders(404, responseBody.toByteArray().size.toLong())
                exchange.responseBody.use { it.write(responseBody.toByteArray()) }
            }
            start()
        }

        val request = requestServiceClient().getRequest(requestId)

        assertNull(request)
        assertEquals("/v1/requests/$requestId", requestedUris.single().path)
        assertFalse(requestedUris.any { uri -> uri.path.startsWith("/api/v1/requests") })
    }

    private fun serverWithRequestResponse(
        requestedUris: MutableList<URI>,
        requestId: UUID,
        beginDateTime: String = "2026-01-02T03:04:05",
        endDateTime: String = "2026-01-03T04:05:06",
    ): HttpServer =
        HttpServer.create(InetSocketAddress(0), 0).apply {
            createContext("/v1/requests") { exchange ->
                requestedUris += exchange.requestURI
                val responseBody = """
                    {
                      "id": "$requestId",
                      "name": "Dynamic plan request",
                      "status": "ACTIVE",
                      "surveyType": "OPTICS",
                      "geometry": "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))",
                      "importance": 7.5,
                      "beginDateTime": "$beginDateTime",
                      "endDateTime": "$endDateTime",
                      "kpp": [1],
                      "highPriorityTransmit": false,
                      "optics": {
                        "resultType": "PANCHROMATIC",
                        "resolution": 2.5,
                        "sunAngleMin": 10.0,
                        "sunAngleMax": 90.0,
                        "clouds": 100.0
                      },
                      "rsa": null,
                      "coverage": {"currentPercent": 0.0},
                      "createdAt": "2026-01-01T00:00:00",
                      "updatedAt": "2026-01-01T00:00:00",
                      "deletedAt": null
                    }
                """.trimIndent()
                exchange.responseHeaders.add("Content-Type", "application/json")
                exchange.sendResponseHeaders(200, responseBody.toByteArray().size.toLong())
                exchange.responseBody.use { it.write(responseBody.toByteArray()) }
            }
            start()
        }

    private fun requestServiceClient(): RequestServiceClient {
        val client = RequestServiceClient()
        ReflectionTestUtils.setField(client, "requestServiceUrl", "http://localhost:${server!!.address.port}")
        ReflectionTestUtils.setField(client, "requestSelectionPath", "/v1/requests")
        return client
    }
}
