package space.nstart.pcp.routepassportconsumer.service

import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import space.nstart.pcp.pcp_types_lib.dto.routes.RawGeoJsonGeometryDto
import space.nstart.pcp.routepassportconsumer.exception.RoutePassportContractException
import tools.jackson.databind.ObjectMapper
import tools.jackson.databind.json.JsonMapper
import tools.jackson.module.kotlin.KotlinModule

class RouteGeometryConverterTest {
    private val objectMapper: ObjectMapper = JsonMapper.builder()
        .addModule(KotlinModule.Builder().build())
        .build()

    private val converter = RouteGeometryConverter()

    @Test
    fun `should convert valid polygon to wkt`() {
        val geometry = geometry(
            type = "Polygon",
            coordinates = """[[[0, 0], [1, 0], [1, 1], [0, 0]]]""",
        )

        val wkt = converter.convert(geometry)

        assertTrue(wkt.startsWith("POLYGON"))
    }

    @Test
    fun `should convert valid multipolygon to wkt`() {
        val geometry = geometry(
            type = "MultiPolygon",
            coordinates = """[[[[0, 0], [1, 0], [1, 1], [0, 0]]]]""",
        )

        val wkt = converter.convert(geometry)

        assertTrue(wkt.startsWith("MULTIPOLYGON"))
    }

    @Test
    fun `should reject unsupported geometry type`() {
        val geometry = geometry(
            type = "Point",
            coordinates = """[0, 0]""",
        )

        assertThrows(RoutePassportContractException::class.java) {
            converter.convert(geometry)
        }
    }

    @Test
    fun `should reject malformed coordinates`() {
        val geometry = geometry(
            type = "Polygon",
            coordinates = """[[[0, 0], [1, 0], [1, 1]]]""",
        )

        assertThrows(RoutePassportContractException::class.java) {
            converter.convert(geometry)
        }
    }

    @Test
    fun `should reject non numeric coordinate values`() {
        val geometry = geometry(
            type = "Polygon",
            coordinates = """[[[0, 0], ["bad", 0], [1, 1], [0, 0]]]""",
        )

        assertThrows(RoutePassportContractException::class.java) {
            converter.convert(geometry)
        }
    }

    private fun geometry(
        type: String,
        coordinates: String,
    ): RawGeoJsonGeometryDto =
        RawGeoJsonGeometryDto(
            type = type,
            coordinates = objectMapper.readTree(coordinates),
        )
}
