code

package site.daydream.colleen.json

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.assertThrows
import java.io.InputStream
import java.util.stream.Stream
import kotlin.reflect.javaType
import kotlin.reflect.typeOf
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

// ========================================================================
// Test Data Classes
// ========================================================================

data class SimpleUser(
    val id: Int,
    val name: String
)

data class UserWithNullable(
    val id: Int,
    val name: String,
    val email: String? = null,
    val age: Int? = null
)

data class UserWithDefaults(
    val id: Int,
    val name: String = "Unknown",
    val active: Boolean = true,
    val score: Double = 0.0
)

data class NestedUser(
    val id: Int,
    val name: String,
    val address: Address?
)

data class Address(
    val street: String,
    val city: String,
    val zipCode: String? = null
)

data class GenericContainer<T>(
    val value: T,
    val metadata: Map<String, String>? = null
)

data class ComplexGeneric<K, V>(
    val data: Map<K, List<V>>,
    val count: Int
)

// ========================================================================
// Helper Functions - Combining TypeRef and JsonMapper
// ========================================================================

// === Deserialization (JSON String -> Object) ===

/**
 * Deserialize using reified type (inline function with typeOf)
 */
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T : Any> fromJson(mapper: JsonMapper, data: String): T {
    return mapper.fromJsonString(data, typeOf<T>().javaType)
}

/**
 * Deserialize using TypeRef
 */
fun <T : Any> fromJson(mapper: JsonMapper, data: String, typeRef: TypeRef<T>): T {
    return mapper.fromJsonString(data, typeRef.type)
}

/**
 * Deserialize using Class
 */
fun <T : Any> fromJson(mapper: JsonMapper, data: String, clazz: Class<T>): T {
    return mapper.fromJsonString(data, clazz)
}

/**
 * Deserialize from InputStream using reified type
 */
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T : Any> fromJsonStream(mapper: JsonMapper, stream: InputStream): T {
    return mapper.fromJsonStream(stream, typeOf<T>().javaType)
}

/**
 * Deserialize from InputStream using TypeRef
 */
fun <T : Any> fromJsonStream(mapper: JsonMapper, stream: InputStream, typeRef: TypeRef<T>): T {
    return mapper.fromJsonStream(stream, typeRef.type)
}

// === Serialization (Object -> JSON String) ===

/**
 * Serialize using reified type
 */
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T : Any> toJson(mapper: JsonMapper, obj: T): String {
    return mapper.toJsonString(obj, typeOf<T>().javaType)
}

/**
 * Serialize using TypeRef
 */
fun <T : Any> toJson(mapper: JsonMapper, obj: T, typeRef: TypeRef<T>): String {
    return mapper.toJsonString(obj, typeRef.type)
}

/**
 * Serialize to InputStream using reified type
 */
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T : Any> toJsonStream(mapper: JsonMapper, obj: T): InputStream {
    return mapper.toJsonStream(obj, typeOf<T>().javaType)
}

/**
 * Serialize to InputStream using TypeRef
 */
fun <T : Any> toJsonStream(mapper: JsonMapper, obj: T, typeRef: TypeRef<T>): InputStream {
    return mapper.toJsonStream(obj, typeRef.type)
}

// === ConvertValue ===

/**
 * Convert value using reified type
 */
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T : Any> convertValue(mapper: JsonMapper, obj: Any): T {
    return mapper.convertValue(obj, typeOf<T>().javaType)
}

/**
 * Convert value using TypeRef
 */
fun <T : Any> convertValue(mapper: JsonMapper, obj: Any, typeRef: TypeRef<T>): T {
    return mapper.convertValue(obj, typeRef.type)
}

// ========================================================================
// Combined TypeRef and JsonMapper Tests
// ========================================================================

class TypeRefJsonMapperIntegrationTest {

    private lateinit var mapper: JsonMapper

    @BeforeEach
    fun setup() {
        mapper = ColleenJackson()
    }

    // ========================================================================
    // Reified Type Tests (inline + typeOf)
    // ========================================================================

    @Nested
    inner class ReifiedTypeTests {

        @Test
        fun `should deserialize simple object using reified type`() {
            // Arrange
            val json = """{"id":1,"name":"Alice"}"""

            // Act
            val user = fromJson<SimpleUser>(mapper, json)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should deserialize List using reified type`() {
            // Arrange
            val json = """[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]"""

            // Act
            val users = fromJson<List<SimpleUser>>(mapper, json)

            // Assert
            assertEquals(2, users.size)
            assertEquals("Alice", users[0].name)
            assertEquals("Bob", users[1].name)
        }

        @Test
        fun `should deserialize Map using reified type`() {
            // Arrange
            val json = """{"user1":{"id":1,"name":"Alice"},"user2":{"id":2,"name":"Bob"}}"""

            // Act
            val userMap = fromJson<Map<String, SimpleUser>>(mapper, json)

            // Assert
            assertEquals(2, userMap.size)
            assertEquals("Alice", userMap["user1"]?.name)
            assertEquals("Bob", userMap["user2"]?.name)
        }

        @Test
        fun `should deserialize nested generics using reified type`() {
            // Arrange
            val json = """{"value":{"id":1,"name":"Alice"},"metadata":{"key":"value"}}"""

            // Act
            val container = fromJson<GenericContainer<SimpleUser>>(mapper, json)

            // Assert
            assertEquals(1, container.value.id)
            assertEquals("Alice", container.value.name)
            assertEquals("value", container.metadata?.get("key"))
        }

        @Test
        fun `should serialize and deserialize using reified type`() {
            // Arrange
            val original = SimpleUser(1, "Alice")

            // Act
            val json = toJson(mapper, original)
            val deserialized = fromJson<SimpleUser>(mapper, json)

            // Assert
            assertEquals(original, deserialized)
        }

        @Test
        fun `should handle nullable fields with reified type`() {
            // Arrange
            val json = """{"id":1,"name":"Bob","email":"bob@example.com"}"""

            // Act
            val user = fromJson<UserWithNullable>(mapper, json)

            // Assert
            assertEquals(1, user.id)
            assertEquals("bob@example.com", user.email)
            assertEquals(null, user.age)
        }

        @Test
        fun `should handle default values with reified type`() {
            // Arrange
            val json = """{"id":1}"""

            // Act
            val user = fromJson<UserWithDefaults>(mapper, json)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Unknown", user.name)
            assertEquals(true, user.active)
        }
    }

    // ========================================================================
    // TypeRef Tests (anonymous object syntax)
    // ========================================================================

    @Nested
    inner class TypeRefTests {

        @Test
        fun `should deserialize simple object using TypeRef`() {
            // Arrange
            val json = """{"id":1,"name":"Alice"}"""
            val typeRef = TypeRef.of(SimpleUser::class.java)

            // Act
            val user = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should deserialize List using TypeRef factory method`() {
            // Arrange
            val json = """[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]"""
            val typeRef = TypeRef.listOf(SimpleUser::class.java)

            // Act
            val users = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, users.size)
            assertEquals("Alice", users[0].name)
            assertEquals("Bob", users[1].name)
        }

        @Test
        fun `should deserialize Set using TypeRef factory method`() {
            // Arrange
            val json = """["Alice","Bob","Charlie"]"""
            val typeRef = TypeRef.setOf(String::class.java)

            // Act
            val names = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(3, names.size)
            assertTrue(names.contains("Alice"))
            assertTrue(names.contains("Bob"))
        }

        @Test
        fun `should deserialize Map using TypeRef factory method`() {
            // Arrange
            val json = """{"user1":{"id":1,"name":"Alice"},"user2":{"id":2,"name":"Bob"}}"""
            val typeRef = TypeRef.mapOf(String::class.java, SimpleUser::class.java)

            // Act
            val userMap = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, userMap.size)
            assertEquals("Alice", userMap["user1"]?.name)
            assertEquals("Bob", userMap["user2"]?.name)
        }

        @Test
        fun `should deserialize nested List using anonymous TypeRef`() {
            // Arrange
            val json = """[["a","b"],["c","d"],["e","f"]]"""
            val typeRef = object : TypeRef<List<List<String>>>() {}

            // Act
            val nestedList = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(3, nestedList.size)
            assertEquals(2, nestedList[0].size)
            assertEquals("a", nestedList[0][0])
            assertEquals("f", nestedList[2][1])
        }

        @Test
        fun `should deserialize Map with List values using anonymous TypeRef`() {
            // Arrange
            val json =
                """{"team1":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}],"team2":[{"id":3,"name":"Charlie"}]}"""
            val typeRef = object : TypeRef<Map<String, List<SimpleUser>>>() {}

            // Act
            val teams = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, teams.size)
            assertEquals(2, teams["team1"]?.size)
            assertEquals("Alice", teams["team1"]?.get(0)?.name)
            assertEquals(1, teams["team2"]?.size)
        }

        @Test
        fun `should deserialize generic container using anonymous TypeRef`() {
            // Arrange
            val json = """{"value":{"id":1,"name":"Alice"},"metadata":{"version":"1.0"}}"""
            val typeRef = object : TypeRef<GenericContainer<SimpleUser>>() {}

            // Act
            val container = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(1, container.value.id)
            assertEquals("Alice", container.value.name)
            assertEquals("1.0", container.metadata?.get("version"))
        }

        @Test
        fun `should deserialize complex nested generic using anonymous TypeRef`() {
            // Arrange
            val json = """{"data":{"group1":[{"id":1,"name":"Alice"}],"group2":[{"id":2,"name":"Bob"}]},"count":2}"""
            val typeRef = object : TypeRef<ComplexGeneric<String, SimpleUser>>() {}

            // Act
            val complex = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, complex.count)
            assertEquals(1, complex.data["group1"]?.size)
            assertEquals("Alice", complex.data["group1"]?.get(0)?.name)
        }

        @Test
        fun `should deserialize List of Maps using anonymous TypeRef`() {
            // Arrange
            val json = """[{"key1":"value1"},{"key2":"value2"}]"""
            val typeRef = object : TypeRef<List<Map<String, String>>>() {}

            // Act
            val listOfMaps = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, listOfMaps.size)
            assertEquals("value1", listOfMaps[0]["key1"])
            assertEquals("value2", listOfMaps[1]["key2"])
        }

        @Test
        fun `should deserialize Map of Lists of Maps using anonymous TypeRef`() {
            // Arrange
            val json = """{"group1":[{"id":1},{"id":2}],"group2":[{"id":3}]}"""
            val typeRef = object : TypeRef<Map<String, List<Map<String, Int>>>>() {}

            // Act
            val complexMap = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(2, complexMap.size)
            assertEquals(2, complexMap["group1"]?.size)
            assertEquals(1, complexMap["group1"]?.get(0)?.get("id"))
        }
    }

    // ========================================================================
    // Class-based Tests
    // ========================================================================

    @Nested
    inner class ClassBasedTests {

        @Test
        fun `should deserialize using Class parameter`() {
            // Arrange
            val json = """{"id":1,"name":"Alice"}"""

            // Act
            val user = fromJson(mapper, json, SimpleUser::class.java)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should serialize and deserialize using Class parameter`() {
            // Arrange
            val original = SimpleUser(1, "Alice")
            val json = toJson(mapper, original)

            // Act
            val deserialized = fromJson(mapper, json, SimpleUser::class.java)

            // Assert
            assertEquals(original, deserialized)
        }
    }

    // ========================================================================
    // Stream Tests with TypeRef
    // ========================================================================

    @Nested
    inner class StreamTests {

        @Test
        fun `should deserialize from InputStream using reified type`() {
            // Arrange
            val json = """{"id":1,"name":"Alice"}"""
            val stream = json.byteInputStream()

            // Act
            val user = fromJsonStream<SimpleUser>(mapper, stream)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should deserialize from InputStream using TypeRef`() {
            // Arrange
            val json = """[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]"""
            val stream = json.byteInputStream()
            val typeRef = TypeRef.listOf(SimpleUser::class.java)

            // Act
            val users = fromJsonStream(mapper, stream, typeRef)

            // Assert
            assertEquals(2, users.size)
            assertEquals("Alice", users[0].name)
        }

        @Test
        fun `should serialize to InputStream and deserialize using reified type`() {
            // Arrange
            val original = SimpleUser(1, "Alice")

            // Act
            val stream = toJsonStream(mapper, original)
            val deserialized = fromJsonStream<SimpleUser>(mapper, stream)

            // Assert
            assertEquals(original, deserialized)
        }

        @Test
        fun `should handle complex generics through stream using reified type`() {
            // Arrange
            val original = GenericContainer(
                value = SimpleUser(1, "Alice"),
                metadata = mapOf("version" to "1.0")
            )

            // Act
            val stream = toJsonStream(mapper, original)
            val deserialized = fromJsonStream<GenericContainer<SimpleUser>>(mapper, stream)

            // Assert
            assertEquals(original, deserialized)
        }
    }

    // ========================================================================
    // Comparison Tests - Different Type Specification Methods
    // ========================================================================

    @Nested
    inner class ComparisonTests {

        @Test
        fun `all three methods should produce same result for simple type`() {
            // Arrange
            val json = """{"id":1,"name":"Alice"}"""

            // Act
            val result1 = fromJson<SimpleUser>(mapper, json)
            val result2 = fromJson(mapper, json, TypeRef.of(SimpleUser::class.java))
            val result3 = fromJson(mapper, json, SimpleUser::class.java)

            // Assert
            assertEquals(result1, result2)
            assertEquals(result2, result3)
        }

        @Test
        fun `reified and TypeRef should produce same result for List`() {
            // Arrange
            val json = """[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]"""

            // Act
            val result1 = fromJson<List<SimpleUser>>(mapper, json)
            val result2 = fromJson(mapper, json, TypeRef.listOf(SimpleUser::class.java))

            // Assert
            assertEquals(result1, result2)
        }

        @Test
        fun `reified and TypeRef should produce same result for Map`() {
            // Arrange
            val json = """{"user1":{"id":1,"name":"Alice"}}"""

            // Act
            val result1 = fromJson<Map<String, SimpleUser>>(mapper, json)
            val result2 = fromJson(mapper, json, TypeRef.mapOf(String::class.java, SimpleUser::class.java))

            // Assert
            assertEquals(result1, result2)
        }

        @Test
        fun `reified and anonymous TypeRef should produce same result for nested generics`() {
            // Arrange
            val json = """{"value":{"id":1,"name":"Alice"},"metadata":{"key":"value"}}"""

            // Act
            val result1 = fromJson<GenericContainer<SimpleUser>>(mapper, json)
            val result2 = fromJson(mapper, json, object : TypeRef<GenericContainer<SimpleUser>>() {})

            // Assert
            assertEquals(result1, result2)
        }
    }

    // ========================================================================
    // ConvertValue Tests with TypeRef
    // ========================================================================

    @Nested
    inner class ConvertValueTests {

        @Test
        fun `should convert Map to object using reified type`() {
            // Arrange
            val map = mapOf("id" to 1, "name" to "Alice")

            // Act
            val user = convertValue<SimpleUser>(mapper, map)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should convert Map to object using TypeRef`() {
            // Arrange
            val map = mapOf("id" to 1, "name" to "Alice")
            val typeRef = TypeRef.of(SimpleUser::class.java)

            // Act
            val user = convertValue(mapper, map, typeRef)

            // Assert
            assertEquals(1, user.id)
            assertEquals("Alice", user.name)
        }

        @Test
        fun `should convert object to Map using reified type`() {
            // Arrange
            val user = SimpleUser(1, "Alice")

            // Act
            val map = convertValue<Map<String, Any>>(mapper, user)

            // Assert
            assertEquals(1, map["id"])
            assertEquals("Alice", map["name"])
        }

        @Test
        fun `should convert List of Maps to List of objects using reified type`() {
            // Arrange
            val maps = listOf(
                mapOf("id" to 1, "name" to "Alice"),
                mapOf("id" to 2, "name" to "Bob")
            )

            // Act
            val users = convertValue<List<SimpleUser>>(mapper, maps)

            // Assert
            assertEquals(2, users.size)
            assertEquals("Alice", users[0].name)
            assertEquals("Bob", users[1].name)
        }

        @Test
        fun `should convert List of Maps to List of objects using TypeRef`() {
            // Arrange
            val maps = listOf(
                mapOf("id" to 1, "name" to "Alice"),
                mapOf("id" to 2, "name" to "Bob")
            )
            val typeRef = TypeRef.listOf(SimpleUser::class.java)

            // Act
            val users = convertValue(mapper, maps, typeRef)

            // Assert
            assertEquals(2, users.size)
            assertEquals("Alice", users[0].name)
        }

        @Test
        fun `should convert nested Map to nested object using anonymous TypeRef`() {
            // Arrange
            val map = mapOf(
                "id" to 1,
                "name" to "Charlie",
                "address" to mapOf(
                    "street" to "123 Main St",
                    "city" to "Springfield",
                    "zipCode" to "12345"
                )
            )
            val typeRef = TypeRef.of(NestedUser::class.java)

            // Act
            val user = convertValue(mapper, map, typeRef)

            // Assert
            assertEquals(1, user.id)
            assertNotNull(user.address)
            assertEquals("123 Main St", user.address?.street)
        }

        @Test
        fun `should convert Map with generic container using anonymous TypeRef`() {
            // Arrange
            val map = mapOf(
                "value" to mapOf("id" to 1, "name" to "Alice"),
                "metadata" to mapOf("version" to "1.0")
            )
            val typeRef = object : TypeRef<GenericContainer<SimpleUser>>() {}

            // Act
            val container = convertValue(mapper, map, typeRef)

            // Assert
            assertEquals(1, container.value.id)
            assertEquals("1.0", container.metadata?.get("version"))
        }

        @Test
        fun `should convert complex nested structures using anonymous TypeRef`() {
            // Arrange
            val map = mapOf(
                "team1" to listOf(
                    mapOf("id" to 1, "name" to "Alice"),
                    mapOf("id" to 2, "name" to "Bob")
                ),
                "team2" to listOf(
                    mapOf("id" to 3, "name" to "Charlie")
                )
            )
            val typeRef = object : TypeRef<Map<String, List<SimpleUser>>>() {}

            // Act
            val teams = convertValue(mapper, map, typeRef)

            // Assert
            assertEquals(2, teams.size)
            assertEquals(2, teams["team1"]?.size)
            assertEquals("Alice", teams["team1"]?.get(0)?.name)
        }

        @Test
        fun `should handle nullable fields in conversion using reified type`() {
            // Arrange
            val map = mapOf("id" to 1, "name" to "Bob", "email" to "bob@example.com")

            // Act
            val user = convertValue<UserWithNullable>(mapper, map)

            // Assert
            assertEquals("bob@example.com", user.email)
            assertEquals(null, user.age)
        }

        @Test
        fun `should convert between different collection types using TypeRef`() {
            // Arrange
            val list = listOf("Alice", "Bob", "Charlie")
            val typeRef = TypeRef.setOf(String::class.java)

            // Act
            val set = convertValue(mapper, list, typeRef)

            // Assert
            assertEquals(3, set.size)
            assertTrue(set.contains("Alice"))
        }

        @Test
        fun `should chain convertValue operations with different TypeRefs`() {
            // Arrange
            val user = SimpleUser(1, "Alice")

            // Act - Convert to Map then back to object
            val map = convertValue<Map<String, Any>>(mapper, user)
            val typeRef = TypeRef.of(SimpleUser::class.java)
            val converted = convertValue(mapper, map, typeRef)

            // Assert
            assertEquals(user, converted)
        }
    }

    // ========================================================================
    // WriteToOutputStream Tests with TypeRef
    // ========================================================================

    @Nested
    inner class WriteToOutputStreamTests {

        @Test
        fun `should write Stream of simple objects to OutputStream`() {
            // Arrange
            val users = Stream.of(
                SimpleUser(1, "Alice"),
                SimpleUser(2, "Bob"),
                SimpleUser(3, "Charlie")
            )
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(users, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.startsWith("["))
            assertTrue(json.endsWith("]"))
            assertTrue(json.contains("\"name\":\"Alice\""))
            assertTrue(json.contains("\"name\":\"Bob\""))
            assertTrue(json.contains("\"name\":\"Charlie\""))
        }

        @Test
        fun `should write Stream of objects with nullable fields to OutputStream`() {
            // Arrange
            val users = Stream.of(
                UserWithNullable(1, "Alice", "alice@example.com", null),
                UserWithNullable(2, "Bob", null, 25)
            )
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(users, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.contains("\"email\":\"alice@example.com\""))
            assertTrue(json.contains("\"age\":25"))
        }

        @Test
        fun `should write Stream of nested objects to OutputStream`() {
            // Arrange
            val users = Stream.of(
                NestedUser(1, "Alice", Address("123 Main St", "Springfield", "12345")),
                NestedUser(2, "Bob", null)
            )
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(users, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.contains("\"address\""))
            assertTrue(json.contains("\"street\":\"123 Main St\""))
        }

        @Test
        fun `should write empty Stream to OutputStream`() {
            // Arrange
            val users = Stream.empty<SimpleUser>()
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(users, outputStream)

            // Assert
            val json = outputStream.toString()
            assertEquals("[]", json)
        }

        @Test
        fun `should write single element Stream to OutputStream`() {
            // Arrange
            val users = Stream.of(SimpleUser(1, "Alice"))
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(users, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.startsWith("["))
            assertTrue(json.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should write Stream of generic containers to OutputStream`() {
            // Arrange
            val containers = Stream.of(
                GenericContainer(SimpleUser(1, "Alice"), mapOf("version" to "1.0")),
                GenericContainer(SimpleUser(2, "Bob"), mapOf("version" to "2.0"))
            )
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(containers, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.contains("\"version\":\"1.0\""))
            assertTrue(json.contains("\"version\":\"2.0\""))
        }

        @Test
        fun `should write Stream and then deserialize result using TypeRef`() {
            // Arrange
            val original = listOf(
                SimpleUser(1, "Alice"),
                SimpleUser(2, "Bob")
            )
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(original.stream(), outputStream)
            val json = outputStream.toString()
            val typeRef = TypeRef.listOf(SimpleUser::class.java)
            val deserialized = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(original, deserialized)
        }

        @Test
        fun `should handle large Stream efficiently`() {
            // Arrange
            val largeStream = (1..1000).map { SimpleUser(it, "User$it") }.stream()
            val outputStream = java.io.ByteArrayOutputStream()

            // Act
            mapper.writeToOutputStream(largeStream, outputStream)

            // Assert
            val json = outputStream.toString()
            assertTrue(json.contains("\"name\":\"User1\""))
            assertTrue(json.contains("\"name\":\"User1000\""))
            val typeRef = TypeRef.listOf(SimpleUser::class.java)
            val deserialized = fromJson(mapper, json, typeRef)
            assertEquals(1000, deserialized.size)
        }
    }

    // ========================================================================
    // Serialization Methods Comparison Tests
    // ========================================================================

    @Nested
    inner class SerializationMethodsComparisonTests {

        @Test
        fun `toJsonString with reified type should match with TypeRef`() {
            // Arrange
            val user = SimpleUser(1, "Alice")
            val typeRef = object : TypeRef<SimpleUser>() {}

            // Act
            val json1 = toJson(mapper, user)
            val json2 = toJson(mapper, user, typeRef)

            // Assert
            assertEquals(json1, json2)
        }

        @Test
        fun `toJsonStream with reified type should match with TypeRef`() {
            // Arrange
            val user = SimpleUser(1, "Alice")
            val typeRef = object : TypeRef<SimpleUser>() {}

            // Act
            val stream1 = toJsonStream(mapper, user)
            val stream2 = toJsonStream(mapper, user, typeRef)

            val json1 = stream1.bufferedReader().use { it.readText() }
            val json2 = stream2.bufferedReader().use { it.readText() }

            // Assert
            assertEquals(json1, json2)
        }

        @Test
        fun `all serialization methods should produce deserializable JSON`() {
            // Arrange
            val original = listOf(SimpleUser(1, "Alice"), SimpleUser(2, "Bob"))

            // Act - Serialize using different methods
            val json1 = toJson(mapper, original)
            val stream = toJsonStream(mapper, original)
            val json2 = stream.bufferedReader().use { it.readText() }

            // Deserialize both
            val typeRef = TypeRef.listOf(SimpleUser::class.java)
            val result1 = fromJson(mapper, json1, typeRef)
            val result2 = fromJson(mapper, json2, typeRef)

            // Assert
            assertEquals(original, result1)
            assertEquals(original, result2)
        }
    }

    // ========================================================================
    // Edge Cases with TypeRef
    // ========================================================================

    @Nested
    inner class EdgeCasesWithTypeRef {

        @Test
        fun `should handle empty List with TypeRef`() {
            // Arrange
            val json = """[]"""
            val typeRef = TypeRef.listOf(SimpleUser::class.java)

            // Act
            val users = fromJson(mapper, json, typeRef)

            // Assert
            assertTrue(users.isEmpty())
        }

        @Test
        fun `should handle empty Map with TypeRef`() {
            // Arrange
            val json = """{}"""
            val typeRef = TypeRef.mapOf(String::class.java, SimpleUser::class.java)

            // Act
            val userMap = fromJson(mapper, json, typeRef)

            // Assert
            assertTrue(userMap.isEmpty())
        }

        @Test
        fun `should handle nullable nested object with TypeRef`() {
            // Arrange
            val json = """{"id":1,"name":"Alice","address":null}"""
            val typeRef = TypeRef.of(NestedUser::class.java)

            // Act
            val user = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(1, user.id)
            assertEquals(null, user.address)
        }

        @Test
        fun `should handle List with nullable elements`() {
            // Arrange
            val json = """[{"id":1,"name":"Alice","email":null}]"""
            val typeRef = TypeRef.listOf(UserWithNullable::class.java)

            // Act
            val users = fromJson(mapper, json, typeRef)

            // Assert
            assertEquals(1, users.size)
            assertEquals(null, users[0].email)
        }

        @Test
        fun `should handle String input directly in toJsonString`() {
            // Arrange
            val jsonString = """{"id":1,"name":"Test"}"""

            // Act
            val result = toJson(mapper, jsonString)

            // Assert
            assertEquals(jsonString, result, "String should be returned as-is")
        }

        @Test
        fun `should handle String input directly in toJsonStream`() {
            // Arrange
            val jsonString = """{"id":1,"name":"Test"}"""

            // Act
            val stream = toJsonStream(mapper, jsonString)
            val result = stream.bufferedReader().use { it.readText() }

            // Assert
            assertEquals(jsonString, result, "String should be returned as-is in stream")
        }

        @Test
        fun `should serialize and deserialize object with defaults using all methods`() {
            // Arrange
            val original = UserWithDefaults(id = 1, name = "Custom", active = false)

            // Act & Assert - toJsonString + fromJsonString
            val json1 = toJson(mapper, original)
            val result1 = fromJson<UserWithDefaults>(mapper, json1)
            assertEquals(original, result1)

            // Act & Assert - toJsonStream + fromJsonStream
            val stream = toJsonStream(mapper, original)
            val result2 = fromJsonStream<UserWithDefaults>(mapper, stream)
            assertEquals(original, result2)

            // Act & Assert - convertValue
            val map = convertValue<Map<String, Any>>(mapper, original)
            val result3 = convertValue<UserWithDefaults>(mapper, map)
            assertEquals(original, result3)
        }
    }

    // ========================================================================
    // Type-Inference Serialization Tests (without explicit type specification)
    // ========================================================================

    @Nested
    inner class TypeInferenceSerializationTests {

        @Test
        fun `should serialize simple object without type specification`() {
            // Arrange
            val user = SimpleUser(1, "Alice")

            // Act - Use object's actual class
            val json = mapper.toJsonString(user, user.javaClass)

            // Assert
            assertTrue(json.contains("\"id\":1"))
            assertTrue(json.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should serialize List without type specification`() {
            // Arrange
            val users = listOf(
                SimpleUser(1, "Alice"),
                SimpleUser(2, "Bob")
            )

            // Act - Use actual runtime class
            val json = mapper.toJsonString(users, users.javaClass)

            // Assert
            assertTrue(json.startsWith("["))
            assertTrue(json.contains("\"name\":\"Alice\""))
            assertTrue(json.contains("\"name\":\"Bob\""))
        }

        @Test
        fun `should serialize Map without type specification`() {
            // Arrange
            val userMap = mapOf(
                "user1" to SimpleUser(1, "Alice"),
                "user2" to SimpleUser(2, "Bob")
            )

            // Act
            val json = mapper.toJsonString(userMap, userMap.javaClass)

            // Assert
            assertTrue(json.contains("\"user1\""))
            assertTrue(json.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should serialize nested object without type specification`() {
            // Arrange
            val user = NestedUser(1, "Charlie", Address("123 Main St", "Springfield", "12345"))

            // Act
            val json = mapper.toJsonString(user, user.javaClass)

            // Assert
            assertTrue(json.contains("\"address\""))
            assertTrue(json.contains("\"street\":\"123 Main St\""))
        }

        @Test
        fun `should serialize generic container without explicit type parameter`() {
            // Arrange
            val container = GenericContainer(
                value = SimpleUser(1, "Alice"),
                metadata = mapOf("version" to "1.0")
            )

            // Act - Runtime type erasure, but should still work
            val json = mapper.toJsonString(container, container.javaClass)

            // Assert
            assertTrue(json.contains("\"value\""))
            assertTrue(json.contains("\"name\":\"Alice\""))
            assertTrue(json.contains("\"metadata\""))
        }

        @Test
        fun `should serialize to stream without type specification`() {
            // Arrange
            val user = SimpleUser(1, "Alice")

            // Act
            val stream = mapper.toJsonStream(user, user.javaClass)
            val json = stream.bufferedReader().use { it.readText() }

            // Assert
            assertTrue(json.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should handle null value serialization - returns JSON null`() {
            // Arrange
            val data: Any? = null
            val value = data ?: "null"  // value becomes the String "null"

            // Act
            val json = mapper.toJsonString(value, value.javaClass)

            // Assert
            // String "null" is treated as already-JSON by ColleenJackson (see toJsonString implementation)
            assertEquals("null", json) // The literal string "null" is returned as-is, not quoted
        }

        @Test
        fun `should handle actual null value serialization`() {
            // Arrange - What if we want to serialize actual null?
            val data: Any? = null

            // Act
            val json = if (data != null) {
                mapper.toJsonString(data, data.javaClass)
            } else {
                "null" // Return JSON null directly
            }

            // Assert
            assertEquals("null", json)
        }

        @Test
        fun `should compare null handling strategies`() {
            // Strategy 1: Use "null" string (current implementation)
            val data1: Any? = null
            val value1 = data1 ?: "null"
            val json1 = mapper.toJsonString(value1, value1.javaClass)
            assertEquals("null", json1) // String is passed through

            // Strategy 2: Serialize actual null
            val data2: Any? = null
            val value2 = data2 ?: mapOf<String, Any?>()  // Use empty object instead
            val json2 = mapper.toJsonString(value2, value2.javaClass)
            assertEquals("{}", json2)

            // Strategy 3: Direct null JSON string
            val json3 = "null"
            assertEquals("null", json3)
        }

        @Test
        fun `should serialize primitive wrapper types without type specification`() {
            // Arrange
            val number: Any = 42
            val text: Any = "Hello"
            val flag: Any = true

            // Act
            val jsonNumber = mapper.toJsonString(number, number.javaClass)
            val jsonText = mapper.toJsonString(text, text.javaClass)
            val jsonFlag = mapper.toJsonString(flag, flag.javaClass)

            // Assert
            assertEquals("42", jsonNumber)
            // String is treated as already-JSON by ColleenJackson, so no quotes added
            assertEquals("Hello", jsonText)
            assertEquals("true", jsonFlag)
        }

        @Test
        fun `should differentiate between JSON string and plain string`() {
            // Arrange
            val plainString = "Hello"
            val jsonString = """{"message":"Hello"}"""

            // Act
            val result1 = mapper.toJsonString(plainString, plainString.javaClass)
            val result2 = mapper.toJsonString(jsonString, jsonString.javaClass)

            // Assert
            // Both are treated as already-JSON by ColleenJackson
            assertEquals("Hello", result1)
            assertEquals("""{"message":"Hello"}""", result2)
        }

        @Test
        fun `should serialize non-string primitives correctly`() {
            // Arrange
            val user = SimpleUser(42, "Test")

            // Act - When we serialize an actual object
            val json = mapper.toJsonString(user, user.javaClass)

            // Assert - This is properly JSON-encoded
            assertTrue(json.contains("\"name\":\"Test\""))  // String IS quoted in object context
            assertTrue(json.contains("\"id\":42"))  // Number is not quoted
        }

        @Test
        fun `should serialize object with nullable fields without type specification`() {
            // Arrange
            val user = UserWithNullable(1, "Bob", "bob@example.com", null)

            // Act
            val json = mapper.toJsonString(user, user.javaClass)

            // Assert
            assertTrue(json.contains("\"email\":\"bob@example.com\""))
            assertTrue(!json.contains("\"age\"")) // null fields omitted
        }

        @Test
        fun `should round-trip serialize and deserialize without explicit types`() {
            // Arrange
            val original = SimpleUser(1, "Alice")

            // Act - Serialize without type specification
            val json = mapper.toJsonString(original, original.javaClass)

            // Deserialize with TypeRef to verify
            val deserialized = fromJson<SimpleUser>(mapper, json)

            // Assert
            assertEquals(original, deserialized)
        }

        @Test
        fun `should handle complex collection types without type specification`() {
            // Arrange
            val data = mapOf(
                "users" to listOf(SimpleUser(1, "Alice"), SimpleUser(2, "Bob")),
                "count" to 2,
                "active" to true
            )

            // Act
            val json = mapper.toJsonString(data, data.javaClass)

            // Assert
            assertTrue(json.contains("\"users\""))
            assertTrue(json.contains("\"count\":2"))
            assertTrue(json.contains("\"active\":true"))
        }

        @Test
        fun `should serialize empty collections without type specification`() {
            // Arrange
            val emptyList = emptyList<SimpleUser>()
            val emptyMap = emptyMap<String, Any>()

            // Act
            val jsonList = mapper.toJsonString(emptyList, emptyList.javaClass)
            val jsonMap = mapper.toJsonString(emptyMap, emptyMap.javaClass)

            // Assert
            assertEquals("[]", jsonList)
            assertEquals("{}", jsonMap)
        }

        @Test
        fun `should demonstrate ResponseBody Json class scenario - with null handling`() {
            // Scenario 1: data is null
            val data1: Any? = null
            val value1 = data1 ?: "null"  // becomes String "null"
            val json1 = mapper.toJsonString(value1, value1.javaClass)
            assertEquals("null", json1) // String "null" is treated as already-JSON

            // Scenario 2: data is an object
            val data2: Any? = SimpleUser(1, "Alice")
            val value2 = data2 ?: "null"
            val json2 = mapper.toJsonString(value2, value2.javaClass)
            assertTrue(json2.contains("\"name\":\"Alice\""))

            // Scenario 3: data is already a JSON string
            val data3: Any? = """{"status":"ok"}"""
            val value3 = data3 ?: "null"
            val json3 = mapper.toJsonString(value3, value3.javaClass)
            assertEquals("""{"status":"ok"}""", json3) // Passed through as-is
        }

        @Test
        fun `should demonstrate ResponseBody Json class scenario - stream mode`() {
            // Arrange - Simulate the ResponseBody.Json scenario
            val data: Any? = listOf(SimpleUser(1, "Alice"), SimpleUser(2, "Bob"))
            val value = data ?: "null"

            // Act - Stream mode
            val stream = mapper.toJsonStream(value, value.javaClass)
            val json = stream.bufferedReader().use { it.readText() }

            // Assert
            assertTrue(json.startsWith("["))
            assertTrue(json.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should demonstrate ResponseBody Json class scenario - bytes mode`() {
            // Arrange - Simulate the ResponseBody.Json scenario
            val data: Any? = SimpleUser(1, "Alice")
            val value = data ?: "null"

            // Act - Bytes mode
            val json = mapper.toJsonString(value, value.javaClass)
            val bytes = json.toByteArray(Charsets.UTF_8)

            // Assert
            assertNotNull(bytes)
            assertTrue(bytes.isNotEmpty())
            val result = String(bytes, Charsets.UTF_8)
            assertTrue(result.contains("\"name\":\"Alice\""))
        }

        @Test
        fun `should handle polymorphic collections without type specification`() {
            // Arrange - Mixed types in collection
            val mixedList: List<Any> = listOf(
                SimpleUser(1, "Alice"),
                mapOf("key" to "value"),
                "plain string",
                42
            )

            // Act
            val json = mapper.toJsonString(mixedList, mixedList.javaClass)

            // Assert
            assertTrue(json.startsWith("["))
            assertTrue(json.contains("\"name\":\"Alice\""))
            assertTrue(json.contains("\"key\":\"value\""))
            assertTrue(json.contains("\"plain string\""))
            assertTrue(json.contains("42"))
        }
    }

    // ========================================================================
    // Error Handling with TypeRef
    // ========================================================================

    @Nested
    inner class ErrorHandlingWithTypeRef {

        @Test
        fun `should throw exception for invalid JSON with reified type`() {
            // Arrange
            val invalidJson = """{"id":1,"name":}"""

            // Act & Assert
            assertThrows<Exception> {
                fromJson<SimpleUser>(mapper, invalidJson)
            }
        }

        @Test
        fun `should throw exception for invalid JSON with TypeRef`() {
            // Arrange
            val invalidJson = """{"id":1,"name":}"""
            val typeRef = TypeRef.of(SimpleUser::class.java)

            // Act & Assert
            assertThrows<Exception> {
                fromJson(mapper, invalidJson, typeRef)
            }
        }

        @Test
        fun `should throw exception for type mismatch with TypeRef`() {
            // Arrange
            val json = """{"id":"not_a_number","name":"Alice"}"""
            val typeRef = TypeRef.of(SimpleUser::class.java)

            // Act & Assert
            assertThrows<Exception> {
                fromJson(mapper, json, typeRef)
            }
        }
    }
}