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

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import com.google.gson.JsonObject
import es.verdnatura.R
import es.verdnatura.domain.SalixCallback
import es.verdnatura.domain.formatWithQuotes
import es.verdnatura.domain.userCases.GetItemFromBarcodeUseCase
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.ItemShelvingSalix
import es.verdnatura.presentation.common.ResponseHasOlder
import es.verdnatura.presentation.view.feature.claim.fragment.reubication.model.Reubication
import es.verdnatura.presentation.view.feature.claim.fragment.reubication.model.ReubicationList
import es.verdnatura.presentation.view.feature.ubicador.model.ItemBuy
import es.verdnatura.presentation.view.feature.ubicador.model.ItemShelvingNewer
import es.verdnatura.presentation.view.feature.ubicador.model.ItemShelvingNewerList
import es.verdnatura.presentation.view.feature.ubicador.model.ItemUbicador
import es.verdnatura.presentation.view.feature.ubicador.model.ItemUbicadorListNew
import es.verdnatura.presentation.view.feature.ubicador.model.ItemUbicadorListVO
import es.verdnatura.presentation.view.feature.ubicador.model.ItemUbicadorVO
import es.verdnatura.presentation.view.feature.workermistake.model.MakeMultiSalix
import retrofit2.Call
import retrofit2.Response

class UbicadorViewModel(val context: Context) : BaseViewModel(context) {
    private val getItemFromBarcodeUseCase = GetItemFromBarcodeUseCase(salix)

    private val _shelvingList by lazy { MutableLiveData<ItemUbicadorListVO>() }

    private val _responseUbicator by lazy { MutableLiveData<Boolean>() }
    val responseUbicator: LiveData<Boolean>
        get() = _responseUbicator

    private val _responseHasOlder by lazy { MutableLiveData<ResponseHasOlder>() }
    val responseHasOlder: LiveData<ResponseHasOlder>
        get() = _responseHasOlder
    val loadResponseHasOlder: LiveData<Event<ResponseHasOlder>> =
        _responseHasOlder.map { Event(it) }

    val loadShelvingList: LiveData<Event<ItemUbicadorListVO>> = _shelvingList.map { Event(it) }

    private val _shelvingListNew by lazy { MutableLiveData<ItemUbicadorListNew>() }
    val loadShelvingListNew: LiveData<Event<ItemUbicadorListNew>> =
        _shelvingListNew.map { Event(it) }

    private val _shelvingListItemNewer by lazy { MutableLiveData<ItemShelvingNewerList>() }
    val loadShelvingListItemNewer: LiveData<Event<ItemShelvingNewerList>> =
        _shelvingListItemNewer.map { Event(it) }

    private val _reubicationList by lazy { MutableLiveData<ReubicationList>() }

    val loadReubicationList: LiveData<Event<ReubicationList>> = _reubicationList.map { Event(it) }

    private val _responseCode by lazy { MutableLiveData<Int?>() }
    val responseCode: LiveData<Int?>
        get() = _responseCode

    val loadResponseCode: LiveData<Event<Int?>> = _responseCode.map { Event(it) }

    private val _responseAddList by lazy { MutableLiveData<Boolean>() }
    val responseAddList: LiveData<Boolean> = _responseAddList

    val loadAddList: LiveData<Event<Boolean>> = _responseAddList.map { Event(it) }

    private val _responseLogAdd by lazy { MutableLiveData<Any>() }
    val responseLogAdd: LiveData<Any>
        get() = _responseLogAdd

    fun itemShelvingList(
        vShelvingFk: String
    ) {
        salix.itemShelvingList(params = listOf(vShelvingFk.uppercase()).formatWithQuotes()).enqueue(
            object : SalixCallback<List<ItemUbicadorVO>>(context) {
                override fun onSuccess(response: Response<List<ItemUbicadorVO>>) {
                    _shelvingList.value = response.body()?.let { ItemUbicadorListVO(it) }
                }

                override fun onError(t: Throwable) {
                    val listError: ArrayList<ItemUbicadorVO> = ArrayList()
                    listError.add(
                        ItemUbicadorVO(
                            0,
                            isError = true,
                            errorMessage = getMessageFromAllResponse(
                                nameofFunction(this),
                                t.message!!,
                            ),
                        ),
                    )
                    _shelvingList.value = ItemUbicadorListVO(listError)
                }

            },
        )
    }

    fun itemShelvingListNew(
        vShelvingFk: String
    ) {
        salix.itemShelvingListNew(params = listOf(vShelvingFk.uppercase()).formatWithQuotes())
            .enqueue(
                object : SalixCallback<List<ItemUbicador>>(context) {
                    override fun onSuccess(response: Response<List<ItemUbicador>>) {
                        _shelvingListNew.value = response.body()?.let { ItemUbicadorListNew(it) }
                    }

                },
            )
    }

    fun shelvingPriorityUpdate(
        priority: Int, shelving: String

    ) {
        salix.updateShelvingPriority(
            where = JsonObject().apply { addProperty("code", shelving) },
            params = hashMapOf("priority" to priority)
        ).enqueue(object : SalixCallback<Any>(context) {})
    }

    fun itemShelvingAddList(
        shelving: String, items: Any, isChecking: Boolean, warehouse: Int
    ) {
        salix.itemShelvingAddList(
            arrayListOf(shelving, items, isChecking, warehouse).formatWithQuotes()
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value =
                    true

            }

        })
    }

    fun itemShelvingAdd(
        shelving: String,
        item: Number,
        quantity: Int,
        packing: Int?,
        warehouse: Int,
        grouping: Int?,
    ) {
        salix.itemShelvingAdd(
            arrayListOf(
                shelving,
                item,
                quantity,
                null,
                grouping,
                packing,
                warehouse,
            ).formatWithQuotes()
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onResponse(call: Call<Any>, response: Response<Any>) {

                _responseUbicator.value =
                    true
                super.onResponse(call, response)
            }

        })
    }

    fun itemShelvingMakeEdit(
        quantity: Int, packing: Int?, itemShelvingFk: Int, grouping: Int?, available: Int?

    ) {
        salix.itemShelvingUpdate(
            params = ItemShelvingSalix(
                visible = quantity,
                packing = packing,
                grouping = grouping,
                available = available
            ),
            id = itemShelvingFk,
        ).enqueue(object : SalixCallback<ItemUbicador?>(context) {
            override fun onSuccess(response: Response<ItemUbicador?>) {
                _responseUbicator.value = true

            }

        })
    }

    fun getInfoFromBuy(
        itemShelvingFk: Number, buyFk: Number

    ) {
        salix.getInfoFromBuyId(
            id = buyFk,
        ).enqueue(object : SalixCallback<ItemBuy>(context) {
            override fun onSuccess(response: Response<ItemBuy>) {
                itemShelvingUpdateFromBuy(itemShelvingFk, response.body().let { it as ItemBuy })
            }

            override fun onError(t: Throwable) {
                val newThrowable = Throwable(context.getString(R.string.errorInputBuyFk), t)
                super.onError(newThrowable)
            }
        })
    }

    fun setParking(
        shelving: String, parking: String
    ) {
        salix.setParking(arrayListOf(shelving, parking).formatWithQuotes())
            .enqueue(object : SalixCallback<Any>(context) {
                override fun onResponse(call: Call<Any>, response: Response<Any>) {
                    _responseUbicator.value = true
                    super.onResponse(call, response)

                }
            })
    }

    fun hasItemOlder(
        shelvingFk: String,
        parking: String,

        ) {
        salix.getListItemNewer(shelvingFk, parking)
            .enqueue(object : SalixCallback<List<ItemShelvingNewer>>(context) {

                override fun onSuccess(response: Response<List<ItemShelvingNewer>>) {

                    if (response.body()!!.isEmpty()) {
                        setParking(shelvingFk, parking)
                    } else {
                        _shelvingListItemNewer.value =
                            response.body()?.let {
                                ItemShelvingNewerList(
                                    it,
                                    originalParking = parking,
                                    originalShelvingFk = shelvingFk
                                )
                            }
                    }

                }

            })
    }

    fun itemShelvingMerge(
        vShelf: Int, shelvingFk: String

    ) {
        salix.itemShelvingsUpdate(
            where = JsonObject().apply { addProperty("id", vShelf) },
            params = hashMapOf("shelvingFk" to shelvingFk)
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                super.onSuccess(response)
                itemShelvingAlternative(
                    shelvingFk = shelvingFk,
                )
            }
        })
    }

    fun itemShelvingDeleteChecked(
        vShelvingFk: String

    ) {
        salix.itemShelvingsUpdate(
            where = JsonObject().apply { addProperty("shelvingFk", vShelvingFk) },
            params = hashMapOf("isChecked" to null)
        ).enqueue(object : SalixCallback<Any>(context) {

            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value = true
                super.onSuccess(response)
            }
        })
    }

    fun itemShelvingUpdateFromBuy(
        itemShelvingFk: Number, itemBuy: ItemBuy

    ) {
        salix.itemShelvingsUpdate(
            where = JsonObject().apply { addProperty("id", itemShelvingFk) },
            params = JsonObject().apply {
                addProperty("itemFk", itemBuy.itemFk)
                addProperty("buyFk", itemBuy.id)
                addProperty("grouping", itemBuy.grouping)
                addProperty("packing", itemBuy.packing)
                addProperty("packagingFk", itemBuy.packagingFk)
            })
            .enqueue(object : SalixCallback<Any>(context) {

                override fun onSuccess(response: Response<Any>) {
                    _responseUbicator.value = true
                    super.onSuccess(response)
                }
            })
    }

    fun shelvingLogAdd(
        code: String
    ) {
        salix.shelvingLogAdd(hashMapOf("code" to code))
            .enqueue(object : SalixCallback<Any>(context) {

                override fun onSuccess(response: Response<Any>) {
                    _responseLogAdd.value = response.message()
                }

            })
    }

    fun itemShelvingAlternative(
        shelvingFk: String,

        ) {
        salix.itemShelvingAlternative(shelvingFk)
            .enqueue(object : SalixCallback<ArrayList<Reubication>>(context) {

                override fun onSuccess(response: Response<ArrayList<Reubication>>) {
                    _reubicationList.value = response.body()?.let { ReubicationList(it) }
                }
            })
    }

    fun clearShelvingList(
        shelvingFk: String,

        ) {

        salix.itemShelvingsUpdate(
            where = JsonObject().apply { addProperty("shelvingFk", shelvingFk) },
            JsonObject().apply {
                addProperty("visible", 0)
                addProperty("available", 0)
            }
        ).enqueue(object : SalixCallback<Any>(context) {

            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value = true
                super.onSuccess(response)
            }
        })
    }

    fun updateIsChecked(
        itemShelvingFk: Int

    ) {

        salix.itemShelvingUpdate(
            id = itemShelvingFk,
            params = hashMapOf("isChecked" to 1)
        ).enqueue(object : SalixCallback<ItemUbicador?>(context) {

            override fun onSuccess(response: Response<ItemUbicador?>) {
                _responseUbicator.value = true
            }
        })
    }

    fun shelvingChangeSalix(
        shelvingFkIn: String, shelvingFkOut: String

    ) {

        salix.itemShelvingsUpdate(
            where = JsonObject().apply { addProperty("shelvingFk", shelvingFkIn) },
            hashMapOf("shelvingFk" to shelvingFkOut)
        ).enqueue(object : SalixCallback<Any>(context) {

            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value = true
                super.onSuccess(response)
            }
        })
    }

    fun itemShelvingTransfer(
        itemFk: Int, shelvingFk: String

    ) {
        salix.itemShelvingTransfer(arrayListOf(itemFk, shelvingFk).formatWithQuotes())
            .enqueue(object : SalixCallback<Any>(context) {
                override fun onSuccess(response: Response<Any>) {
                    _responseUbicator.value = true
                    super.onSuccess(response)
                }

            })
    }

    fun itemShelvingDelete(itemShelvingFk: Int) {
        salix.itemShelvingsDelete(itemShelvingFk).enqueue(object : SalixCallback<Any>(context) {

            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value = true

            }
        })
    }

    fun itemShelvingSelfConsumption(shelvingFk: String, itemFk: Int, quantity: Int) {
        salix.itemShelvingSelfConsumption(
            arrayListOf(
                shelvingFk, itemFk, quantity
            ).formatWithQuotes()
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseUbicator.value = true
            }
        })
    }

    fun getIdFromCode(code: String) {
        getItemFromBarcodeUseCase.execute(code)
            .enqueue(object : SalixCallback<Int?>(context) {

                override fun onSuccess(response: Response<Int?>) {

                    _responseCode.value = response.body()

                }
            })
    }

    fun itemShelvingMakeMulti(
        shelvingFk: String, items: List<Long>, warehouseFk: Int
    ) {

        salix.upsertItem(MakeMultiSalix(shelvingFk, items, warehouseFk))
            .enqueue(object : SalixCallback<Any>(context) {

                override fun onSuccess(response: Response<Any>) {
                    super.onSuccess(response)
                    _responseUbicator.value = true

                }
            })

    }

}
