package com.doverfuelingsolutions.issp.view.fragment

import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.res.ResourcesCompat
import androidx.core.os.bundleOf
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import com.doverfuelingsolutions.issp.DFSApplication
import com.doverfuelingsolutions.issp.R
import com.doverfuelingsolutions.issp.api.SystemApi
import com.doverfuelingsolutions.issp.api.enums.PaymentId
import com.doverfuelingsolutions.issp.data.GlobalData
import com.doverfuelingsolutions.issp.databinding.FragmentPayScanCodeBinding
import com.doverfuelingsolutions.issp.driver.lib.ScanCodeManager
import com.doverfuelingsolutions.issp.fusion.FusionManager
import com.doverfuelingsolutions.issp.utils.DFSToastUtil
import com.doverfuelingsolutions.issp.utils.StringUtil
import com.doverfuelingsolutions.issp.utils.ValidateUtil.Companion.isAliPaymentQRCode
import com.doverfuelingsolutions.issp.utils.ValidateUtil.Companion.isPositiveInt
import com.doverfuelingsolutions.issp.utils.ValidateUtil.Companion.isWXPaymentQRCode
import com.doverfuelingsolutions.issp.utils.sp.SPUtil
import com.doverfuelingsolutions.issp.view.MainActivity
import com.wayne.www.waynelib.fdc.message.DeviceClass
import com.wayne.www.waynelib.util.log.DFSLog
import com.wayne.www.waynelib.webservice.entity.PosTrx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

class FragmentPayScanCode private constructor() : FragmentBasic() {

    companion object {
        fun build(dc: DeviceClass, posTrx: PosTrx): FragmentPayScanCode {
            return FragmentPayScanCode().apply {
                arguments = bundleOf(
                    Pair("dc", dc),
                    Pair("posTrx", posTrx),
                )
            }
        }
    }

    private lateinit var dc: DeviceClass
    private lateinit var posTrx: PosTrx

    override val title = StringUtil.get(R.string.pay_by_qr)
    override val countdownTime: Int = -1

    private lateinit var binding: FragmentPayScanCodeBinding
    private val viewModel = PayScanCodeViewModel()

    private val scanCodeManager = ScanCodeManager()

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

        val sDC = arguments?.getSerializable("dc")
        val sPos = arguments?.getSerializable("posTrx")
        if (sDC is DeviceClass && sPos is PosTrx) {
            dc = sDC
            posTrx = sPos
        } else {
            DFSToastUtil.fail("no DeviceClass or PosTrx")
            (requireActivity() as MainActivity).fragmentRouter.pop()
        }

        lifecycleScope.launchWhenCreated { scanCodeManager.create() }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        if (!this::binding.isInitialized) {
            binding = DataBindingUtil.inflate(inflater, R.layout.fragment_pay_scan_code, container, false)
            binding.lifecycleOwner = this
            binding.viewModel = viewModel.apply {
                nozzle.value = dc.nozzleNo
                amount.value = dc.myAmount
                netAmount.value = posTrx.myNetAmount
                discount.value = posTrx.myDiscount
                volume.value = dc.volume
                oil.value = dc.productName
                time.value = dc.endTimeStamp.substring(5)
            }
        }
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        startPay()
    }

    override fun onDestroy() {
        super.onDestroy()

        scanCodeManager.destroy()
    }

    private fun startPay() {
        lifecycleScope.launchWhenStarted {
            if (!scanCodeManager.isAvailable) {
                DFSToastUtil.fail(StringUtil.get(R.string.fail_behave_reason, StringUtil.get(R.string.init_scanner), StringUtil.get(R.string.plz_check_scanner)))
                return@launchWhenStarted
            }

            val scanValue = scanCodeManager.start()
            if (scanValue == null || (scanValue.length != 18 && scanValue.length != 19)) {
                DFSToastUtil.fail(R.string.plz_correct_pay_code)
                startPay()
                return@launchWhenStarted
            }

            val paymentId = GlobalData.paymentId.get()
            when(paymentId) {
                PaymentId.ALI_PAYMENT.paymentId -> { //支付宝支付
                    if (scanValue.length != 18 || !isAliPaymentQRCode(scanValue)) {
                        DFSToastUtil.fail(R.string.plz_correct_pay_code)
                        startPay()
                        return@launchWhenStarted
                    }
                }
                PaymentId.WX_PAYMENT.paymentId -> { //微信支付
                    if (scanValue.length != 18 || !isWXPaymentQRCode(scanValue)) {
                        DFSToastUtil.fail(R.string.plz_correct_pay_code)
                        startPay()
                        return@launchWhenStarted
                    }
                }
                PaymentId.ALL_IN_PAYMENT.paymentId, PaymentId.ALL_IN_PAYMENT_V2.paymentId -> { //通联或通联分账
                    if (scanValue.length != 18 || (!isWXPaymentQRCode(scanValue) && !isAliPaymentQRCode(scanValue))) {
                        DFSToastUtil.fail(R.string.plz_correct_pay_code)
                        startPay()
                        return@launchWhenStarted
                    }
                }
                PaymentId.UNION_FAST_PAYMENT.paymentId -> { //云闪付
                    if (!isPositiveInt(scanValue)) {
                        DFSToastUtil.fail(R.string.plz_correct_pay_code)
                        startPay()
                        return@launchWhenStarted
                    }
                }
            }

            val dialog = loading(R.string.in_pay,false)

            val discount = SystemApi.getDiscount(posTrx, scanValue)
            if (discount.success && discount.data != null) {
                posTrx = discount.data
            } else {
                DFSLog.e(discount.message)
            }

            GlobalData.isPaying = true
            val result = SystemApi.pay(posTrx, scanValue)
            GlobalData.isPaying = false
            dialog.dismiss()

            if ((result.success && result.data != null) || (!result.success && result.message == "此订单已支付，请勿重复支付")) {
                // 支付成功后，移除本地云订单，清单
                GlobalScope.launch(Dispatchers.IO) {
                    SPUtil.removeLockOrder(dc)
                    val resultClear = FusionManager.clearOrder(dc)
                    if (resultClear.success) {
                        dc.state = "Cleared"
                        SPUtil.removeUnclearedOrder(dc)
                        SPUtil.removeWayneOrder(dc)
                    } else {
                        // 失败则记下来，后续再尝试消单
                        SPUtil.addUnclearedOrder(dc)
                    }

                }

                // 获取加油员名称
                val resultInfo = SystemApi.getPosTicketInfo(posTrx.id)


                if (result.success) {
                    (requireActivity() as MainActivity).fragmentRouter.push(FragmentPayResult.build(dc, result.data!!.PosTrx,
                        resultInfo.data?.employee ?: "",resultInfo.data?.qrCodeStr ?: ""))
                } else {
                    DFSToastUtil.fail(result.message)
                    (requireActivity() as MainActivity).fragmentRouter.popBottom()
                }
            } else {
                DFSToastUtil.fail(result.message)
                viewModel.scanTip.value = StringUtil.get(R.string.plz_scan_again)
                startPay()
            }
        }
    }

    class PayScanCodeViewModel : ViewModel() {
        val nozzle = MutableLiveData(1)
        val amount = MutableLiveData("0.00")
        val netAmount = MutableLiveData("0.00")
        val discount = MutableLiveData("0.00")
        val scanTip = MutableLiveData(StringUtil.get(R.string.plz_scan))
        val volume = MutableLiveData("0.00")
        val oil = MutableLiveData("")
        val time = MutableLiveData("12-12")
    }
}