package org.nstart.dep265.requestservice.dto

import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import java.time.OffsetDateTime
import java.util.UUID
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse

class RequestApiDtoContractTest {
    private val objectMapper = jacksonObjectMapper()
        .registerModule(JavaTimeModule())
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)

    @Test
    fun `create request dto matches openapi input fields`() {
        val request = objectMapper.readValue<CreateRequestDto>(
            """
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Тест1",
              "geometry": "POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))",
              "importance": 10.0,
              "beginDateTime": "2026-01-01T00:00:00Z",
              "endDateTime": "2026-01-31T23:59:59Z",
              "kpp": [1, 2, 3],
              "highPriorityTransmit": false,
              "optics": {
                "resultType": "PANCHROMATIC",
                "resolution": 1.0,
                "sunAngleMin": 10.0,
                "sunAngleMax": 45.0,
                "clouds": 90.0
              }
            }
            """.trimIndent(),
        )

        assertEquals(UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"), request.id)
        assertEquals("Тест1", request.name)
        assertEquals(10.0, request.importance)
        assertEquals(OffsetDateTime.parse("2026-01-01T00:00:00Z"), request.beginDateTime)
        assertEquals(OpticsResultTypeDto.PANCHROMATIC, request.optics?.resultType)
    }

    @Test
    fun `create request dto rejects survey type as input field`() {
        val payloadWithSurveyType = """
            {
              "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
              "name": "Тест1",
              "geometry": "POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))",
              "importance": 10.0,
              "beginDateTime": "2026-01-01T00:00:00Z",
              "endDateTime": "2026-01-31T23:59:59Z",
              "surveyType": "OPTICS",
              "optics": {
                "resultType": "PANCHROMATIC",
                "resolution": 1.0
              }
            }
        """.trimIndent()

        assertFailsWith<Exception> {
            objectMapper.readValue<CreateRequestDto>(payloadWithSurveyType)
        }
    }

    @Test
    fun `create request serialization does not expose survey type`() {
        val json = objectMapper.writeValueAsString(
            CreateRequestDto(
                id = UUID.fromString("3fa85f64-5717-4562-b3fc-2c963f66afa6"),
                name = "Тест1",
                geometry = "POLYGON ((37.5 55.5, 37.7 55.5, 37.7 55.7, 37.5 55.7, 37.5 55.5))",
                importance = 10.0,
                beginDateTime = OffsetDateTime.parse("2026-01-01T00:00:00Z"),
                endDateTime = OffsetDateTime.parse("2026-01-31T23:59:59Z"),
                optics = OpticsParamsDto(
                    resultType = OpticsResultTypeDto.PANCHROMATIC,
                    resolution = 1.0,
                ),
            ),
        )

        assertFalse(json.contains("surveyType"))
        assertFalse(json.contains("app_type"))
        assertFalse(json.contains("appType"))
        assertFalse(json.contains("AppType"))
        assertFalse(json.contains("requestType"))
    }

    @Test
    fun `cells list response dto matches openapi fields`() {
        val json = objectMapper.writeValueAsString(
            CellsListResponseDto(
                items = listOf(
                    CellSummaryResponseDto(
                        cellNum = 42,
                        latitude = 55.0,
                        longitude = 37.0,
                        importance = 10.0,
                        contour = "POLYGON ((36 55, 37 55, 37 56, 36 56, 36 55))",
                    )
                ),
                page = 0,
                size = 50,
                totalItems = 1,
                totalPages = 1,
            )
        )

        assertEquals(
            setOf("items", "page", "size", "totalItems", "totalPages"),
            objectMapper.readTree(json).fieldNames().asSequence().toSet(),
        )
        assertEquals(
            setOf("cellNum", "latitude", "longitude", "importance", "contour"),
            objectMapper.readTree(json)["items"][0].fieldNames().asSequence().toSet(),
        )
    }
}
