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

import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.ImageView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import es.verdnatura.R
import es.verdnatura.databinding.FragmentExpeditionLoadunloadDeliveryBinding
import es.verdnatura.db.DeliveryDatabase
import es.verdnatura.domain.toDateString
import es.verdnatura.domain.toast
import es.verdnatura.presentation.base.BaseFragment
import es.verdnatura.presentation.base.database
import es.verdnatura.presentation.common.OnOptionsSelectedListener
import es.verdnatura.presentation.common.ToolBarAdapterTooltip
import es.verdnatura.presentation.view.feature.delivery.activity.SignedActivity
import es.verdnatura.presentation.view.feature.delivery.adapters.ExpeditionLoadUnloadAdapter
import es.verdnatura.presentation.view.feature.delivery.model.ClientTicket
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoLoadUnload
import es.verdnatura.presentation.view.feature.delivery.model.ExpeditionInfoPending
import es.verdnatura.presentation.view.feature.delivery.model.RouteLoaded
import es.verdnatura.presentation.view.feature.delivery.viewmodels.DeliveryViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.util.Date


class LoadUnloadFragment(
    var title: String = "",
    var state: String = "",
    var entryPoint: String,
    var clientTicketList: ArrayList<ClientTicket>?

) : BaseFragment<FragmentExpeditionLoadunloadDeliveryBinding, DeliveryViewModel>(
    DeliveryViewModel::class
) {

    private var adapter: ExpeditionLoadUnloadAdapter? = null
    private var originalItem: Int = 0
    private lateinit var myList: MutableList<ExpeditionInfoLoadUnload>
    private var counterCalls = 0
    private var counterResponse = 0
    private var route = 0
    private var addressFk = 0
    private lateinit var db: DeliveryDatabase

    companion object {
        fun newInstance(
            title: String,
            state: String,
            entryPoint: String,
            clientTicketList: ArrayList<ClientTicket>? = null
        ) =
            LoadUnloadFragment(title, state, entryPoint, clientTicketList)
    }

    override fun getLayoutId(): Int = R.layout.fragment_expedition_loadunload_delivery

    @RequiresApi(Build.VERSION_CODES.O)
    override fun init() {
        try {
            route = JSONObject(entryPoint).get("route").toString().toInt()
            addressFk = JSONObject(entryPoint).get("address").toString().toInt()
        } catch (ex: Exception) {
        }

        setEvents()
        setToolBar()
        setSwitchButon()
        binding.scanInput.requestFocus()
        viewModel.getExpeditionFromRoute(route)

        super.init()

    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        db = database(requireContext().applicationContext)
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun setToolBar() {
        ma.hideBottomNavigation(View.GONE)
        binding.mainToolbar.toolbarTitle.visibility = View.VISIBLE
        binding.mainToolbar.toolbarSubtitle.visibility = View.VISIBLE
        binding.mainToolbar.toolbarSubtitle.setTextColor(requireContext().getColor((R.color.verdnatura_pumpkin_orange)))
        binding.mainToolbar.toolbarIcons.visibility = View.VISIBLE
        binding.mainToolbar.switchButton.visibility = if (state != "DELIVERED") {
            View.VISIBLE
        } else {
            View.GONE
        }
        binding.mainToolbar.toolbarTitle.text = title

        val listIcons: ArrayList<ImageView> = ArrayList()
        val iconConfirm = ImageView(context)
        val iconSign = ImageView(context)

        iconConfirm.setImageResource(R.drawable.ic_confirm)
        iconSign.setImageResource(R.drawable.ic_sign)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            iconConfirm.tooltipText = getTooltip(R.drawable.ic_confirm)
        }

        listIcons.add(
            if (state == "DELIVERED") {
                iconSign
            } else {
                iconConfirm
            }
        )


        binding.mainToolbar.toolbarIcons.adapter =
            ToolBarAdapterTooltip(listIcons, object : OnOptionsSelectedListener {

                override fun onOptionsItemSelected(item: Drawable) {
                    try {

                        when (item) {
                            iconConfirm.drawable -> {
                                saveLoaded()
                                setExpeditionsState(myList, state)
                            }

                            iconSign.drawable -> {
                                setExpeditionsState(myList, state)
                                //openSignActivity()
                            }
                        }
                    } catch (ex:Exception){
                        //Tarea 5313
                        getString(R.string.errorNotData).toast(requireContext())
                    }

                }

            })

        binding.mainToolbar.toolbarIcons.layoutManager =
            LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
        binding.mainToolbar.toolbarIcons.visibility = View.VISIBLE
    }

    private fun saveLoaded() {
        lifecycleScope.launch {
            withContext(Dispatchers.IO) {
                db.routesDao().insertLoaded(RouteLoaded(route.toLong(), toDateString(Date())))
            }
        }


    }

    private fun setExpeditionsState(list: MutableList<ExpeditionInfoLoadUnload>, state: String) {

        if (list.filter { it.code == state }.isNotEmpty()) {
            if (list.filter { it.code == state }.size == list.size) {
                binding.splashProgress.visibility = View.VISIBLE
                viewModel.expeditionState_add(list.filter { it.code == state }, state)
                counterCalls = 1
            } else {
                val alertDialog = android.app.AlertDialog.Builder(requireContext()).create()
                alertDialog.setTitle(getString(R.string.info))
                alertDialog.setMessage(getString(R.string.expeditionTotal))
                alertDialog.setButton(
                    android.app.AlertDialog.BUTTON_NEUTRAL, getString(R.string.save)
                ) { dialog, which ->

                    counterCalls = 2
                    if (list.filter { it.code == state }.isEmpty()) {
                        counterCalls--
                    } else {
                        viewModel.expeditionState_add(list.filter { it.code == state }, state)
                    }
                    if (list.filter { it.code != state && it.code != "FOUND" }.isEmpty()) {
                        counterCalls--
                    } else {
                        viewModel.expeditionState_add(
                            list.filter { it.code != state && it.code != "FOUND" },
                            "LOST"
                        )
                    }

                }
                alertDialog.setButton(
                    android.app.AlertDialog.BUTTON_POSITIVE, getString(R.string.ordenar)
                ) { dialog, which ->
                    createList(list.sortedByDescending { it.code } as MutableList<ExpeditionInfoLoadUnload>)
                }
                alertDialog.show()
            }
        } else {
            openSignActivity()

        }

    }

    private fun openSignActivity() {
        val intent = Intent(requireContext(), SignedActivity::class.java)

        intent.putExtra(
            "clientTicketList",
            clientTicketList!!.first()
        )

        intent.putExtra("objectSigned", "ticket") //cmr
        startActivity(intent)
        requireActivity().onBackPressed()
    }

    private fun openAppDelivery() {
        val i = Intent()
        val manager: PackageManager = requireContext().packageManager
        val info: PackageInfo = manager.getPackageInfo(requireContext().packageName, 0)
        val version = info.versionName

        if (version.contains("Beta")) {
            i.setClassName(
                "verdnatura.es.repartoverdnatura.sfusion",
                "verdnatura.es.repartoverdnatura.ExpeditionSummaryActivity"
            )
        } else {
            i.setClassName(
                "verdnatura.es.repartoverdnatura",
                "verdnatura.es.repartoverdnatura.ExpeditionSummaryActivity"
            )
        }
        i.putExtra("app", "picking")
        startActivity(i)
    }

    private fun setEvents() {
        binding.mainToolbar.backButton.setOnClickListener {
            requireActivity().onBackPressed()
        }

        binding.scanInput.setOnEditorActionListener { _, actionId, _ ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_ACTION_DONE || actionId == 0 || actionId == EditorInfo.IME_ACTION_NEXT) {
                if (!binding.scanInput.text.isNullOrEmpty()) {

                    try {
                        markExpedition(
                            binding.scanInput.text.toString().toInt(),
                            if (!binding.mainToolbar.switchButton.isChecked) {
                                state
                            } else {
                                "FOUND"
                            },

                            )
                        if (state != "DELIVERED") {

                            binding.mainToolbar.toolbarTitle.text =
                                if (!binding.mainToolbar.switchButton.isChecked) {
                                    getString(R.string.loading)
                                } else {
                                    getString(R.string.unloading)
                                }
                        }

                    } catch (ex: Exception) {
                        getString(R.string.errorExpedition).toast(context, Toast.LENGTH_SHORT)
                    }
                    binding.scanInput.setText("")
                }

                return@setOnEditorActionListener true
            }
            false
        }

        binding.scanInput.requestFocus()
    }

    private fun markExpedition(expedNumber: Int, state: String) {

        var found = false

        if (myList.filter { it.id == expedNumber }.filter { it.code == state }.isNotEmpty()) {
            ma.messageWithSound(getString(R.string.expeditionMarked), null, true)
        } else {
            for (exped in myList) {
                if (exped.id == expedNumber) {
                    found = true
                    exped.code = state
                    break
                }
            }
            if (found) {
                ma.messageWithSound("", false, true, isToasted = false)
            } else {
                ma.messageWithSound("", true, true, isToasted = null)
            }
        }

        if (binding.mainToolbar.switchButton.isChecked) {
            counterCalls = 1
            binding.splashProgress.visibility = View.VISIBLE
            viewModel.expeditionState_add(myList.filter { it.code == state }, state)
        } else {
            updateCount(myList, state)
        }
    }

    @RequiresApi(Build.VERSION_CODES.O)
    override fun observeViewModel() {
        with(viewModel) {
            expeditionInfoLoadUnloadList.observe(viewLifecycleOwner) {
                binding.splashProgress.visibility = View.GONE
                createList(it.list as MutableList<ExpeditionInfoLoadUnload>)
            }
            routeInfoList.observe(viewLifecycleOwner) {
                binding.splashProgress.visibility = View.GONE
                if (it.list.isNotEmpty()) {
                    binding.mainToolbar.toolbarIcons.visibility = View.VISIBLE
                    binding.mainToolbar.switchButton.visibility = View.VISIBLE
                } else {
                    binding.scanInput.setText("")
                    binding.mainToolbar.toolbarIcons.visibility = View.GONE
                    binding.mainToolbar.switchButton.visibility = View.GONE
                }
            }
            responseStateAdd.observe(viewLifecycleOwner) {
                binding.splashProgress.visibility = View.GONE
                if (!it.isError) {
                    counterResponse = counterResponse + 1
                    if (counterResponse == counterCalls) {
                        // viewModel.getExpeditionFromRoute(route)
                        if (!binding.mainToolbar.switchButton.isChecked) {
                            if (state == "DELIVERED") {
                                openSignActivity()
                            } else {
                                requireActivity().onBackPressed()
                            }
                        } else {
                            binding.mainToolbar.switchButton.isChecked = false
                        }
                        counterResponse = 0
                        counterCalls = 0
                    }
                } else {
                    ma.messageWithSound(it.errorMessage, true, true, "Error", true)
                    openSignActivity()
                }

            }
            responseStateList.observe(viewLifecycleOwner) {
                binding.splashProgress.visibility = View.GONE
                ma.messageWithSound(it.errorMessage, true, true, "", true)
                savePendingExpeditions()
                openSignActivity()
            }

            responseLoadList.observe(viewLifecycleOwner) {
                binding.splashProgress.visibility = View.GONE
                createList(mutableListOf(), true)
            }
        }
    }

    private fun savePendingExpeditions() {
        lifecycleScope.launch {
            withContext(Dispatchers.IO) {

                var myListPending = myList.map { item ->
                    ExpeditionInfoPending(
                        id = item.id,
                        ticketFk = item.ticketFk,
                        routeFk = item.routeFk,
                        addressFk = item.addressFk,
                        itemPackingTypeConcat = item.itemPackingTypeConcat,
                        city = item.city,
                        street = item.street,
                        code = if (item.code == "DELIVERED" || item.code == "ON DELIVERY") {
                            item.code
                        } else {
                            "LOST"
                        },
                        nickname = item.nickname,
                        postalCode = item.postalCode
                    )
                } as MutableList<ExpeditionInfoPending>

                db.expedicionDao().insertPending(myListPending)

            }
        }

    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun setSwitchButon() {
        binding.mainToolbar.switchButton.tooltipText = getString(R.string.expeditionMarkLost)
        binding.mainToolbar.switchButton.setOnCheckedChangeListener { buttonView, isChecked ->
            binding.mainToolbar.switchButton.tooltipText = if (isChecked)
                getString(R.string.expeditionMarkFound) else
                getString(R.string.expeditionMarkLost)


            binding.mainToolbar.toolbarTitle.text = if (isChecked) {
                getString(R.string.unloading)
            } else {
                getString(R.string.loading)
            }
            getString(R.string.unloading)

        }

    }

    private fun createList(list: MutableList<ExpeditionInfoLoadUnload>, getSaved: Boolean = false) {


        lifecycleScope.launch {
            withContext(Dispatchers.IO) {


                if (getSaved) {
                    myList =
                        db.expedicionDao()
                            .getAllPending(route)
                    if (myList.isEmpty()) {
                        myList =
                            db.expedicionDao()
                                .getAll(route)
                    }

                } else {
                    db.expedicionDao().insert(list)
                    myList = list
                }

            }
            if (addressFk != 0) {
                myList =
                    myList.filter { it.addressFk == addressFk } as MutableList<ExpeditionInfoLoadUnload>
            } else {
                myList.filter {
                    it.routeFk == route
                }
            }
            adapter = ExpeditionLoadUnloadAdapter(myList)
            binding.expeditionloadunloadRecyclerview.adapter = adapter
            binding.expeditionloadunloadRecyclerview.layoutManager =
                LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
            binding.mainToolbar.toolbarSubtitle.text =
                getString(
                    R.string.summaryCount,
                    myList.filter { it.code == state }.size,
                    myList.size
                )

            setListPosition(myList)
        }


    }

    private fun updateExpeditionTable(list: List<ExpeditionInfoLoadUnload>) {
        lifecycleScope.launch {
            withContext(Dispatchers.IO) {
                db.expedicionDao().insert(list.filter { it.routeFk == route }
                    .filter { it.addressFk == addressFk } as MutableList<ExpeditionInfoLoadUnload>)

            }
        }

    }

    private fun getExpeditionTable(myRoute: Int) {
        lifecycleScope.launch {
            withContext(Dispatchers.IO) {
                myList =
                    db.expedicionDao().getAll(myRoute) as MutableList<ExpeditionInfoLoadUnload>
            }

        }
    }

    private fun setListPosition(list: MutableList<ExpeditionInfoLoadUnload>) {
        for (i in list.indices) {
            if (list[i].code != state) {
                binding.expeditionloadunloadRecyclerview.scrollToPosition(i)
                break
            }
        }
    }

    private fun updateCount(list: MutableList<ExpeditionInfoLoadUnload>, state: String) {

        val countMarked =
            list.filter { it.code == state }.size
        binding.mainToolbar.toolbarSubtitle.text =
            getString(R.string.summaryCount, countMarked, list.size)

        if (countMarked == list.size) {
            setExpeditionsState(list, state)
        }
        adapter!!.notifyDataSetChanged()
    }
}