package es.verdnatura.presentation.view.feature.login.fragment

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import es.verdnatura.MobileApplication
import es.verdnatura.domain.ConstAndValues.TOKEN
import es.verdnatura.domain.ConstAndValues.TOKENCREATED
import es.verdnatura.domain.ConstAndValues.TTL
import es.verdnatura.domain.SalixCallback
import es.verdnatura.domain.SilexCallback
import es.verdnatura.domain.formatWithQuotes
import es.verdnatura.presentation.base.BaseViewModel
import es.verdnatura.presentation.base.getMessageFromAllResponse
import es.verdnatura.presentation.base.nameofFunction
import es.verdnatura.presentation.common.Event
import es.verdnatura.presentation.common.ResponseItemVO
import es.verdnatura.presentation.view.feature.historicoshelvinglog.model.DeviceLogSalix
import es.verdnatura.presentation.view.feature.login.model.DataUserSalix
import es.verdnatura.presentation.view.feature.login.model.LoginDevice
import es.verdnatura.presentation.view.feature.login.model.LoginSalixVO
import es.verdnatura.presentation.view.feature.login.model.OperatorSalix
import es.verdnatura.presentation.view.feature.login.model.RenewToken
import es.verdnatura.presentation.view.feature.login.model.accessConfigSalix
import es.verdnatura.presentation.view.feature.login.model.accessConfigSalixList
import es.verdnatura.presentation.view.feature.login.model.versionApp
import es.verdnatura.presentation.view.feature.paletizador.model.itemsExpeditionDynamics
import kotlinx.coroutines.runBlocking
import retrofit2.Response
import java.util.Date

class LoginViewModel(val context: Context) : BaseViewModel(context) {
    private val _loginSalixItem by lazy { MutableLiveData<LoginSalixVO>() }
    val loginSalixItem: LiveData<LoginSalixVO>
        get() = _loginSalixItem

    private val _devicelogresponse by lazy { MutableLiveData<ResponseItemVO>() }
    val devicelogresponse: LiveData<ResponseItemVO>
        get() = _devicelogresponse

    private val _operatorAdd by lazy { MutableLiveData<ResponseItemVO>() }
    val operatorAdd: LiveData<ResponseItemVO>
        get() = _operatorAdd

    private val _versionappitem by lazy { MutableLiveData<versionApp>() }
    val versionappitem: LiveData<versionApp>
        get() = _versionappitem

    private val _logindevice by lazy { MutableLiveData<LoginDevice>() }
    val logindevice: LiveData<LoginDevice>
        get() = _logindevice

    private val _workerOperator by lazy { MutableLiveData<OperatorSalix>() }
    val workerOperator: LiveData<OperatorSalix>
        get() = _workerOperator

    private val _accessConfigSalixList by lazy { MutableLiveData<accessConfigSalixList>() }

    private val _renewTokenResponse by lazy { MutableLiveData<RenewToken>() }
    val renewTokenResponse: LiveData<RenewToken>
        get() = _renewTokenResponse

    val loadAccessConfigSalixList = Transformations.map(_accessConfigSalixList) { Event(it) }

    fun loginSalix(user: String, password: String) {
        salix.login(LoginSalixVO(user, password))
            .enqueue(object : SalixCallback<LoginSalixVO>(context) {
                override fun onSuccess(response: Response<LoginSalixVO>) {

                    val loginSalixVO: LoginSalixVO?
                    if (response.body() != null) {
                        loginSalixVO = response.body()?.let {
                            LoginSalixVO(
                                user,
                                password,
                                it.token,
                                it.created,
                                it.ttl,
                                isError = false,
                                errorMessage = ""
                            )
                        }
                    } else {

                        loginSalixVO = LoginSalixVO(
                            user,
                            password,
                            isError = true,
                            errorMessage = getMessageFromAllResponse(
                                nameofFunction(this), response.message()
                            )
                        )

                    }

                    _loginSalixItem.value = loginSalixVO
                }

                override fun onError(t: Throwable) {
                    val loginSalixVO = LoginSalixVO(
                        user,
                        password,
                        "",
                        isError = true,
                        errorMessage = getMessageFromAllResponse(
                            nameofFunction(this), t.message!!
                        )
                    )
                    _loginSalixItem.value = loginSalixVO
                }
            })
    }

    fun deviceCheckLogin(userId: Int, androidId: String) {
        // FALTA EL USUARI
        /* fun deviceCheckLogin(androidId: String) {
         silex.device_checkLogin(androidId)*/
        salix.deviceCheckLogin(arrayListOf(userId, androidId).formatWithQuotes())
            .enqueue(object : SalixCallback<List<LoginDevice>>(context) {
                override fun onSuccess(response: Response<List<LoginDevice>>) {
                    response.body()?.get(0).let {
                        _logindevice.value = LoginDevice(
                            it!!.vMessage, it.vIsAuthorized, isError = false, errorMessage = ""
                        )
                    }
                }

                override fun onError(t: Throwable) {
                    _logindevice.value = LoginDevice(
                        "", "", isError = true, errorMessage = getMessageFromAllResponse(
                            nameofFunction(this), t.message!!
                        )
                    )
                }
            })
    }

    fun getCurrentUserData(
        appName: String, versionApp: String, androidId: String, serialnumber: String? = null
    ) {
        salix.getCurrentUserData().enqueue(object : SalixCallback<DataUserSalix>(context) {
            override fun onSuccess(response: Response<DataUserSalix>) {
                app.userName = response.body()?.nickname
                app.userId = response.body()?.id
                deviceLog_addSalix(
                    app = appName,
                    versionApp = versionApp,
                    android_id = androidId,
                    userFk = app.userId!!,
                    serialnumber = serialnumber
                )
                //Tarea 5870
                operator_getDataSalix(app.userId!!)
                deviceCheckLogin(app.userId!!, androidId)
            }
        })
    }

    /*    fun deviceLog_add(
            app: String, versionApp: String, android_id: String, userFk :Int
        ) {
            //Tarea 4815
             salix.deviceLogInsert(DeviceLogSalix(android_id = android_id,nameApp= app,versionApp= versionApp, serialNumber = null, userFk = userFk))

                .enqueue(object : SilexCallback<Unit>(context) {
                    override fun onSuccess(response: Response<Unit>) {
                    }
                })

        }*/

    fun deviceLog_addSalix(
        app: String, versionApp: String, android_id: String, userFk: Int, serialnumber: String?
    ) {

        //Tarea 4815
        salix.deviceLogInsert(
            DeviceLogSalix(
                android_id = android_id,
                userFk = userFk,
                nameApp = app,
                versionApp = versionApp,
                serialNumber = serialnumber
            )
        ).enqueue(object : SalixCallback<Unit>(context) {

                override fun onSuccess(response: Response<Unit>) {
                }

            })

    }

    fun checkVersion(nameApp: String) {
        //Tarea 6276
        // salix.getVersion(nameApp)
        silex.getVersion(nameApp).enqueue(object : SilexCallback<versionApp>(context) {
                override fun onSuccess(response: Response<versionApp>) {
                    if (response.body() != null) {
                        _versionappitem.value = response.body()?.let {
                            versionApp(
                                it.appname,
                                it.version,
                                it.IsVersionCritical,
                                it.url,
                                isError = false,
                                errorMessage = ""
                            )

                        }

                    } else {
                        _versionappitem.value = versionApp(
                            "", "", isError = true, errorMessage = getMessageFromAllResponse(
                                nameofFunction(this), response.message()
                            )
                        )
                    }
                }

                override fun onError(t: Throwable) {
                    _versionappitem.value = versionApp(
                        nameApp, "", isError = true, errorMessage = getMessageFromAllResponse(
                            nameofFunction(this), t.message!!
                        )
                    )
                }
            })
    }

    fun getListFromJSON(json: JsonObject): MutableList<itemsExpeditionDynamics> {
        val gson = Gson()
        val list = mutableListOf<itemsExpeditionDynamics>()
        val expeditionState: Map<String, Any> =
            gson.fromJson(json, object : TypeToken<Map<String, Any>>() {}.type)
        expeditionState.forEach {

            list.add(itemsExpeditionDynamics(key = it.key, value = it.value.toString()))

        }
        return list
    }

    fun operator_add() {
        //Tarea 6276
        //salix.operatorAdd().enqueue(object : SalixCallback<Any>(context) {
        silex.operator_add().enqueue(object : SilexCallback<Any>(context) {
            override fun onError(t: Throwable) {
                _operatorAdd.value = ResponseItemVO(
                    isError = true,
                    errorMessage = getMessageFromAllResponse(nameofFunction(this), t.message!!)
                )
            }

            override fun onSuccess(response: Response<Any>) {
                _operatorAdd.value = ResponseItemVO("", false)
            }
        })
    }

    //Tarea 5870
    fun operator_getDataSalix(
        workerId: Int
    ) {
        val filter =
            """{"fields":["itemPackingTypeFk","numberOfWagons","sectorFk","trainFk","labelerFk"],"include":[{"relation":"sector","scope":{"fields":["description","warehouseFk"]}},{"relation":"printer","scope":{"fields":["name"]}},{"relation":"train","scope":{"fields":["name"]}}]}"""
        salix.operator_getData(id = workerId, filter)
            .enqueue(object : SalixCallback<OperatorSalix>(context) {
                override fun onError(t: Throwable) {

                    _workerOperator.value = OperatorSalix(
                        isError = true, errorMessage = getMessageFromAllResponse(
                            nameofFunction(this), t.message!!
                        )
                    )

                }

                override fun onSuccess(response: Response<OperatorSalix>) {
                    if (response.body() != null) {
                        _workerOperator.value = response.body()
                    } else {
                        _workerOperator.value = response.body()?.let {
                            OperatorSalix(
                                isError = true, errorMessage = getMessageFromAllResponse(
                                    nameofFunction(this), response.message()
                                )
                            )
                        }
                    }

                }

            })
    }

    fun getAccessTokenConfigs(
    ) {

        salix.getAccessTokenConfigs()
            .enqueue(object : SalixCallback<List<accessConfigSalix>>(context) {
                override fun onError(t: Throwable) {
                    val listError: ArrayList<accessConfigSalix> = ArrayList()
                    listError.add(
                        accessConfigSalix(
                            isError = true, errorMessage = getMessageFromAllResponse(
                                nameofFunction(this), t.message!!
                            )
                        )
                    )
                    _accessConfigSalixList.value = accessConfigSalixList(listError)

                }

                override fun onSuccess(response: Response<List<accessConfigSalix>>) {
                    if (response.body() != null) {
                        _accessConfigSalixList.value = response.body()?.let {
                            accessConfigSalixList(it)
                        }

                    } else {
                        val listError: ArrayList<accessConfigSalix> = ArrayList()
                        listError.add(
                            accessConfigSalix(
                                isError = true, errorMessage = getMessageFromAllResponse(
                                    nameofFunction(this), response.message()
                                )
                            )
                        )
                        _accessConfigSalixList.value = accessConfigSalixList(listError)

                    }

                }

            })
    }

    fun renewToken(
    ) {
        salix.renewToken().enqueue(object : SalixCallback<RenewToken>(context) {

                override fun onSuccess(response: Response<RenewToken>) {

                    val renewToken = response.body()
                    runBlocking {
                        (context as MobileApplication).dataStoreApp.editDataStoreKey(
                            TOKEN, renewToken!!.id
                        )
                        (context).dataStoreApp.editDataStoreKey(
                            TTL, renewToken!!.ttl
                        )
                        (context).dataStoreApp.editDataStoreKey(
                            TOKENCREATED, Date().time
                        )
                    }

                    _renewTokenResponse.value = renewToken

                }

                override fun onError(t: Throwable) {

                    _renewTokenResponse.value = RenewToken(
                        "", 0, true, getMessageFromAllResponse(
                            nameofFunction(this), t.message!!
                        )
                    )

                }

            })
    }
}
