@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.model.repository

import eu.gaudian.translator.model.grammar.DictionaryEntryData
import eu.gaudian.translator.model.grammar.DictionaryJsonParser
import eu.gaudian.translator.utils.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

import javax.inject.Inject

/**
 * Service layer for accessing parsed dictionary JSON data.
 * 
 * This service provides a clean interface between the repository layer
 * and the JSON parsing logic, making it easy to use structured dictionary
 * data throughout the application.
 * 
 * The service handles caching and error handling, ensuring that
 * UI components and other parts of the app can safely access
 * parsed dictionary data without worrying about JSON parsing details.
 */
class DictionaryJsonService @Inject constructor() {
    
    private val parseCache = mutableMapOf<String, DictionaryEntryData?>()
    @Suppress("PrivatePropertyName")
    private val TAG = "DictionaryJsonService"
    
    /**
     * Parse a dictionary entry's JSON data into a structured format.
     * 
     * @param entry The dictionary entry from the local database
     * @return Structured dictionary data or null if parsing fails
     */
    suspend fun parseEntry(entry: DictionaryWordEntry): DictionaryEntryData? {
        return withContext(Dispatchers.IO) {
            // Check cache first
            parseCache[entry.json]?.let { return@withContext it }
            
            try {
                val parsed = DictionaryJsonParser.parseJson(entry.json)
                parseCache[entry.json] = parsed
                parsed
            } catch (e: Exception) {
                Log.e(TAG, "Failed to parse dictionary entry for '${entry.word}': ${e.message}", e)
                parseCache[entry.json] = null
                null
            }
        }
    }
    
    /**
     * Parse multiple dictionary entries efficiently.
     * 
     * @param entries List of dictionary entries to parse
     * @return Map of entry word to parsed data (null for failed parses)
     */
    suspend fun parseEntries(entries: List<DictionaryWordEntry>): Map<String, DictionaryEntryData?> {
        return withContext(Dispatchers.IO) {
            entries.associate { entry ->
                entry.word to parseEntry(entry)
            }
        }
    }
    
    /**
     * Get translations for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of translations or empty list if parsing fails
     */
    suspend fun getTranslations(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.translations ?: emptyList()
    
    /**
     * Get synonyms for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of synonyms or empty list if parsing fails
     */
    suspend fun getSynonyms(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.synonyms ?: emptyList()
    
    /**
     * Get hyponyms for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of hyponyms or empty list if parsing fails
     */
    suspend fun getHyponyms(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.hyponyms ?: emptyList()
    
    /**
     * Get all related words for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of all related words or empty list if parsing fails
     */
    suspend fun getAllRelatedWords(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.allRelatedWords ?: emptyList()

    suspend fun getPhonetics(entry: DictionaryWordEntry): List<String> =
        parseEntry(entry)?.phonetics?.ipa ?: emptyList()
    
    /**
     * Get hyphenation data for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of hyphenation parts or empty list if parsing fails
     */
    suspend fun getHyphenation(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.hyphenation ?: emptyList()
    
    /**
     * Get etymology data for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return Etymology data or empty data if parsing fails
     */
    suspend fun getEtymology(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.etymology ?: eu.gaudian.translator.model.grammar.EtymologyData(emptyList())
    
    /**
     * Get senses/definitions for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of senses or empty list if parsing fails
     */
    suspend fun getSenses(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.senses ?: emptyList()
    
    /**
     * Get grammatical properties for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return Grammatical properties or null if parsing fails
     */
    suspend fun getGrammaticalProperties(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.grammaticalProperties
    
    /**
     * Get pronunciation data for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of pronunciation data or empty list if parsing fails
     */
    suspend fun getPronunciation(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.pronunciation ?: emptyList()
    

    
    /**
     * Get inflection data for a specific dictionary entry.
     * 
     * @param entry The dictionary entry
     * @return List of inflection data or empty list if parsing fails
     */
    suspend fun getInflections(entry: DictionaryWordEntry) = 
        parseEntry(entry)?.inflections ?: emptyList()
    
    /**
     * Clear the internal cache. Useful for testing or when memory is constrained.
     */
    fun clearCache() {
        parseCache.clear()
    }
    
    /**
     * Get cache statistics for debugging purposes.
     */
    fun getCacheStats(): CacheStats {
        return CacheStats(
            totalEntries = parseCache.size,
            successfulParses = parseCache.values.count { it != null },
            failedParses = parseCache.values.count { it == null }
        )
    }
}

/**
 * Cache statistics for debugging and monitoring.
 */
data class CacheStats(
    val totalEntries: Int,
    val successfulParses: Int,
    val failedParses: Int
)
