package es.verdnatura.dataStore

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import es.verdnatura.MobileApplication
import es.verdnatura.R
import es.verdnatura.domain.ConstAndValues.BASEURLLILIUM
import es.verdnatura.domain.ConstAndValues.BASEURLSALIX
import es.verdnatura.domain.ConstAndValues.BASE_URL_LILIUM
import es.verdnatura.domain.ConstAndValues.BASE_URL_SALIX
import es.verdnatura.domain.ConstAndValues.ENTRYID
import es.verdnatura.domain.ConstAndValues.ENTRYOBSERVATIONORIGINAL
import es.verdnatura.domain.ConstAndValues.ENTRYOBSERVATIONS
import es.verdnatura.domain.ConstAndValues.ITEMPACKING
import es.verdnatura.domain.ConstAndValues.NUMBEROFWAGONS
import es.verdnatura.domain.ConstAndValues.PRINTERFK
import es.verdnatura.domain.ConstAndValues.PRINTERFKDEFAULT
import es.verdnatura.domain.ConstAndValues.PRINTERNAME
import es.verdnatura.domain.ConstAndValues.RESERVATIONMODE
import es.verdnatura.domain.ConstAndValues.SECTORDESCRIP
import es.verdnatura.domain.ConstAndValues.SECTORFK
import es.verdnatura.domain.ConstAndValues.SECTORFKDEFAULT
import es.verdnatura.domain.ConstAndValues.SECTORISONRESERVATIONMODE
import es.verdnatura.domain.ConstAndValues.SUPPLIERID
import es.verdnatura.domain.ConstAndValues.SUPPLIERNAME
import es.verdnatura.domain.ConstAndValues.TRAINNAME
import es.verdnatura.domain.ConstAndValues.WAREHOUSEFK
import es.verdnatura.domain.ConstAndValues.WAREHOUSEFKDEFAULT
import es.verdnatura.domain.ConstAndValues.WORKFORMSELECTED
import es.verdnatura.presentation.view.feature.login.model.OperatorSalix
import es.verdnatura.presentation.view.feature.login.model.WorkForms
import es.verdnatura.presentation.view.feature.login.model.WorkerData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
import org.json.JSONObject
import java.util.Calendar

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
val Context.dataStoreWork: DataStore<Preferences> by preferencesDataStore(name = "workForm")

class DataStoreLocal(var mobileApplication: MobileApplication) {
    val IMAGES_KEY = stringPreferencesKey("images_key")

    suspend fun saveDataOperator(operator: OperatorSalix) {

        editDataStoreKey(
            SECTORFK, if (operator.sector != null) {
                operator.sector.id
            } else {
                SECTORFKDEFAULT
            }
        )
        editDataStoreKey(
            WAREHOUSEFK, if (operator.sector != null) {
                operator.sector.warehouseFk
            } else {
                WAREHOUSEFKDEFAULT
            }
        )
        editDataStoreKey(
            SECTORDESCRIP, if (operator.sector != null) {
                operator.sector.description
            } else {
                mobileApplication.getString(R.string.Sinsector)
            }
        )

        editDataStoreKey(
            PRINTERFK, if (operator.printer != null) {
                operator.printer.id
            } else {
                PRINTERFKDEFAULT
            }
        )
        editDataStoreKey(
            PRINTERNAME, if (operator.printer != null) {
                operator.printer.name
            } else {
                mobileApplication.getString(R.string.printerWithout)
            }
        )

        editDataStoreKey(
            TRAINNAME, if (operator.train != null) {
                operator.train.name
            } else {
                ""
            }
        )
        editDataStoreKey(
            NUMBEROFWAGONS, operator.numberOfWagons
        )

        editDataStoreKey(
            ITEMPACKING,
            if (operator.itemPackingTypeFk != null) operator.itemPackingTypeFk.toString() else ""
        )


        editDataStoreKey(
            RESERVATIONMODE, operator.isOnReservationMode
        )

    }

    //Tarea 6868
    suspend fun saveWorkerData(operator: WorkerData) {

        editDataStoreKey(
            SECTORFK, if (operator.sector != null) {
                operator.sector.id
            } else {
                SECTORFKDEFAULT
            }
        )
        
        if (operator.sector?.isOnReservationMode != null) {
            editDataStoreKey(
                SECTORISONRESERVATIONMODE,
                operator.sector.isOnReservationMode
            )
        } else {
            mobileApplication.dataStore.edit { preferences ->
                preferences.remove(stringPreferencesKey(SECTORISONRESERVATIONMODE))
            }
        }
        editDataStoreKey(
            WAREHOUSEFK, if (operator.sector != null) {
                operator.sector.warehouseFk
            } else {
                WAREHOUSEFKDEFAULT
            }
        )
        editDataStoreKey(
            SECTORDESCRIP, if (operator.sector != null) {
                operator.sector.description
            } else {
                mobileApplication.getString(R.string.Sinsector)
            }
        )

        editDataStoreKey(
            PRINTERFK, if (operator.printer != null) {
                operator.printer.id
            } else {
                PRINTERFKDEFAULT
            }
        )
        editDataStoreKey(
            PRINTERNAME, if (operator.printer != null) {
                operator.printer.name
            } else {
                mobileApplication.getString(R.string.printerWithout)
            }
        )

        editDataStoreKey(
            TRAINNAME, if (operator.train != null) {
                operator.train.name
            } else {
                ""
            }
        )
        editDataStoreKey(
            NUMBEROFWAGONS, operator.numberOfWagons
        )
        editDataStoreKey(
            RESERVATIONMODE, operator.isOnReservationMode
        )

    }

    suspend fun isPreferenceExists(key: String): Boolean {
        val preferencesKey = booleanPreferencesKey(key)
        val preferences = mobileApplication.dataStore.data.first()
        return preferences.contains(preferencesKey)
    }

    inline fun <reified T> readDataStoreKey(key: String): T {

        return when (T::class) {
            Int::class ->
                runBlocking {
                    mobileApplication.dataStore.data
                        .map { preferences -> preferences[intPreferencesKey(key)] ?: -1 }
                        .first() as T
                }

            String::class -> runBlocking {
                mobileApplication.dataStore.data
                    .map { preferences ->
                        preferences[stringPreferencesKey(key)] ?: if (key == BASEURLSALIX) {
                            BASE_URL_SALIX
                        } else {
                            ""
                        }
                    }
                    .first() as T
            }

            Boolean::class -> runBlocking {
                mobileApplication.dataStore.data
                    .map { preferences -> preferences[booleanPreferencesKey(key)] ?: false }
                    .first() as T
            }

            Long::class -> runBlocking {
                mobileApplication.dataStore.data
                    .map { preferences -> preferences[longPreferencesKey(key)] ?: 0 }
                    .first() as T
            }

            else -> "ERROR" as T
        }

    }

    suspend fun editDataStoreKey(key: String, value: Any) {

        mobileApplication.dataStore.edit { preferences ->
            when (value) {
                is Int -> preferences[intPreferencesKey(key)] = value
                is String -> preferences[stringPreferencesKey(key)] = value
                is Boolean -> preferences[booleanPreferencesKey(key)] = value
                is Long -> preferences[longPreferencesKey(key)] = value
            }
        }

    }

    suspend fun saveImages(images: MutableList<com.esafirm.imagepicker.model.Image>?) {
        val gson = Gson()
        val imagesJson = gson.toJson(images)
        mobileApplication.dataStore.edit { preferences ->
            preferences[IMAGES_KEY] = imagesJson
        }
    }

    fun getImages(): Flow<List<com.esafirm.imagepicker.model.Image>> {
        val gson = Gson()
        return mobileApplication.dataStore.data.map { preferences ->
            val imagesJson = preferences[IMAGES_KEY]
                ?: return@map emptyList<com.esafirm.imagepicker.model.Image>()
            val type = object : TypeToken<List<com.esafirm.imagepicker.model.Image>>() {}.type
            gson.fromJson(imagesJson, type)
        }
    }

    suspend fun deleteEntryPackaging() {
        mobileApplication.dataStoreApp.editDataStoreKey(ENTRYID, "")
        mobileApplication.dataStoreApp.editDataStoreKey(SUPPLIERID, "")
        mobileApplication.dataStoreApp.editDataStoreKey(SUPPLIERNAME, "")
        mobileApplication.dataStoreApp.editDataStoreKey(ENTRYOBSERVATIONORIGINAL, "")
        mobileApplication.dataStoreApp.editDataStoreKey(ENTRYOBSERVATIONS, "")

    }

    suspend fun deleteImages() {
        mobileApplication.dataStore.edit { preferences ->
            preferences.remove(IMAGES_KEY)
        }
    }

    suspend fun deleteWorkForm(nameWorkForm: Preferences.Key<String>) {

        if (nameWorkForm.name == "all") {
            mobileApplication.dataStoreWork.edit {
                it.clear()
            }

        } else {
            mobileApplication.dataStoreWork.edit { preferences ->
                preferences.remove(nameWorkForm)
            }
            mobileApplication.dataStoreApp.editDataStoreKey(
                WORKFORMSELECTED, "Producción"
            )
            saveWorkForm(
                WorkForms(
                    "Producción",
                    "https://salix.verdnatura.es"
                )
            )
        }

    }

    suspend fun getWorkForm(): List<WorkForms> {
        val listForms: ArrayList<WorkForms> = ArrayList()
        val preferences = mobileApplication.dataStoreWork.data.first()

        preferences.asMap().forEach { entry ->
            val key = entry.key
            val value = entry.value

            val json2 = JSONObject(value.toString())

            listForms.add(
                WorkForms(
                    key.name,
                    json2.get("urlSalix").toString(),
                    json2.get("isShowDelete").toString().toBoolean(),
                    json2.get("created") as Long

                )
            )

        }

        if (listForms.isEmpty() || listForms.size == 1) {
            createWorksDefault()
        }
        //createWorksDefault()

        return listForms.sortedBy { it.created }
    }

    private suspend fun createWorksDefault() {
        saveWorkForm(
            WorkForms(
                "Producción",
                "https://salix.verdnatura.es"
            )
        )
        saveWorkForm(
            WorkForms(
                "Test",
                urlSalix = "https://test-salix.verdnatura.es"
            )
        )
        saveWorkForm(
            WorkForms(
                "Dev",
                urlSalix = "https://dev-salix.verdnatura.es"
            )
        )
        saveWorkForm(
            WorkForms(
                "Aula formación",
                urlSalix = "http://pc525.samba.verdnatura.es:3000"
            )
        )
        val working_in_test = false
        if (working_in_test) {
            saveWorkForm(
                WorkForms(
                    "TestHome",
                    urlSalix = "https://test-salix.verdnatura.es"
                )
            )
            saveWorkForm(
                WorkForms(
                    "TestLOCAL",
                    urlSalix = "http://10.1.4.42:3000"
                )
            )
            saveWorkForm(
                WorkForms(
                    "TestLOCALHOME",
                    urlSalix = "http://192.168.1.139:3000"
                )
            )
            saveWorkForm(
                WorkForms(
                    "DEV SALIX",
                    urlSalix = "https://dev-salix.verdnatura.es"
                )
            )
        } else {
            //deleteWorkForm("all")
        }
        saveWorkForm(
            WorkForms(
                mobileApplication.getString(R.string.addWorkForm),
                "",
                isShowDelete = false,
                created = Calendar.getInstance().timeInMillis + Calendar.getInstance().timeInMillis

            )
        )

    }

    suspend fun saveWorkForm(workForm: WorkForms) {

        val gson = Gson()
        val json = gson.toJson(workForm)
        mobileApplication.dataStoreWork.edit { preferences ->
            preferences[stringPreferencesKey(workForm.name)] = json
        }

        runBlocking {

            mobileApplication.dataStoreApp.editDataStoreKey(
                BASEURLSALIX,
                workForm.urlSalix
            )
        }

    }

    fun getServerSalix(): String {

        var url =
            readDataStoreKey<String>(BASEURLSALIX)
        if (url.isBlank()) {
            url = BASE_URL_SALIX
        }
        return url
    }

    fun getServerLilium(): String {

        var url =
            readDataStoreKey<String>(BASEURLLILIUM)
        if (url.isBlank()) {
            url = BASE_URL_LILIUM
        }
        return url
    }
}