package com.rssuper.models

import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import java.util.Date

class SearchFiltersTest {

    private lateinit var moshi: Moshi
    private lateinit var adapter: com.squareup.moshi.JsonAdapter<SearchFilters>

    @Before
    fun setup() {
        moshi = Moshi.Builder()
            .add(KotlinJsonAdapterFactory())
            .build()
        adapter = moshi.adapter(SearchFilters::class.java)
    }

    @Test
    fun testSerialization() {
        val filters = SearchFilters(
            dateFrom = Date(1672531200000),
            dateTo = Date(1672617600000),
            feedIds = listOf("feed-1", "feed-2"),
            authors = listOf("John Doe", "Jane Smith"),
            contentType = ContentType.ARTICLE,
            sortOption = SearchSortOption.DATE_DESC
        )

        val json = adapter.toJson(filters)
        assertNotNull(json)
    }

    @Test
    fun testDeserialization() {
        val json = """{
            "dateFrom": 1672531200000,
            "dateTo": 1672617600000,
            "feedIds": ["feed-1", "feed-2"],
            "authors": ["John Doe", "Jane Smith"],
            "contentType": "article",
            "sortOption": "date_desc"
        }"""

        val filters = adapter.fromJson(json)
        assertNotNull(filters)
        assertNotNull(filters?.dateFrom)
        assertNotNull(filters?.dateTo)
        assertEquals(2, filters?.feedIds?.size)
        assertEquals(2, filters?.authors?.size)
        assertEquals(ContentType.ARTICLE, filters?.contentType)
        assertEquals(SearchSortOption.DATE_DESC, filters?.sortOption)
    }

    @Test
    fun testContentTypeAudio() {
        val json = """{
            "contentType": "audio"
        }"""

        val filters = adapter.fromJson(json)
        assertNotNull(filters)
        assertEquals(ContentType.AUDIO, filters?.contentType)
    }

    @Test
    fun testContentTypeVideo() {
        val json = """{
            "contentType": "video"
        }"""

        val filters = adapter.fromJson(json)
        assertNotNull(filters)
        assertEquals(ContentType.VIDEO, filters?.contentType)
    }

    @Test
    fun testSortOptions() {
        val sortOptions = listOf(
            "relevance" to SearchSortOption.RELEVANCE,
            "date_desc" to SearchSortOption.DATE_DESC,
            "date_asc" to SearchSortOption.DATE_ASC,
            "title_asc" to SearchSortOption.TITLE_ASC,
            "title_desc" to SearchSortOption.TITLE_DESC,
            "feed_asc" to SearchSortOption.FEED_ASC,
            "feed_desc" to SearchSortOption.FEED_DESC
        )

        for ((jsonValue, expectedEnum) in sortOptions) {
            val json = """{"sortOption": "$jsonValue"}"""
            val filters = adapter.fromJson(json)
            assertNotNull("Failed for sortOption: $jsonValue", filters)
            assertEquals("Failed for sortOption: $jsonValue", expectedEnum, filters?.sortOption)
        }
    }

    @Test
    fun testOptionalFieldsNull() {
        val json = "{}"

        val filters = adapter.fromJson(json)
        assertNotNull(filters)
        assertNull(filters?.dateFrom)
        assertNull(filters?.dateTo)
        assertNull(filters?.feedIds)
        assertNull(filters?.authors)
        assertNull(filters?.contentType)
        assertEquals(SearchSortOption.RELEVANCE, filters?.sortOption)
    }

    @Test
    fun testCopy() {
        val original = SearchFilters(
            feedIds = listOf("feed-1"),
            sortOption = SearchSortOption.RELEVANCE
        )

        val modified = original.copy(
            feedIds = listOf("feed-1", "feed-2"),
            sortOption = SearchSortOption.DATE_DESC
        )

        assertEquals(2, modified.feedIds?.size)
        assertEquals(SearchSortOption.DATE_DESC, modified.sortOption)
    }

    @Test
    fun testEqualsAndHashCode() {
        val filters1 = SearchFilters(feedIds = listOf("feed-1"), sortOption = SearchSortOption.RELEVANCE)
        val filters2 = SearchFilters(feedIds = listOf("feed-1"), sortOption = SearchSortOption.RELEVANCE)
        val filters3 = SearchFilters(feedIds = listOf("feed-2"), sortOption = SearchSortOption.RELEVANCE)

        assertEquals(filters1, filters2)
        assertEquals(filters1.hashCode(), filters2.hashCode())
        assert(filters1 != filters3)
    }

    @Test
    fun testToString() {
        val filters = SearchFilters(
            feedIds = listOf("feed-1"),
            sortOption = SearchSortOption.DATE_DESC
        )

        val toString = filters.toString()
        assertNotNull(toString)
        assert(toString.contains("feedIds"))
        assert(toString.contains("sortOption"))
    }
}
