package com.swoosh.microblog.data.model

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.junit.Assert.*
import org.junit.Test

class GhostTagTest {

    private val gson = Gson()

    @Test
    fun `GhostTag serializes to JSON correctly`() {
        val tag = GhostTag(name = "kotlin")
        val json = gson.toJson(tag)
        assertTrue(json.contains("\"name\":\"kotlin\""))
    }

    @Test
    fun `GhostTag serializes with all fields`() {
        val tag = GhostTag(id = "tag123", name = "kotlin", slug = "kotlin")
        val json = gson.toJson(tag)
        assertTrue(json.contains("\"id\":\"tag123\""))
        assertTrue(json.contains("\"name\":\"kotlin\""))
        assertTrue(json.contains("\"slug\":\"kotlin\""))
    }

    @Test
    fun `GhostTag deserializes from JSON`() {
        val json = """{"id":"abc","name":"android","slug":"android"}"""
        val tag = gson.fromJson(json, GhostTag::class.java)
        assertEquals("abc", tag.id)
        assertEquals("android", tag.name)
        assertEquals("android", tag.slug)
    }

    @Test
    fun `GhostTag deserializes with only name`() {
        val json = """{"name":"test-tag"}"""
        val tag = gson.fromJson(json, GhostTag::class.java)
        assertNull(tag.id)
        assertEquals("test-tag", tag.name)
        assertNull(tag.slug)
    }

    @Test
    fun `GhostTag list serializes for API payload`() {
        val tags = listOf(
            GhostTag(name = "kotlin"),
            GhostTag(name = "android"),
            GhostTag(name = "ghost-cms")
        )
        val json = gson.toJson(tags)
        assertTrue(json.contains("kotlin"))
        assertTrue(json.contains("android"))
        assertTrue(json.contains("ghost-cms"))
    }

    @Test
    fun `GhostTag list deserializes from API response`() {
        val json = """[{"id":"1","name":"kotlin","slug":"kotlin"},{"id":"2","name":"android","slug":"android"}]"""
        val type = object : TypeToken<List<GhostTag>>() {}.type
        val tags: List<GhostTag> = gson.fromJson(json, type)
        assertEquals(2, tags.size)
        assertEquals("kotlin", tags[0].name)
        assertEquals("android", tags[1].name)
    }

    @Test
    fun `GhostPost with tags serializes correctly for API`() {
        val post = GhostPost(
            title = "Test Post",
            status = "published",
            tags = listOf(GhostTag(name = "kotlin"), GhostTag(name = "android"))
        )
        val wrapper = PostWrapper(listOf(post))
        val json = gson.toJson(wrapper)
        assertTrue(json.contains("\"tags\""))
        assertTrue(json.contains("\"kotlin\""))
        assertTrue(json.contains("\"android\""))
    }

    @Test
    fun `GhostPost with null tags serializes without tags`() {
        val post = GhostPost(title = "Test Post", tags = null)
        val json = gson.toJson(post)
        // Gson does not serialize null fields by default
        assertFalse(json.contains("\"tags\""))
    }

    @Test
    fun `GhostPost with empty tags list serializes with empty array`() {
        val post = GhostPost(title = "Test Post", tags = emptyList())
        val json = gson.toJson(post)
        assertTrue(json.contains("\"tags\":[]"))
    }

    @Test
    fun `GhostPost deserializes tags from API response`() {
        val json = """{
            "id": "post1",
            "title": "Hello",
            "tags": [{"id":"t1","name":"kotlin","slug":"kotlin"},{"id":"t2","name":"android","slug":"android"}]
        }"""
        val post = gson.fromJson(json, GhostPost::class.java)
        assertNotNull(post.tags)
        assertEquals(2, post.tags!!.size)
        assertEquals("kotlin", post.tags!![0].name)
        assertEquals("android", post.tags!![1].name)
    }

    @Test
    fun `GhostPost without tags field deserializes with null tags`() {
        val json = """{"id":"post1","title":"Hello"}"""
        val post = gson.fromJson(json, GhostPost::class.java)
        assertNull(post.tags)
    }

    @Test
    fun `Tag names stored as JSON in LocalPost round-trip correctly`() {
        val tagNames = listOf("kotlin", "android", "ghost-cms")
        val json = gson.toJson(tagNames)
        val type = object : TypeToken<List<String>>() {}.type
        val restored: List<String> = gson.fromJson(json, type)
        assertEquals(tagNames, restored)
    }

    @Test
    fun `Empty tag list stored as JSON round-trips correctly`() {
        val tagNames = emptyList<String>()
        val json = gson.toJson(tagNames)
        assertEquals("[]", json)
        val type = object : TypeToken<List<String>>() {}.type
        val restored: List<String> = gson.fromJson(json, type)
        assertTrue(restored.isEmpty())
    }

    @Test
    fun `FeedPost default tags is empty list`() {
        val post = FeedPost(
            title = "Test",
            textContent = "Content",
            htmlContent = null,
            imageUrl = null,
            linkUrl = null,
            linkTitle = null,
            linkDescription = null,
            linkImageUrl = null,
            status = "published",
            publishedAt = null,
            createdAt = null,
            updatedAt = null
        )
        assertTrue(post.tags.isEmpty())
    }

    @Test
    fun `FeedPost with tags stores them correctly`() {
        val post = FeedPost(
            title = "Test",
            textContent = "Content #kotlin",
            htmlContent = null,
            imageUrl = null,
            linkUrl = null,
            linkTitle = null,
            linkDescription = null,
            linkImageUrl = null,
            tags = listOf("kotlin", "android"),
            status = "published",
            publishedAt = null,
            createdAt = null,
            updatedAt = null
        )
        assertEquals(2, post.tags.size)
        assertEquals("kotlin", post.tags[0])
        assertEquals("android", post.tags[1])
    }

    @Test
    fun `LocalPost default tags is empty JSON array`() {
        val post = LocalPost()
        assertEquals("[]", post.tags)
    }
}
