@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.utils

import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.assertFalse
import junit.framework.TestCase.assertNotNull
import junit.framework.TestCase.assertTrue
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.junit.Before
import org.junit.Test

class JsonHelperComprehensiveTest {

    private lateinit var jsonHelper: JsonHelper
    private val jsonParser = Json { ignoreUnknownKeys = true; isLenient = true }

    @Before
    fun setup() {
        jsonHelper = JsonHelper()
    }

    @Test
    fun `parseJson should handle valid DictionaryApiResponse`() {
        // Given
        val validJson = """{"word": "hello", "parts": [{"title": "Definition", "content": "A greeting"}]}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("word", "parts"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `parseJson should handle valid VocabularyApiResponse`() {
        // Given
        val validJson = """{"flashcards": [{"front": {"language": "English", "word": "hello"}, "back": {"language": "Spanish", "word": "hola"}}]}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("flashcards"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `parseJson should handle valid TranslationApiResponse`() {
        // Given
        val validJson = """{"translatedText": "hola"}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("translatedText"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `parseJson should handle valid CorrectionResponse`() {
        // Given
        val validJson = """{"correctedText": "Hello world", "explanation": "Capitalized first letter"}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("correctedText", "explanation"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `parseJson should handle valid EtymologyApiResponse`() {
        // Given
        val validJson = """{"word": "hello", "timeline": [{"year": "1890", "language": "Old English", "description": "From greeting"}], "relatedWords": []}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("word", "timeline", "relatedWords"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `parseJson should handle valid SynonymApiResponse`() {
        // Given
        val validJson = """{"synonyms": [{"word": "hi", "proximity": 95}, {"word": "greetings", "proximity": 85}]}"""
        
        // When
        val result = jsonHelper.validateRequiredFields(validJson, listOf("synonyms"))
        
        // Then
        assertTrue(result)
    }

    @Test
    fun `validateRequiredFields should return false for empty JSON`() {
        // Given
        val emptyJson = """{}"""
        val requiredFields = listOf("word")

        // When
        val result = jsonHelper.validateRequiredFields(emptyJson, requiredFields)

        // Then
        assertFalse(result)
    }

    @Test
    fun `validateRequiredFields should return false for malformed JSON`() {
        // Given
        val malformedJson = """{"word": "hello", "parts": ["""
        val requiredFields = listOf("word", "parts")

        // When
        val result = jsonHelper.validateRequiredFields(malformedJson, requiredFields)

        // Then
        assertFalse(result)
    }

    @Test
    fun `validateRequiredFields should handle nested objects`() {
        // Given
        val nestedJson = """{"flashcards": [{"front": {"language": "English", "word": "hello"}]}"""
        val requiredFields = listOf("flashcards")

        // When
        val result = jsonHelper.validateRequiredFields(nestedJson, requiredFields)

        // Then
        assertTrue(result)
    }

    @Test
    fun `extractField should extract simple field`() {
        // Given
        val json = """{"word": "hello", "parts": []}"""

        // When
        val result = jsonHelper.extractField(json, "word")

        // Then
        assertEquals("hello", result)
    }

    @Test
    fun `extractField should extract nested field`() {
        // Given
        val json = """{"flashcards": [{"front": {"language": "English", "word": "hello"}}]}"""

        // When
        val result = jsonHelper.extractField(json, "flashcards")

        // Then
        assertNotNull(result)
        assertTrue(result!!.contains("English"))
        assertTrue(result.contains("hello"))
    }

    @Test
    fun `extractField should return null for non-existent field`() {
        // Given
        val json = """{"word": "hello"}"""

        // When
        val result = jsonHelper.extractField(json, "nonexistent")

        // Then
        assertEquals(null, result)
    }

    @Test
    fun `extractField should handle array fields`() {
        // Given
        val json = """{"synonyms": [{"word": "hi", "proximity": 95}]}"""

        // When
        val result = jsonHelper.extractField(json, "synonyms")

        // Then
        assertNotNull(result)
        assertTrue(result!!.contains("hi"))
        assertTrue(result.contains("95"))
    }

    @Test
    fun `formatForDisplay should format simple JSON`() {
        // Given
        val json = """{"word": "hello", "parts": []}"""

        // When
        val result = jsonHelper.formatForDisplay(json)

        // Then
        assertTrue(result.contains("{\n"))
        assertTrue(result.contains("}\n"))
        assertTrue(result.contains(",\n"))
    }

    @Test
    fun `formatForDisplay should handle malformed JSON gracefully`() {
        // Given
        val malformedJson = """{"word": "hello", "parts": ["""

        // When
        val result = jsonHelper.formatForDisplay(malformedJson)

        // Then
        assertEquals(malformedJson, result) // Should return original if formatting fails
    }

    @Test
    fun `cleanAndValidateJson should handle markdown wrapped JSON`() {
        // Given
        val markdownJson = """
        ```json
        {"word": "hello", "parts": []}
        ```
        """.trim()

        // When
        val result = jsonHelper.validateRequiredFields(markdownJson, listOf("word", "parts"))

        // Then
        assertTrue(result)
    }

    @Test
    fun `cleanAndValidateJson should handle JSON with comments`() {
        // Given
        val jsonWithComments = """
        {
            "word": "hello", // This is the word
            "parts": [] /* This is the parts array */
        }
        """.trim()

        // When
        val result = jsonHelper.validateRequiredFields(jsonWithComments, listOf("word", "parts"))

        // Then
        assertTrue(result)
    }

    @Test
    fun `cleanAndValidateJson should handle JSON with trailing commas`() {
        // Given
        val jsonWithTrailingComma = """
        {
            "word": "hello",
            "parts": [],
        }
        """.trim()

        // When
        val result = jsonHelper.validateRequiredFields(jsonWithTrailingComma, listOf("word", "parts"))

        // Then
        assertTrue(result)
    }

    // Test data classes
    @Serializable
    data class TestDictionaryResponse(
        val word: String,
        val parts: List<TestEntryPart>
    )

    @Serializable
    data class TestEntryPart(
        val title: String,
        val content: String
    )

    @Serializable
    data class TestVocabularyResponse(
        val flashcards: List<TestFlashcard>
    )

    @Serializable
    data class TestFlashcard(
        val front: TestCardSide,
        val back: TestCardSide
    )

    @Serializable
    data class TestCardSide(
        val language: String,
        val word: String
    )

    @Test
    fun `real parsing test with DictionaryApiResponse`() {
        // Given
        val json = """{"word": "hello", "parts": [{"title": "Definition", "content": "A greeting"}]}"""
        
        // When
        val result = jsonParser.decodeFromString(TestDictionaryResponse.serializer(), json)
        
        // Then
        assertEquals("hello", result.word)
        assertEquals(1, result.parts.size)
        assertEquals("Definition", result.parts[0].title)
        assertEquals("A greeting", result.parts[0].content)
    }

    @Test
    fun `real parsing test with VocabularyApiResponse`() {
        // Given
        val json = """{"flashcards": [{"front": {"language": "English", "word": "hello"}, "back": {"language": "Spanish", "word": "hola"}}]}"""
        
        // When
        val result = jsonParser.decodeFromString(TestVocabularyResponse.serializer(), json)
        
        // Then
        assertEquals(1, result.flashcards.size)
        assertEquals("English", result.flashcards[0].front.language)
        assertEquals("hello", result.flashcards[0].front.word)
        assertEquals("Spanish", result.flashcards[0].back.language)
        assertEquals("hola", result.flashcards[0].back.word)
    }
}
