@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.model.repository

import android.content.Context
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import eu.gaudian.translator.model.DictionaryEntry
import eu.gaudian.translator.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.serialization.SerializationException

class DictionaryRepository(private val context: Context) {

    companion object {
        private val DICTIONARY_ENTRY_KEY = stringPreferencesKey("dictionary_entry")
        private val WORD_OF_THE_DAY_KEY = stringPreferencesKey("word_of_the_day")
    }

    init {
        CoroutineScope(context = Dispatchers.IO).launch {
        }
    }

    suspend fun saveDictionaryEntry(entry: DictionaryEntry) {
        val history = loadDictionaryEntry().first().toMutableList()
        history.removeAll { it.word.equals(entry.word, ignoreCase = true) && it.languageCode == entry.languageCode }
        history.add(0, entry)
        val updatedHistory = history.take(20)
        context.dataStore.saveObjectList(DICTIONARY_ENTRY_KEY, updatedHistory)
    }


    fun loadDictionaryEntry(): Flow<List<DictionaryEntry>> {
        return context.dataStore.loadObjectList<DictionaryEntry>(DICTIONARY_ENTRY_KEY)
            .catch { exception ->
                if (exception is SerializationException) {
                    Log.w("DictionaryRepo", "Could not parse old dictionary history. Clearing it.", exception)
                    clearHistory()
                    emit(emptyList())
                } else {
                    throw exception
                }
            }
    }

    suspend fun updateDictionaryEntry(entry: DictionaryEntry) {
        val history = loadDictionaryEntry().first().toMutableList()
        val index = history.indexOfFirst { it.id == entry.id }

        if (index != -1) {
            history[index] = entry
            context.dataStore.saveObjectList(DICTIONARY_ENTRY_KEY, history)
            Log.d("DictionaryRepo", "Entry with id ${entry.id} updated.")
        } else {
            Log.w("DictionaryRepo", "Attempted to update non-existent entry with id ${entry.id}.")
        }
    }

    suspend fun clearHistory() {
        context.dataStore.saveObjectList(DICTIONARY_ENTRY_KEY, emptyList<DictionaryEntry>())
    }

    suspend fun saveWordOfTheDay(entry: DictionaryEntry) {
        context.dataStore.saveObject(WORD_OF_THE_DAY_KEY, entry)
    }


    fun loadWordOfTheDay(): Flow<DictionaryEntry?> {
        return context.dataStore.loadObject<DictionaryEntry>(WORD_OF_THE_DAY_KEY)
            .catch { exception ->
                if (exception is SerializationException) {
                    Log.w("DictionaryRepo", "Could not parse old Word of the Day. Clearing it.", exception)
                    context.dataStore.edit { preferences ->
                        preferences.remove(WORD_OF_THE_DAY_KEY)
                    }
                    emit(null)
                } else {
                    throw exception
                }
            }
    }

}