package com.swoosh.microblog.data.model

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

class MemberModelsTest {

    private val gson = Gson()

    @Test
    fun `GhostMember deserializes from JSON correctly`() {
        val json = """{
            "id": "member1",
            "email": "test@example.com",
            "name": "John Doe",
            "status": "free",
            "avatar_image": "https://example.com/avatar.jpg",
            "email_count": 10,
            "email_opened_count": 5,
            "email_open_rate": 50.0,
            "last_seen_at": "2026-03-15T10:00:00.000Z",
            "created_at": "2026-01-01T00:00:00.000Z",
            "updated_at": "2026-03-15T10:00:00.000Z",
            "note": "VIP member",
            "geolocation": "Warsaw, Poland"
        }"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals("member1", member.id)
        assertEquals("test@example.com", member.email)
        assertEquals("John Doe", member.name)
        assertEquals("free", member.status)
        assertEquals("https://example.com/avatar.jpg", member.avatar_image)
        assertEquals(10, member.email_count)
        assertEquals(5, member.email_opened_count)
        assertEquals(50.0, member.email_open_rate!!, 0.001)
        assertEquals("VIP member", member.note)
        assertEquals("Warsaw, Poland", member.geolocation)
    }

    @Test
    fun `GhostMember deserializes with missing optional fields`() {
        val json = """{"id": "member2"}"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals("member2", member.id)
        assertNull(member.email)
        assertNull(member.name)
        assertNull(member.status)
        assertNull(member.avatar_image)
        assertNull(member.email_count)
        assertNull(member.email_opened_count)
        assertNull(member.email_open_rate)
        assertNull(member.last_seen_at)
        assertNull(member.created_at)
        assertNull(member.updated_at)
        assertNull(member.labels)
        assertNull(member.newsletters)
        assertNull(member.subscriptions)
        assertNull(member.note)
        assertNull(member.geolocation)
    }

    @Test
    fun `GhostMember deserializes with labels`() {
        val json = """{
            "id": "member3",
            "labels": [
                {"id": "label1", "name": "VIP", "slug": "vip"},
                {"id": "label2", "name": "Beta", "slug": "beta"}
            ]
        }"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals(2, member.labels?.size)
        assertEquals("VIP", member.labels?.get(0)?.name)
        assertEquals("vip", member.labels?.get(0)?.slug)
        assertEquals("Beta", member.labels?.get(1)?.name)
    }

    @Test
    fun `GhostMember deserializes with newsletters`() {
        val json = """{
            "id": "member4",
            "newsletters": [
                {"id": "nl1", "name": "Weekly Digest", "slug": "weekly-digest"},
                {"id": "nl2", "name": "Product Updates", "slug": "product-updates"}
            ]
        }"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals(2, member.newsletters?.size)
        assertEquals("Weekly Digest", member.newsletters?.get(0)?.name)
        assertEquals("nl2", member.newsletters?.get(1)?.id)
    }

    @Test
    fun `GhostMember deserializes with subscriptions`() {
        val json = """{
            "id": "member5",
            "status": "paid",
            "subscriptions": [
                {
                    "id": "sub1",
                    "status": "active",
                    "start_date": "2026-01-01T00:00:00.000Z",
                    "current_period_end": "2026-04-01T00:00:00.000Z",
                    "cancel_at_period_end": false,
                    "price": {"amount": 500, "currency": "USD", "interval": "month"},
                    "tier": {"id": "tier1", "name": "Gold"}
                }
            ]
        }"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals("paid", member.status)
        assertEquals(1, member.subscriptions?.size)
        val sub = member.subscriptions!![0]
        assertEquals("sub1", sub.id)
        assertEquals("active", sub.status)
        assertEquals(false, sub.cancel_at_period_end)
        assertEquals(500, sub.price?.amount)
        assertEquals("USD", sub.price?.currency)
        assertEquals("month", sub.price?.interval)
        assertEquals("Gold", sub.tier?.name)
    }

    @Test
    fun `MembersResponse deserializes with members and pagination`() {
        val json = """{
            "members": [
                {"id": "m1", "email": "a@example.com", "name": "Alice", "status": "free"},
                {"id": "m2", "email": "b@example.com", "name": "Bob", "status": "paid"}
            ],
            "meta": {
                "pagination": {
                    "page": 1, "limit": 15, "pages": 3, "total": 42, "next": 2, "prev": null
                }
            }
        }"""
        val response = gson.fromJson(json, MembersResponse::class.java)
        assertEquals(2, response.members.size)
        assertEquals("m1", response.members[0].id)
        assertEquals("Alice", response.members[0].name)
        assertEquals("free", response.members[0].status)
        assertEquals("Bob", response.members[1].name)
        assertEquals("paid", response.members[1].status)
        assertEquals(1, response.meta?.pagination?.page)
        assertEquals(3, response.meta?.pagination?.pages)
        assertEquals(42, response.meta?.pagination?.total)
        assertEquals(2, response.meta?.pagination?.next)
        assertNull(response.meta?.pagination?.prev)
    }

    @Test
    fun `MembersResponse deserializes with empty members list`() {
        val json = """{
            "members": [],
            "meta": {
                "pagination": {
                    "page": 1, "limit": 15, "pages": 0, "total": 0, "next": null, "prev": null
                }
            }
        }"""
        val response = gson.fromJson(json, MembersResponse::class.java)
        assertTrue(response.members.isEmpty())
        assertEquals(0, response.meta?.pagination?.total)
    }

    @Test
    fun `MemberLabel deserializes correctly`() {
        val json = """{"id": "l1", "name": "Premium", "slug": "premium"}"""
        val label = gson.fromJson(json, MemberLabel::class.java)
        assertEquals("l1", label.id)
        assertEquals("Premium", label.name)
        assertEquals("premium", label.slug)
    }

    @Test
    fun `MemberLabel allows null id and slug`() {
        val json = """{"name": "Test"}"""
        val label = gson.fromJson(json, MemberLabel::class.java)
        assertNull(label.id)
        assertEquals("Test", label.name)
        assertNull(label.slug)
    }

    @Test
    fun `MemberNewsletter deserializes correctly`() {
        val json = """{"id": "n1", "name": "Daily News", "slug": "daily-news"}"""
        val newsletter = gson.fromJson(json, MemberNewsletter::class.java)
        assertEquals("n1", newsletter.id)
        assertEquals("Daily News", newsletter.name)
        assertEquals("daily-news", newsletter.slug)
    }

    @Test
    fun `SubscriptionPrice deserializes correctly`() {
        val json = """{"amount": 1000, "currency": "EUR", "interval": "year"}"""
        val price = gson.fromJson(json, SubscriptionPrice::class.java)
        assertEquals(1000, price.amount)
        assertEquals("EUR", price.currency)
        assertEquals("year", price.interval)
    }

    @Test
    fun `SubscriptionTier deserializes correctly`() {
        val json = """{"id": "t1", "name": "Premium"}"""
        val tier = gson.fromJson(json, SubscriptionTier::class.java)
        assertEquals("t1", tier.id)
        assertEquals("Premium", tier.name)
    }

    @Test
    fun `GhostMember serializes to JSON correctly`() {
        val member = GhostMember(
            id = "m1",
            email = "test@test.com",
            name = "Test User",
            status = "free",
            avatar_image = null,
            email_count = 5,
            email_opened_count = 3,
            email_open_rate = 60.0,
            last_seen_at = null,
            created_at = "2026-01-01T00:00:00.000Z",
            updated_at = null,
            labels = emptyList(),
            newsletters = emptyList(),
            subscriptions = null,
            note = null,
            geolocation = null
        )
        val json = gson.toJson(member)
        assertTrue(json.contains("\"id\":\"m1\""))
        assertTrue(json.contains("\"email\":\"test@test.com\""))
        assertTrue(json.contains("\"status\":\"free\""))
    }

    @Test
    fun `MembersResponse reuses Meta and Pagination from GhostModels`() {
        // Verify MembersResponse uses the same Meta/Pagination as PostsResponse
        val json = """{
            "members": [{"id": "m1"}],
            "meta": {"pagination": {"page": 2, "limit": 50, "pages": 5, "total": 250, "next": 3, "prev": 1}}
        }"""
        val response = gson.fromJson(json, MembersResponse::class.java)
        val pagination = response.meta?.pagination!!
        assertEquals(2, pagination.page)
        assertEquals(50, pagination.limit)
        assertEquals(5, pagination.pages)
        assertEquals(250, pagination.total)
        assertEquals(3, pagination.next)
        assertEquals(1, pagination.prev)
    }

    @Test
    fun `GhostMember with zero email stats`() {
        val json = """{
            "id": "m1",
            "email_count": 0,
            "email_opened_count": 0,
            "email_open_rate": null
        }"""
        val member = gson.fromJson(json, GhostMember::class.java)
        assertEquals(0, member.email_count)
        assertEquals(0, member.email_opened_count)
        assertNull(member.email_open_rate)
    }

    @Test
    fun `MemberSubscription with cancel_at_period_end true`() {
        val json = """{
            "id": "sub1",
            "status": "active",
            "cancel_at_period_end": true,
            "price": {"amount": 900, "currency": "USD", "interval": "month"},
            "tier": {"id": "t1", "name": "Basic"}
        }"""
        val sub = gson.fromJson(json, MemberSubscription::class.java)
        assertEquals(true, sub.cancel_at_period_end)
        assertEquals(900, sub.price?.amount)
    }
}
