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.log.DFSLog
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)
    }

    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 selectedName = ""
    private val oilNameList: List<String> by lazyOf(FusionManager.pumpList.map { it.oilName })
    private val chooseListAdapter: ChooseListAdapter by lazy {
        ChooseListAdapter(
            oilNameList,
            this::selectOilName
        )
    }

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

        lifecycleScope.launch {
            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

            setToolBar(binding.fragmentToolbar)
        }
        return binding.root
    }

    private fun selectOrder(dc: DeviceClass) {
        lifecycleScope.launch {
            when {
                dc.releaseTokenElement == null || dc.releaseTokenAttribute == null -> {
                    DFSToastUtil.fail(R.string.wrong_order_info)
                }
                else -> {
                    if (dc.isLock && !SPUtil.isLockByThis(dc)) {
                        DFSToastUtil.warn(R.string.order_lock_by_other)
                    } else {
                        (activity as MainActivity).setFragment(FragmentPayType.build(dc), true)
                    }
                }
            }
        }
    }

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

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

    private suspend fun loadListData() {
        if (orderList.isEmpty()) loading(R.string.in_get_order)
        if (this::binding.isInitialized) binding.orderListView.scrollTo(0, 0)

        // -1 选油品，非 -1 选枪
        // 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()
        hideLoading()
    }

    private suspend fun loadRemoteData() {
        val result = FusionManager.getAllUnsettledOrder(pumpId)
        if (result.success && result.data != null) {
            // TODO 本地缓存的订单数据（云订单，锁定，待清除订单），需要对照这里的远端数据进行整理
            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.size != result.data.size || getOrderListHash(orderList) != getOrderListHash(result.data)) {
                    if (orderList.isNotEmpty()) orderList.clear()
                    orderList.addAll(result.data)
                    filterOrderListByOilName()
                    orderListAdapter.notifyDataSetChanged()

                    DFSToastUtil.success(R.string.data_refresh)
                }
            }
        }
    }

    private fun getOrderListHash(list: List<DeviceClass>): String {
        return list.joinToString(",") { "${it.pumpNo}-${it.transactionSeqNo}" }
    }

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

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