package es.verdnatura.presentation.view.feature.delivery.viewmodels

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.map
import es.verdnatura.R
import es.verdnatura.domain.SalixCallback
import es.verdnatura.domain.userCases.GetItemFromBarcodeUseCase
import es.verdnatura.presentation.base.BaseViewModel
import es.verdnatura.presentation.common.Event
import es.verdnatura.presentation.common.ExpeditionPrintOut
import es.verdnatura.presentation.common.ResponseSign
import es.verdnatura.presentation.view.feature.delivery.model.ClientTicketList
import es.verdnatura.presentation.view.feature.delivery.model.ClientTicketSalix
import es.verdnatura.presentation.view.feature.delivery.model.DeliveryInfo
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoList
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoLoadUnload
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoLog
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoSummary
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionList
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionSummaryList
import es.verdnatura.presentation.view.feature.delivery.model.FreeLanceDeliveryInfoList
import es.verdnatura.presentation.view.feature.delivery.model.RouteDelivery
import es.verdnatura.presentation.view.feature.delivery.model.RouteDeliveryList
import es.verdnatura.presentation.view.feature.delivery.model.RouteInfo
import es.verdnatura.presentation.view.feature.delivery.model.RouteList
import es.verdnatura.presentation.view.feature.delivery.model.Ticket
import es.verdnatura.presentation.view.feature.delivery.model.TicketObservation
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import org.json.JSONArray
import org.json.JSONObject
import retrofit2.Call
import retrofit2.Response
import java.io.File

class DeliveryViewModel(val context: Context) : BaseViewModel(context) {

    private val getItemFromBarcodeUseCase = GetItemFromBarcodeUseCase(salix)
    private val _isBoxPickingInPrintOut by lazy { MutableLiveData<ExpeditionPrintOut>() }
    val isBoxPickingInPrintOut: LiveData<ExpeditionPrintOut> = _isBoxPickingInPrintOut

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

    private val _expeditionInfoList by lazy { MutableLiveData<ExpeditionInfoList>() }
    val expeditionInfoList: LiveData<ExpeditionInfoList> = _expeditionInfoList

    private val _expeditionInfoLoadUnloadList by lazy { MutableLiveData<ExpeditionList>() }
    val expeditionInfoLoadUnloadList: LiveData<ExpeditionList> = _expeditionInfoLoadUnloadList

    private val _expeditionInfoSummary by lazy { MutableLiveData<ExpeditionSummaryList>() }
    val expeditionInfoSummary: LiveData<ExpeditionSummaryList> = _expeditionInfoSummary

    private val _routeList by lazy { MutableLiveData<RouteList>() }
    val routeList: LiveData<RouteList> = _routeList

    private val _clientTicketList by lazy { MutableLiveData<ClientTicketList>() }
    val clientTicketList: LiveData<ClientTicketList> = _clientTicketList

    private val _routeInfoList by lazy { MutableLiveData<RouteDeliveryList>() }
    val routeInfoList: LiveData<RouteDeliveryList> = _routeInfoList

    private val _freelanceInfoList by lazy { MutableLiveData<FreeLanceDeliveryInfoList>() }
    val freelanceInfoList: LiveData<FreeLanceDeliveryInfoList> = _freelanceInfoList

    private val _companyInfoList by lazy { MutableLiveData<FreeLanceDeliveryInfoList>() }
    val companyInfoList: LiveData<FreeLanceDeliveryInfoList> = _companyInfoList

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

    private val _responseExpeditionStateId by lazy { MutableLiveData<Number>() }
    val responseExpeditionStateId: LiveData<Number> = _responseExpeditionStateId

    private val _responseFindExpeditionId by lazy { MutableLiveData<Number>() }
    val responseFindExpeditionId: LiveData<Number> = _responseFindExpeditionId

    private val _responseDeleteExpedition by lazy { MutableLiveData<Boolean>() }
    val responseDeleteExpedition: LiveData<Boolean> = _responseDeleteExpedition

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

    private val _responseSign by lazy { MutableLiveData<ResponseSign>() }
    val responseSign: LiveData<ResponseSign> = _responseSign

    private val _responseNotes by lazy { MutableLiveData<Boolean>() }
    val responseNotes: LiveData<Boolean> = _responseNotes
    var loadNotes: LiveData<Event<Boolean>> = _responseNotes.map { Event(it) }

    private val _responseObservations by lazy { MutableLiveData<List<TicketObservation>>() }
    val responseObservations: LiveData<List<TicketObservation>> = _responseObservations

    private val _expeditionList by lazy { MutableLiveData<ExpeditionList>() }
    val expeditionList: LiveData<ExpeditionList> = _expeditionList

    val loadRouteList: LiveData<Event<RouteList>> = _routeList.map { Event(it) }

    private val _responseLoadList by lazy { MutableLiveData<Boolean>() }
    val responseLoadList: LiveData<Boolean> = _responseLoadList

    private val _responseStateList by lazy { MutableLiveData<Boolean>() }
    val responseStateList: LiveData<Boolean> = _responseStateList
    fun getTicketObservations(
        listTickets: List<Long>

    ) {
        salix.getTicketObservations(
            filter = """{ "where": { "ticketFk": { "inq": $listTickets } }, 
                |"fields": ["description", "ticketFk", "observationTypeFk"], 
                |"include": [ { "relation": "observationType", 
                |"scope": { "where": { "code": "claim" } } } ] }""".trimMargin()
        ).enqueue(object : SalixCallback<List<TicketObservation>>(context) {
            override fun onSuccess(response: Response<List<TicketObservation>>) {
                _responseObservations.value = response.body()

            }
        })
    }

    fun companyGetFiscaldata(
        userId: Int
    ) {
        salix.companyGetFiscaldata(arrayListOf(userId))
            .enqueue(object : SalixCallback<List<DeliveryInfo>>(context) {
                override fun onSuccess(response: Response<List<DeliveryInfo>>) {
                    _companyInfoList.value = response.body()?.let { FreeLanceDeliveryInfoList(it) }
                }

            })
    }

    fun expeditionGetLog(
        expedition: Number
    ) {
        salix.getExpeditionStates(
            """{"where": {"expeditionFk": $expedition},"include": [{"relation": "expeditionStateType","scope": {"fields": ["id","description"]}}],"fields": {"id": true,"created": true,"typeFk": true}}"""
        ).enqueue(object : SalixCallback<List<ExpeditionInfoLog>>(context) {
            override fun onSuccess(response: Response<List<ExpeditionInfoLog>>) {
                _expeditionInfoList.value = response.body()?.let { ExpeditionInfoList(it) }
            }

        })
    }

    fun getExpeditionFromRoute(
        route: Int
    ) {
        salix.expeditionGetFromRoute(arrayListOf(route))
            .enqueue(object : SalixCallback<List<ExpeditionInfoLoadUnload>>(context) {
                override fun onSuccess(response: Response<List<ExpeditionInfoLoadUnload>>) {
                    _expeditionInfoLoadUnloadList.value =
                        response.body()?.let { ExpeditionList(it) }
                }
            })
    }

    fun getRoutesFromExpedition(
        expedition: Number
    ) {
        salix.getRoutesFromExpedition(
            filter = """{
             "where": {
                "id": $expedition
                },
            "fields": [
            "id",
            "ticketFk"
            ],
            "include": [
            {
                "relation": "ticket",
                "scope": {
                "include": {
                "relation": "route",
                "scope": {
                "fields": [
                "id",
                "created",
                "agencyModeFk",
                "routeFk"
                ],
                "include": {
                "relation": "agencyMode",
                "scope": {
                "include": {
                "relation": "agency",
                "scope": {
                "fields": [
                "name"
                ]
            }
            },
                "fields": [
                "id",
                "agencyFk"
                ]
            }
            }
            }
            },
                "fields": [
                "id",
                "nickname",
                "routeFk"
                ]
            }
            }
            ]
        }""".trim()
        ).enqueue(object : SalixCallback<List<RouteDelivery>>(context) {
            override fun onSuccess(response: Response<List<RouteDelivery>>) {

                _routeInfoList.value = response.body()?.let { RouteDeliveryList(it) }

            }
        })

    }

    fun expeditionStateAddSalix(expeditions: Any) {
        salix.addExpeditionState(expeditions).enqueue(object : SalixCallback<Unit>(context) {
            override fun onSuccess(response: Response<Unit>) {
                super.onSuccess(response)
                _responseStateAdd.value = true
            }

            override fun onError(t: Throwable) {
                super.onError(t)
                _responseStateAdd.value = false
            }

            override fun onFailure(call: Call<Unit>, t: Throwable) {
                //Fallo de red guardamos pendientes
                _responseStateList.value = false
                super.onFailure(call, Throwable(context.getString(R.string.offline)))

            }
        })
    }

    fun findExpedition(expedition: Number, expeditionStateId: Number) {
        salix.findExpedition(
            filter = """{"where":
            {
                "expeditionFk":$expedition,
                "typeFk":$expeditionStateId
                    }
             }""".trimMargin()
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseFindExpeditionId.value = 0

            }

            override fun onError(t: Throwable) {
                _responseFindExpeditionId.value = expedition
            }

        })
    }

    fun deleteExpedition(expeditionIds: ArrayList<Number>) {
        salix.deleteExpedition(
            hashMapOf("expeditionIds" to expeditionIds)
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                super.onSuccess(response)
                _responseDeleteExpedition.value = true

            }

        })
    }

    fun getExpeditionStateId(stateCode: String) {

        salix.getExpeditionStateTypeId(
            filter = """{"where":{"code":"$stateCode"}}""".trimMargin()
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseExpeditionStateId.value =
                    response.body()?.toString()?.let { JSONObject(it).getInt("id") }
            }

        })
    }

    fun getInfoFreelance(
        userId: Int
    ) {
        salix.freelanceGetInfo(arrayListOf(userId))
            .enqueue(object : SalixCallback<List<DeliveryInfo>>(context) {
                override fun onSuccess(response: Response<List<DeliveryInfo>>) {

                    _freelanceInfoList.value =
                        response.body()?.let { FreeLanceDeliveryInfoList(it) }

                }

            })
    }

    fun routeGetExpeditionSummary(
        route: Int
    ) {
        salix.routeGetExpeditionSummary(route)
            .enqueue(object : SalixCallback<List<ExpeditionInfoSummary>>(context) {
                override fun onSuccess(response: Response<List<ExpeditionInfoSummary>>) {
                    _expeditionInfoSummary.value =
                        response.body()?.let { ExpeditionSummaryList(it) }

                }

            })
    }

    fun getRoutes(
    ) {

        salix.getRoutes().enqueue(object : SalixCallback<MutableList<RouteInfo>>(context) {

            override fun onSuccess(response: Response<MutableList<RouteInfo>>) {
                _routeList.value = response.body()?.let { RouteList(it) }
            }

            override fun onError(t: Throwable) {
                //_routeList.value = RouteList()
                _responseLoadList.value = false
                //super.onError(t)

            }

            override fun onFailure(call: Call<MutableList<RouteInfo>>, t: Throwable) {
                _responseLoadList.value = false
            }
        })
    }

    fun getTickets(
        routeId: Long
    ) {
        salix.getTickets("""{"id":$routeId,"order":["priority","id"]}""")
            .enqueue(object : SalixCallback<MutableList<ClientTicketSalix>>(context) {
                override fun onSuccess(response: Response<MutableList<ClientTicketSalix>>) {
                    _clientTicketList.value = response.body()?.let { ClientTicketList(it) }
                }

                override fun onError(t: Throwable) {
                    _responseLoadList.value = false

                }
            })
    }

    fun driverRouteEmail(
        routeId: Long, email: String
    ) {
        salix.driverRouteEmail(id = routeId, hashMapOf("recipient" to email))
            .enqueue(object : SalixCallback<Any>(context) {})
    }

    fun routeUpdate(
        route: RouteInfo
    ) {
        salix.routeUpdate(route.id, route).enqueue(object : SalixCallback<Any>(context) {

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

            }

        })
    }

    fun updateNotesFromDropOff(
        ticketFK: Long, description: String

    ) {
        salix.updateNoteFromDropOff(
            where = """{"ticketFk" : $ticketFK,"observationTypeFk":10}""",
            params = hashMapOf("description" to description)
        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseNotes.value = true
                super.onSuccess(response)

            }
        })
    }

    fun addFropOff(
        ticketFK: Long, note: String

    ) {
        salix.addFropOff(
            ticketFK, note

        ).enqueue(object : SalixCallback<Any>(context) {
            override fun onSuccess(response: Response<Any>) {
                _responseNotes.value = true
                super.onSuccess(response)

            }
        })
    }

    fun imageUpload(
        warehouseId: Number,
        companyId: Number,
        dmsTypeId: Number,
        reference: String,
        description: String,
        hasFile: Boolean,
        file: MultipartBody.Part
    ) {
        salix.imageUpload(warehouseId, companyId, dmsTypeId, reference, description, hasFile, file)
            .enqueue(object : SalixCallback<Any>(context) {})
    }

    fun saveSign(filePath: String, mapQuery: Map<String?, String?>) {
        val filePart = MultipartBody.Part.createFormData(
            "file", File(filePath).name, RequestBody.create(
                MediaType.parse("image/png"), File(filePath)
            )
        )
        salix.saveSign(filePart, mapQuery).enqueue(object : SalixCallback<Any>(context) {

            override fun onSuccess(response: Response<Any>) {
                _responseSign.value = ResponseSign(fileToSign = filePath, isError = false)
                super.onSuccess(response)

            }

            //Otro fallo
            override fun onError(t: Throwable) {
                _responseSign.value = ResponseSign(
                    fileToSign = "",
                    isError = true,
                    message = "Tickets:${File(filePath).name}→${t.message.toString()}"
                )

            }

            //Fallo de red
            override fun onFailure(call: Call<Any>, t: Throwable) {
                _responseSign.value = ResponseSign(fileToSign = "", isError = true)
                super.onFailure(call, t)
            }

        })
    }

    fun isBoxPickingInPrintOut(expeditionFk: Long, barcode: String) {
        getItemFromBarcodeUseCase.execute(barcode).enqueue(object : SalixCallback<Int?>(context) {

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

                if (response.body() != null) {
                    isBoxPickingOk(
                        itemFk = response.body().toString().toLong(),
                        expeditionFk = expeditionFk
                    )
                } else {
                    _responseCode.value = false
                }

            }
        })
    }

    fun isBoxPickingOk(
        expeditionFk: Long, itemFk: Long

    ) {

        salix.isBoxPickingInPrintOut(
            filter = """{"where":{"expeditionFk":$expeditionFk,"itemFk":$itemFk}}"""
        ).enqueue(object : SalixCallback<ExpeditionPrintOut>(context) {

            override fun onSuccess(response: Response<ExpeditionPrintOut>) {
                _isBoxPickingInPrintOut.value = response.body()
            }

            override fun onError(t: Throwable) {
                _isBoxPickingInPrintOut.value = ExpeditionPrintOut(0, 0, false)
            }

        })
    }

}

fun createJSONObject(listTickets: MutableList<Ticket>, note: String): String {
    // Supongamos que tienes la lista de tickets y el valor como los siguientes:
    // val listTickets: List<String> = listOf("4255452", "5454515")
    // Crear el objeto JSON
    val jsonObject = JSONObject()
    val jsonArrayTickets = JSONArray(listTickets)
    jsonObject.put("tickets", jsonArrayTickets)
    jsonObject.put("note", note)

    // Convertir el objeto JSON a un String
    return jsonObject.toString()
}



