package com.swoosh.microblog.data.model

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

class PageModelsTest {

    private val gson = Gson()

    // --- GhostPage defaults ---

    @Test
    fun `GhostPage all fields default to null`() {
        val page = GhostPage()
        assertNull(page.id)
        assertNull(page.title)
        assertNull(page.slug)
        assertNull(page.url)
        assertNull(page.html)
        assertNull(page.plaintext)
        assertNull(page.mobiledoc)
        assertNull(page.status)
        assertNull(page.feature_image)
        assertNull(page.custom_excerpt)
        assertNull(page.created_at)
        assertNull(page.updated_at)
        assertNull(page.published_at)
    }

    @Test
    fun `GhostPage stores all fields correctly`() {
        val page = GhostPage(
            id = "page-1",
            title = "About",
            slug = "about",
            url = "https://blog.example.com/about/",
            html = "<p>About us</p>",
            plaintext = "About us",
            mobiledoc = """{"version":"0.3.1"}""",
            status = "published",
            feature_image = "https://blog.example.com/img.jpg",
            custom_excerpt = "Learn more about us",
            created_at = "2024-01-01T00:00:00.000Z",
            updated_at = "2024-06-15T12:00:00.000Z",
            published_at = "2024-01-02T00:00:00.000Z"
        )
        assertEquals("page-1", page.id)
        assertEquals("About", page.title)
        assertEquals("about", page.slug)
        assertEquals("https://blog.example.com/about/", page.url)
        assertEquals("<p>About us</p>", page.html)
        assertEquals("About us", page.plaintext)
        assertEquals("published", page.status)
        assertEquals("https://blog.example.com/img.jpg", page.feature_image)
        assertEquals("Learn more about us", page.custom_excerpt)
        assertEquals("2024-01-01T00:00:00.000Z", page.created_at)
        assertEquals("2024-06-15T12:00:00.000Z", page.updated_at)
        assertEquals("2024-01-02T00:00:00.000Z", page.published_at)
    }

    // --- GSON serialization ---

    @Test
    fun `GhostPage serializes to JSON correctly`() {
        val page = GhostPage(
            id = "abc123",
            title = "Contact",
            slug = "contact",
            status = "published"
        )
        val json = gson.toJson(page)
        assertTrue(json.contains("\"id\":\"abc123\""))
        assertTrue(json.contains("\"title\":\"Contact\""))
        assertTrue(json.contains("\"slug\":\"contact\""))
        assertTrue(json.contains("\"status\":\"published\""))
    }

    @Test
    fun `GhostPage deserializes from JSON correctly`() {
        val json = """{"id":"xyz","title":"FAQ","slug":"faq","status":"draft"}"""
        val page = gson.fromJson(json, GhostPage::class.java)
        assertEquals("xyz", page.id)
        assertEquals("FAQ", page.title)
        assertEquals("faq", page.slug)
        assertEquals("draft", page.status)
    }

    @Test
    fun `GhostPage deserializes with missing optional fields`() {
        val json = """{"id":"test"}"""
        val page = gson.fromJson(json, GhostPage::class.java)
        assertEquals("test", page.id)
        assertNull(page.title)
        assertNull(page.slug)
        assertNull(page.html)
        assertNull(page.status)
    }

    // --- PagesResponse ---

    @Test
    fun `PagesResponse deserializes with pages and pagination`() {
        val json = """{
            "pages": [{"id": "1", "title": "About"}, {"id": "2", "title": "Contact"}],
            "meta": {"pagination": {"page": 1, "limit": 15, "pages": 1, "total": 2, "next": null, "prev": null}}
        }"""
        val response = gson.fromJson(json, PagesResponse::class.java)
        assertEquals(2, response.pages.size)
        assertEquals("1", response.pages[0].id)
        assertEquals("About", response.pages[0].title)
        assertEquals("2", response.pages[1].id)
        assertEquals("Contact", response.pages[1].title)
        assertEquals(1, response.meta?.pagination?.page)
        assertEquals(2, response.meta?.pagination?.total)
        assertNull(response.meta?.pagination?.next)
    }

    @Test
    fun `PagesResponse deserializes with empty pages list`() {
        val json = """{"pages": [], "meta": null}"""
        val response = gson.fromJson(json, PagesResponse::class.java)
        assertTrue(response.pages.isEmpty())
        assertNull(response.meta)
    }

    // --- PageWrapper ---

    @Test
    fun `PageWrapper wraps pages for API request`() {
        val wrapper = PageWrapper(listOf(GhostPage(title = "New Page", status = "draft")))
        val json = gson.toJson(wrapper)
        assertTrue(json.contains("\"pages\""))
        assertTrue(json.contains("\"New Page\""))
    }

    @Test
    fun `PageWrapper serializes single page correctly`() {
        val page = GhostPage(
            title = "About Us",
            slug = "about-us",
            status = "published",
            mobiledoc = """{"version":"0.3.1","atoms":[],"cards":[],"markups":[],"sections":[[1,"p",[[0,[],0,"Welcome"]]]]}"""
        )
        val wrapper = PageWrapper(listOf(page))
        val json = gson.toJson(wrapper)
        assertTrue(json.contains("\"title\":\"About Us\""))
        assertTrue(json.contains("\"slug\":\"about-us\""))
        assertTrue(json.contains("\"status\":\"published\""))
    }

    @Test
    fun `GhostPage updated_at is preserved for PUT requests`() {
        val page = GhostPage(
            id = "page-1",
            title = "Updated Title",
            updated_at = "2024-06-15T12:00:00.000Z"
        )
        val json = gson.toJson(page)
        assertTrue(json.contains("\"updated_at\":\"2024-06-15T12:00:00.000Z\""))
    }
}
