package com.swoosh.microblog.data.model

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

class TagModelsTest {

    private val gson = Gson()

    // --- GhostTagFull defaults ---

    @Test
    fun `GhostTagFull default id is null`() {
        val tag = GhostTagFull(name = "test")
        assertNull(tag.id)
    }

    @Test
    fun `GhostTagFull default visibility is public`() {
        val tag = GhostTagFull(name = "test")
        assertEquals("public", tag.visibility)
    }

    @Test
    fun `GhostTagFull default optional fields are null`() {
        val tag = GhostTagFull(name = "test")
        assertNull(tag.slug)
        assertNull(tag.description)
        assertNull(tag.feature_image)
        assertNull(tag.accent_color)
        assertNull(tag.count)
        assertNull(tag.created_at)
        assertNull(tag.updated_at)
        assertNull(tag.url)
    }

    @Test
    fun `GhostTagFull stores all fields`() {
        val tag = GhostTagFull(
            id = "tag-1",
            name = "kotlin",
            slug = "kotlin",
            description = "Posts about Kotlin",
            feature_image = "https://example.com/kotlin.png",
            visibility = "public",
            accent_color = "#FF5722",
            count = TagCount(posts = 42),
            created_at = "2024-01-01T00:00:00.000Z",
            updated_at = "2024-06-15T12:00:00.000Z",
            url = "https://blog.example.com/tag/kotlin/"
        )
        assertEquals("tag-1", tag.id)
        assertEquals("kotlin", tag.name)
        assertEquals("kotlin", tag.slug)
        assertEquals("Posts about Kotlin", tag.description)
        assertEquals("https://example.com/kotlin.png", tag.feature_image)
        assertEquals("public", tag.visibility)
        assertEquals("#FF5722", tag.accent_color)
        assertEquals(42, tag.count?.posts)
        assertEquals("2024-01-01T00:00:00.000Z", tag.created_at)
        assertEquals("2024-06-15T12:00:00.000Z", tag.updated_at)
        assertEquals("https://blog.example.com/tag/kotlin/", tag.url)
    }

    // --- TagCount ---

    @Test
    fun `TagCount stores post count`() {
        val count = TagCount(posts = 10)
        assertEquals(10, count.posts)
    }

    @Test
    fun `TagCount allows null posts`() {
        val count = TagCount(posts = null)
        assertNull(count.posts)
    }

    // --- GSON serialization ---

    @Test
    fun `GhostTagFull serializes to JSON correctly`() {
        val tag = GhostTagFull(
            name = "android",
            description = "Android development",
            accent_color = "#3DDC84"
        )
        val json = gson.toJson(tag)
        assertTrue(json.contains("\"name\":\"android\""))
        assertTrue(json.contains("\"description\":\"Android development\""))
        assertTrue(json.contains("\"accent_color\":\"#3DDC84\""))
    }

    @Test
    fun `GhostTagFull deserializes from JSON correctly`() {
        val json = """{
            "id": "abc123",
            "name": "tech",
            "slug": "tech",
            "description": "Technology posts",
            "visibility": "public",
            "accent_color": "#1E88E5",
            "count": {"posts": 15},
            "created_at": "2024-01-01T00:00:00.000Z",
            "updated_at": "2024-06-01T00:00:00.000Z",
            "url": "https://blog.example.com/tag/tech/"
        }"""
        val tag = gson.fromJson(json, GhostTagFull::class.java)
        assertEquals("abc123", tag.id)
        assertEquals("tech", tag.name)
        assertEquals("tech", tag.slug)
        assertEquals("Technology posts", tag.description)
        assertEquals("public", tag.visibility)
        assertEquals("#1E88E5", tag.accent_color)
        assertEquals(15, tag.count?.posts)
        assertEquals("2024-01-01T00:00:00.000Z", tag.created_at)
        assertEquals("2024-06-01T00:00:00.000Z", tag.updated_at)
        assertEquals("https://blog.example.com/tag/tech/", tag.url)
    }

    @Test
    fun `GhostTagFull deserializes with missing optional fields`() {
        val json = """{"name": "minimal"}"""
        val tag = gson.fromJson(json, GhostTagFull::class.java)
        assertEquals("minimal", tag.name)
        assertNull(tag.id)
        assertNull(tag.slug)
        assertNull(tag.description)
        assertNull(tag.accent_color)
        assertNull(tag.count)
    }

    // --- TagsResponse ---

    @Test
    fun `TagsResponse deserializes with tags and meta`() {
        val json = """{
            "tags": [
                {"id": "1", "name": "news", "slug": "news", "count": {"posts": 5}},
                {"id": "2", "name": "tech", "slug": "tech", "count": {"posts": 12}}
            ],
            "meta": {"pagination": {"page": 1, "limit": 15, "pages": 1, "total": 2, "next": null, "prev": null}}
        }"""
        val response = gson.fromJson(json, TagsResponse::class.java)
        assertEquals(2, response.tags.size)
        assertEquals("news", response.tags[0].name)
        assertEquals(5, response.tags[0].count?.posts)
        assertEquals("tech", response.tags[1].name)
        assertEquals(12, response.tags[1].count?.posts)
        assertNotNull(response.meta)
        assertEquals(1, response.meta?.pagination?.page)
        assertEquals(2, response.meta?.pagination?.total)
    }

    @Test
    fun `TagsResponse deserializes with null meta`() {
        val json = """{"tags": [{"name": "solo"}], "meta": null}"""
        val response = gson.fromJson(json, TagsResponse::class.java)
        assertEquals(1, response.tags.size)
        assertNull(response.meta)
    }

    // --- TagWrapper ---

    @Test
    fun `TagWrapper wraps tags for API request`() {
        val wrapper = TagWrapper(listOf(GhostTagFull(name = "new-tag", description = "A new tag")))
        val json = gson.toJson(wrapper)
        assertTrue(json.contains("\"tags\""))
        assertTrue(json.contains("\"new-tag\""))
        assertTrue(json.contains("\"A new tag\""))
    }

    @Test
    fun `TagWrapper serializes accent_color`() {
        val wrapper = TagWrapper(listOf(GhostTagFull(
            name = "colored",
            accent_color = "#FF0000"
        )))
        val json = gson.toJson(wrapper)
        assertTrue(json.contains("\"accent_color\":\"#FF0000\""))
    }

    @Test
    fun `TagCount zero posts`() {
        val count = TagCount(posts = 0)
        assertEquals(0, count.posts)
    }

    @Test
    fun `GhostTagFull with internal visibility`() {
        val tag = GhostTagFull(name = "internal-tag", visibility = "internal")
        assertEquals("internal", tag.visibility)
    }
}
