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.Before
import org.junit.Test

class ReadingPreferencesTest {

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

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

    @Test
    fun testSerialization() {
        val preferences = ReadingPreferences(
            fontSize = FontSize.LARGE,
            lineHeight = LineHeight.RELAXED,
            showTableOfContents = true,
            showReadingTime = true,
            showAuthor = false,
            showDate = true
        )

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

    @Test
    fun testDeserialization() {
        val json = """{
            "fontSize": "large",
            "lineHeight": "relaxed",
            "showTableOfContents": true,
            "showReadingTime": true,
            "showAuthor": false,
            "showDate": true
        }"""

        val preferences = adapter.fromJson(json)
        assertNotNull(preferences)
        assertEquals(FontSize.LARGE, preferences?.fontSize)
        assertEquals(LineHeight.RELAXED, preferences?.lineHeight)
        assertEquals(true, preferences?.showTableOfContents)
        assertEquals(true, preferences?.showReadingTime)
        assertEquals(false, preferences?.showAuthor)
        assertEquals(true, preferences?.showDate)
    }

    @Test
    fun testFontSizeOptions() {
        val fontSizes = listOf(
            "small" to FontSize.SMALL,
            "medium" to FontSize.MEDIUM,
            "large" to FontSize.LARGE,
            "xlarge" to FontSize.XLARGE
        )

        for ((jsonValue, expectedEnum) in fontSizes) {
            val json = """{"fontSize": "$jsonValue"}"""
            val preferences = adapter.fromJson(json)
            assertNotNull("Failed for fontSize: $jsonValue", preferences)
            assertEquals("Failed for fontSize: $jsonValue", expectedEnum, preferences?.fontSize)
        }
    }

    @Test
    fun testLineHeightOptions() {
        val lineHeights = listOf(
            "normal" to LineHeight.NORMAL,
            "relaxed" to LineHeight.RELAXED,
            "loose" to LineHeight.LOOSE
        )

        for ((jsonValue, expectedEnum) in lineHeights) {
            val json = """{"lineHeight": "$jsonValue"}"""
            val preferences = adapter.fromJson(json)
            assertNotNull("Failed for lineHeight: $jsonValue", preferences)
            assertEquals("Failed for lineHeight: $jsonValue", expectedEnum, preferences?.lineHeight)
        }
    }

    @Test
    fun testDefaultValues() {
        val preferences = ReadingPreferences()

        assertEquals(FontSize.MEDIUM, preferences.fontSize)
        assertEquals(LineHeight.NORMAL, preferences.lineHeight)
        assertEquals(false, preferences.showTableOfContents)
        assertEquals(true, preferences.showReadingTime)
        assertEquals(true, preferences.showAuthor)
        assertEquals(true, preferences.showDate)
    }

    @Test
    fun testCopy() {
        val original = ReadingPreferences(
            fontSize = FontSize.MEDIUM,
            showReadingTime = true
        )

        val modified = original.copy(fontSize = FontSize.XLARGE, showReadingTime = false)

        assertEquals(FontSize.XLARGE, modified.fontSize)
        assertEquals(false, modified.showReadingTime)
        assertEquals(LineHeight.NORMAL, modified.lineHeight)
    }

    @Test
    fun testEqualsAndHashCode() {
        val pref1 = ReadingPreferences(fontSize = FontSize.MEDIUM, showReadingTime = true)
        val pref2 = ReadingPreferences(fontSize = FontSize.MEDIUM, showReadingTime = true)
        val pref3 = ReadingPreferences(fontSize = FontSize.LARGE, showReadingTime = true)

        assertEquals(pref1, pref2)
        assertEquals(pref1.hashCode(), pref2.hashCode())
        assert(pref1 != pref3)
    }

    @Test
    fun testToString() {
        val preferences = ReadingPreferences(
            fontSize = FontSize.LARGE,
            showReadingTime = true
        )

        val toString = preferences.toString()
        assertNotNull(toString)
        assert(toString.contains("fontSize"))
        assert(toString.contains("showReadingTime"))
    }
}
