package dev.kaizen.app

import dev.kaizen.app.db.ConversationEntity
import dev.kaizen.app.db.MessageEntity
import dev.kaizen.app.db.toEntity
import dev.kaizen.app.db.toStoredMessage
import dev.kaizen.app.db.toSummary
import dev.kaizen.app.net.Attachment
import dev.kaizen.app.net.ConversationSummary
import dev.kaizen.app.net.SearchSource
import dev.kaizen.app.net.StoredMessage
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class MappersTest {

    @Test
    fun conversationSummaryToEntity() {
        val summary = ConversationSummary(
            id = "conv-1",
            title = "Test Chat",
            locked = false,
            pinned = true,
            updatedAt = "2026-06-21T12:00:00Z",
        )
        val entity = summary.toEntity()

        assertEquals("conv-1", entity.id)
        assertEquals("Test Chat", entity.title)
        assertEquals(false, entity.locked)
        assertEquals(true, entity.pinned)
        assertEquals("2026-06-21T12:00:00Z", entity.updatedAt)
        assertTrue(entity.cachedAt > 0)
    }

    @Test
    fun conversationEntityToSummary() {
        val entity = ConversationEntity(
            id = "conv-2",
            title = "Another Chat",
            locked = true,
            pinned = false,
            updatedAt = null,
            cachedAt = 1000L,
        )
        val summary = entity.toSummary()

        assertEquals("conv-2", summary.id)
        assertEquals("Another Chat", summary.title)
        assertEquals(true, summary.locked)
        assertEquals(false, summary.pinned)
        assertEquals(null, summary.updatedAt)
    }

    @Test
    fun conversationRoundTrip() {
        val original = ConversationSummary(
            id = "rt-1", title = "Round Trip", locked = false, pinned = true,
            updatedAt = "2026-06-21T08:00:00Z",
        )
        val roundTripped = original.toEntity().toSummary()

        assertEquals(original.id, roundTripped.id)
        assertEquals(original.title, roundTripped.title)
        assertEquals(original.locked, roundTripped.locked)
        assertEquals(original.pinned, roundTripped.pinned)
        assertEquals(original.updatedAt, roundTripped.updatedAt)
    }

    @Test
    fun storedMessageToEntity() {
        val attachment = Attachment(url = "https://example.com/img.png", kind = "image", name = "img.png")
        val msg = StoredMessage(
            id = "msg-1",
            role = "assistant",
            content = "Hello there",
            attachments = listOf(attachment),
        )
        val entity = msg.toEntity(conversationId = "conv-1", sortOrder = 3)

        assertEquals("msg-1", entity.id)
        assertEquals("conv-1", entity.conversationId)
        assertEquals("assistant", entity.role)
        assertEquals("Hello there", entity.content)
        assertEquals(3, entity.sortOrder)
        assertEquals(1, entity.attachments.size)
        assertEquals("img.png", entity.attachments[0].name)
    }

    @Test
    fun messageEntityToStoredMessage() {
        val entity = MessageEntity(
            id = "msg-2",
            conversationId = "conv-1",
            role = "user",
            content = "Hi",
            attachments = emptyList(),
            sortOrder = 0,
        )
        val stored = entity.toStoredMessage()

        assertEquals("msg-2", stored.id)
        assertEquals("user", stored.role)
        assertEquals("Hi", stored.content)
        assertTrue(stored.attachments.isEmpty())
    }

    @Test
    fun messageRoundTrip() {
        val attachment = Attachment(url = "https://f.co/a.pdf", kind = "document", name = "a.pdf", mimeType = "application/pdf", size = 1024)
        val original = StoredMessage(id = "rt-msg", role = "user", content = "Check this", attachments = listOf(attachment))
        val roundTripped = original.toEntity("c1", 5).toStoredMessage()

        assertEquals(original.id, roundTripped.id)
        assertEquals(original.role, roundTripped.role)
        assertEquals(original.content, roundTripped.content)
        assertEquals(original.attachments.size, roundTripped.attachments.size)
        assertEquals(original.attachments[0].url, roundTripped.attachments[0].url)
        assertEquals(original.attachments[0].mimeType, roundTripped.attachments[0].mimeType)
        assertEquals(original.attachments[0].size, roundTripped.attachments[0].size)
    }

    @Test
    fun reasoningPreservedInRoundTrip() {
        val original = StoredMessage(
            id = "msg-r", role = "assistant", content = "Answer",
            reasoning = "Let me think about this step by step...",
        )
        val roundTripped = original.toEntity("c1", 0).toStoredMessage()

        assertEquals("Let me think about this step by step...", roundTripped.reasoning)
    }

    @Test
    fun nullReasoningPreserved() {
        val original = StoredMessage(id = "msg-nr", role = "assistant", content = "Simple answer")
        val entity = original.toEntity("c1", 0)
        assertNull(entity.reasoning)
        val roundTripped = entity.toStoredMessage()
        assertNull(roundTripped.reasoning)
    }

    @Test
    fun sourcesPreservedInRoundTrip() {
        val sources = listOf(
            SearchSource(title = "Wikipedia", url = "https://en.wikipedia.org/wiki/Test", snippet = "A test"),
            SearchSource(title = "MDN", url = "https://developer.mozilla.org", snippet = "Web docs"),
        )
        val original = StoredMessage(
            id = "msg-s", role = "assistant", content = "Search result",
            sources = sources,
        )
        val roundTripped = original.toEntity("c1", 0).toStoredMessage()

        assertEquals(2, roundTripped.sources?.size)
        assertEquals("Wikipedia", roundTripped.sources!![0].title)
        assertEquals("https://developer.mozilla.org", roundTripped.sources!![1].url)
    }

    @Test
    fun emptySourcesBecomeNull() {
        val original = StoredMessage(id = "msg-es", role = "assistant", content = "No sources")
        val entity = original.toEntity("c1", 0)
        assertTrue(entity.sources.isEmpty())
        val roundTripped = entity.toStoredMessage()
        assertNull(roundTripped.sources)
    }

    @Test
    fun reasoningAndSourcesTogether() {
        val original = StoredMessage(
            id = "msg-rs", role = "assistant", content = "Full answer",
            reasoning = "Thinking...",
            sources = listOf(SearchSource(title = "Src", url = "https://src.com")),
        )
        val roundTripped = original.toEntity("c1", 0).toStoredMessage()

        assertEquals("Thinking...", roundTripped.reasoning)
        assertEquals(1, roundTripped.sources?.size)
        assertEquals("Src", roundTripped.sources!![0].title)
    }
}
