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.domain.SilexCallback
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 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 : SilexCallback<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 device_checkLogin(android_id: String) {

        silex.device_checkLogin(android_id)
            .enqueue(object : SilexCallback<LoginDevice>(context) {
                override fun onSuccess(response: Response<LoginDevice>) {
                    if (response.body() != null) {

                        response.body()?.let {

                            _logindevice.value = LoginDevice(
                                it.vMessage, it.vIsAuthorized,
                                isError = false,
                                errorMessage = ""
                            )

                        }
                    } else {
                        _logindevice.value = LoginDevice(
                            isError = true,
                            errorMessage = getMessageFromAllResponse(
                                nameofFunction(this),
                                response.message()
                            )
                        )
                    }

                }

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

    fun getCurrentUserData(
        appName: String,
        versionApp: String,
        android_id: String,
        serialnumber: String? = null
    ) {
        salix.getCurrentUserData().enqueue(object : SilexCallback<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 = android_id,
                    userFk = app.userId!!,
                    serialnumber = serialnumber
                )
                //Tarea 5870
                operator_getDataSalix(app.userId!!)
            }
        })
    }

    /*    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 : SilexCallback<Unit>(context) {

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

            })

    }

    fun checkVersion(nameApp: String) {
        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 5134 no se puede modificar directamente con un upsertWith, hay que modificar front. Y si al hacer login en Salix hacer el insertIgnore en -> operator_add, back de Salix sabe
        //si es de app?
        //salix.operatorAdd()
        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 : SilexCallback<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 : SilexCallback<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 : SilexCallback<RenewToken>(context) {

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

                    val RenewToken = response.body()
                    val prefs = app.getPrefsEditor()
                    prefs.putString("token", RenewToken!!.id)
                    prefs.putLong("ttl", RenewToken!!.ttl)
                    prefs.putLong("tokenCreated", Date().time)
                    _renewTokenResponse.value = RenewToken

                }

                override fun onError(t: Throwable) {

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


                }

            })
    }
}
