package com.doverfuelingsolutions.issp.view.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.doverfuelingsolutions.issp.R
import com.doverfuelingsolutions.issp.databinding.FragmentNozzleOrdersBinding
import com.doverfuelingsolutions.issp.fusion.FusionManager
import com.doverfuelingsolutions.issp.utils.DFSToastUtil
import com.doverfuelingsolutions.issp.utils.StringUtil
import com.doverfuelingsolutions.issp.utils.sp.SPUtil
import com.doverfuelingsolutions.issp.view.MainActivity
import com.doverfuelingsolutions.issp.view.adapter.ChooseListAdapter
import com.doverfuelingsolutions.issp.view.adapter.OrderListAdapter
import com.scwang.smart.refresh.header.ClassicsHeader
import com.wayne.www.waynelib.fdc.message.DeviceClass
import kotlinx.coroutines.launch

class FragmentOrderList private constructor(private val pumpId: Int) : FragmentBasic() {

    companion object {
        fun build(pumpId: Int) = FragmentOrderList(pumpId)
    }

    override val title = StringUtil.get(R.string.select_pay_order)
    override val countdownTime: Int = 80

    private lateinit var binding: FragmentNozzleOrdersBinding
    val viewModel = FragmentNozzleViewModel().apply {
        pump.value = pumpId
        isNozzle.value = pumpId != -1
    }

    private val orderList = arrayListOf<DeviceClass>()
    private val orderListAfterFilter = arrayListOf<DeviceClass>()
    private val orderListAdapter = OrderListAdapter(if (pumpId != -1) orderList else orderListAfterFilter, this::selectOrder)
    private var selectedPosition: Int? = null

    private var selectedName = ""
    private val oilNameList = FusionManager.pumpList.map { it.productName }.filter { it.isNotBlank() }
    private val chooseListAdapter = ChooseListAdapter(oilNameList, this::selectOilName, true)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        loadListData()
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        if (!this::binding.isInitialized) {
            binding = DataBindingUtil.inflate(inflater, R.layout.fragment_nozzle_orders, container, false)

            // 油品模式
            if (pumpId == -1) {
                binding.oilList.layoutManager = GridLayoutManager(context, 4)
                binding.oilList.adapter = chooseListAdapter
            }

            binding.orderListView.layoutManager = GridLayoutManager(context, 2)
            binding.orderListView.adapter = orderListAdapter

            binding.smartRefreshLayout.setEnableLoadMore(false)
            binding.smartRefreshLayout.setEnableRefresh(true)
            binding.smartRefreshLayout.setRefreshHeader(ClassicsHeader(requireContext()))
            binding.smartRefreshLayout.setOnRefreshListener { handleRefresh() }

            binding.lifecycleOwner = this
            binding.viewModel = viewModel
        }

        // Adapter has to update if dc is changed in FragmentPayType and route back.
        selectedPosition?.let { orderListAdapter.notifyItemChanged(it) }

        return binding.root
    }

    private fun selectOrder(dc: DeviceClass, type: Int, position: Int) {
        lifecycleScope.launch {
            when {
                dc.releaseTokenElement == null || dc.releaseTokenAttribute == null -> {
                    DFSToastUtil.fail(R.string.wrong_order_info)
                }
                type == 0 -> {
                    if (dc.isLock && !SPUtil.isLockByThis(dc)) {
                        DFSToastUtil.warn(R.string.order_lock_by_other)
                    } else {
                        selectedPosition = position
                        (activity as MainActivity).fragmentRouter.push(FragmentPayType.build(dc))
                    }
                }
                type == 1 && dc.isLock -> {
                    if (SPUtil.isLockByThis(dc)) {
                        val result = FusionManager.lockOrder(dc, false)
                        if (result.success) {
                            dc.state = "Payable"
                            orderListAdapter.notifyItemChanged(position)
                            DFSToastUtil.success(R.string.unlock_order_success)
                        } else {
                            DFSToastUtil.fail(R.string.fail_unlock_order)
                        }
                    } else {
                        DFSToastUtil.warn(R.string.cant_unlock_others)
                    }
                }
            }
        }
    }

    private fun selectOilName(oilName: String, refreshView: Boolean = true) {
        selectedName = oilName
        filterOrderListByOilName()
        if (refreshView) {
            orderListAdapter.notifyDataSetChanged()
        }
    }

    private fun handleRefresh() {
        lifecycleScope.launch {
            loadRemoteData()
            binding.smartRefreshLayout.finishRefresh(200, true, false)
        }
    }

    private fun loadListData() {
        lifecycleScope.launchWhenStarted {
            val dialog = loading(R.string.in_get_order)
            (requireActivity() as MainActivity).fragmentRouter.stopFragmentToolbarTimer()
            binding.orderListView.scrollTo(0, 0)

            // local cache
            if (orderList.isNotEmpty()) orderList.clear()
            if (pumpId == -1) {
                val allPumpOrderList = FusionManager.pumpList.map {
                    SPUtil.getOrderListByPump(it.pumpId)
                }
                val sum = allPumpOrderList.reduce { acc, list ->
                    acc.addAll(list)
                    acc
                }
                sum.sortByDescending { it.releaseTokenAttribute }
                orderList.addAll(sum)
                selectOilName(oilNameList[0], false)
            } else {
                orderList.addAll(SPUtil.getOrderListByPump(pumpId))
            }
            orderListAdapter.notifyDataSetChanged()

            // remote data
            loadRemoteData()
            dialog.dismiss()
            (requireActivity() as MainActivity).fragmentRouter.resumeFragmentToolbarTimer()
        }
    }

    private suspend fun loadRemoteData() {
        val result = FusionManager.getAllUnsettledOrder(pumpId)
        if (result.success && result.data != null) {
            if (pumpId == -1) {
                SPUtil.setAllOrderList(result.data)
            } else {
                SPUtil.setOrderListByPump(pumpId, result.data)
            }
            if (result.data.isEmpty()) {
                DFSToastUtil.info(R.string.no_unpaid_order)
                back()
            } else {
                if (orderList.isNotEmpty()) orderList.clear()
                orderList.addAll(result.data)
                filterOrderListByOilName()
                orderListAdapter.notifyDataSetChanged()
            }
        }
    }

    private fun filterOrderListByOilName() {
        if (orderListAfterFilter.isNotEmpty()) orderListAfterFilter.clear()
        orderListAfterFilter.addAll(orderList.filter { it.productName == selectedName })
    }

    class FragmentNozzleViewModel() : ViewModel() {
        val pump = MutableLiveData(-1)
        val isNozzle = MutableLiveData(true)
    }
}