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.LocalDateTime
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:00",
              "endDateTime": "2026-01-31T23:59:59",
              "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(LocalDateTime.of(2026, 1, 1, 0, 0, 0), request.beginDateTime)
        assertEquals(OpticsResultTypeDto.PANCHROMATIC, request.optics?.resultType)
        // Поле опционально: при отсутствии в payload — порог покрытия по умолчанию 100%.
        assertEquals(100.0, request.coverageRequiredPercent)
    }

    @Test
    fun `create request dto binds explicit coverage required percent`() {
        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:00",
              "endDateTime": "2026-01-31T23:59:59",
              "coverageRequiredPercent": 80.0,
              "optics": {
                "resultType": "PANCHROMATIC",
                "resolution": 1.0
              }
            }
            """.trimIndent(),
        )

        assertEquals(80.0, request.coverageRequiredPercent)
    }

    @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:00",
              "endDateTime": "2026-01-31T23:59:59",
              "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 = LocalDateTime.of(2026, 1, 1, 0, 0, 0),
                endDateTime = LocalDateTime.of(2026, 1, 31, 23, 59, 59),
                optics = OpticsParamsDto(
                    resultType = OpticsResultTypeDto.PANCHROMATIC,
                    resolution = 1.0,
                ),
            ),
        )

        val node = objectMapper.readTree(json)
        assertFalse(node.has("surveyType"), "surveyType should not be serialized")
    }
}
