package com.doverfuelingsolutions.issp.view

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.net.Uri
import android.os.Bundle
import android.util.Base64
import android.util.Base64InputStream
import android.view.KeyEvent
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
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.R
import com.doverfuelingsolutions.issp.api.SystemApi
import com.doverfuelingsolutions.issp.data.GlobalData
import com.doverfuelingsolutions.issp.databinding.ActivityMainBinding
import com.doverfuelingsolutions.issp.driver.lib.PrintManager
import com.doverfuelingsolutions.issp.fusion.FusionManager
import com.doverfuelingsolutions.issp.fusion.FusionStatus
import com.doverfuelingsolutions.issp.fusion.callback.OnFusionStatus
import com.doverfuelingsolutions.issp.receiver.HomeAndMenuReceiver
import com.doverfuelingsolutions.issp.utils.DFSToastUtil
import com.doverfuelingsolutions.issp.utils.WindowUtil
import com.wayne.www.waynelib.util.log.DFSLog
import com.doverfuelingsolutions.issp.utils.sp.SPUtil
import com.doverfuelingsolutions.issp.view.fragment.FragmentNozzle
import com.doverfuelingsolutions.issp.view.fragment.FragmentReconnect
import com.doverfuelingsolutions.issp.view.fragment.router.FragmentRouter
import com.doverfuelingsolutions.issp.view.fragment.router.OnRouteChangeListener
import com.doverfuelingsolutions.issp.view.util.LoadingDialogBuilder
import com.doverfuelingsolutions.issp.view.util.LoginTokenRefresher
import com.wayne.www.waynelib.fdc.FdcClient
import com.wayne.www.waynelib.fdc.message.DeviceClass
import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.ByteArrayInputStream
import java.io.File
import java.math.BigDecimal
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.HashMap

class MainActivity : AppCompatActivity(),
    View.OnClickListener,
    View.OnLongClickListener,
    OnFusionStatus,
    OnRouteChangeListener {

    companion object {
        fun start(context: Context) {
            Intent(context, MainActivity::class.java).let { context.startActivity(it) }
        }
    }

    private val binding: ActivityMainBinding by lazy {
        DataBindingUtil.setContentView(this, R.layout.activity_main)
    }
    private val mainViewModel: MainViewModel by viewModels()
    val fragmentRouter: FragmentRouter by lazy { FragmentRouter(this, R.id.fragmentBox) }

    private var dialogFusionLinking: AlertDialog? = null
    private var isBlockBackPress = false

    private var homeAndMenuReceiver: HomeAndMenuReceiver? = null
    private var isInLockTaskMode: Boolean = false

    private val orderClearCountMap:HashMap<String,Int> = hashMapOf() //用于记录消单次数

    private val mLoginTokenRefresher = LoginTokenRefresher()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding.lifecycleOwner = this
        binding.mainViewModel = mainViewModel
        binding.handler = this
        binding.clock.setOnLongClickListener(this)
//        register()

        removeData()
        supportActionBar?.hide()
        initView()
        initBanner()

        FusionManager.onFusionStatus = this
        lifecycle.addObserver(FusionManager)

        fragmentRouter.setFragmentToolbar(binding.fragmentToolbar)
        fragmentRouter.setOnRouteChangeListener(this)
        fragmentRouter.push(FragmentReconnect.build())

        mLoginTokenRefresher.start(this)
    }

    private fun removeData() {
//        SPUtil.printData()
        SPUtil.removeLockOrderAndClearOrder() //怀疑自动解锁和自动消单占用太多线程，处理一下
    }

    override fun onResume() {
        super.onResume()
        WindowUtil.setFullscreen(this)
        this.startLockTask()
    }

    override fun onDestroy() {
        super.onDestroy()

        dialogFusionLinking?.dismiss()
        dialogFusionLinking = null
        fragmentRouter.stopFragmentToolbarTimer()
        FusionManager.onFusionStatus = null
        mLoginTokenRefresher.stop()
    }

    @SuppressLint("MissingSuperCall")
    override fun onSaveInstanceState(outState: Bundle) {}

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        lifecycleScope.launchWhenStarted {
            when (requestCode) {
                PreferenceActivity.codeRequestResult -> {
                    data?.let {
                        val isMiddleModified = it.getBooleanExtra(
                            PreferenceActivity.isMiddleModified,
                            false
                        )
                        val isFuelModified = it.getBooleanExtra(
                            PreferenceActivity.isFuelModified,
                            false
                        )
                        val isChooseOrderTypeModified = it.getBooleanExtra(
                            PreferenceActivity.isChooseOrderTypeModified,
                            false
                        )
                        val isRelogin = it.getBooleanExtra(
                            PreferenceActivity.isReLogin,
                            false
                        )

                        if (isRelogin) {
                            stopLockTask()

                            GlobalData.isLogin = false
                            GlobalData.password.set("")
                            GlobalData.accessToken.set("")
                            GlobalData.accessTokenExpire.set(0L)
                            LoginActivity.start(this@MainActivity, bundleOf(Pair(LoginActivity.autoLogin, false)))

                            this@MainActivity.finish()
                            return@let
                        }

                        if (isMiddleModified || FusionManager.stateFusion != FdcClient.FdcClientState.Connected) {
                            setFusionLinkingLoading()
                            FusionManager.restart(true)
                            return@let
                        } else if (isFuelModified && FusionManager.stateFusion == FdcClient.FdcClientState.Connected) {
                            val dialog = LoadingDialogBuilder(this@MainActivity)
                                .setLoadingText(R.string.in_get_fuel)
                                .show()
                            val result = FusionManager.getPumpInfo()
                            dialog.dismiss()
                            if (result.success) {
                                DFSToastUtil.success(R.string.get_fuel_success)
                                initFragmentEntry()
                                return@let
                            } else {
                                DFSToastUtil.fail(R.string.get_fuel_failed)
                                onFusionStatus(FusionStatus.ConnectedWithoutInfo)
                                return@let
                            }
                        }

                        if (isChooseOrderTypeModified) {
                            initFragmentEntry()
                        }
                    }
                }
            }
        }
    }

    override fun onBackPressed() {
        if (!isBlockBackPress) super.onBackPressed()
    }

    override fun onClick(v: View?) {
        when (v) {
            binding.stationLogo,
            binding.stationName -> {
                DFSLog.i("refresh station info")
                lifecycleScope.launchWhenStarted {
                    val resultPhone = SystemApi.sessionInfo()
                    if (resultPhone.success && resultPhone.data != null) {
                        GlobalData.stationTel.set(resultPhone.data.phoneNumber)
                        GlobalData.businessName.set(resultPhone.data.currentbuName)
                    }

                    val resultLogo = SystemApi.stationLogo()
                    if (resultLogo.success && !resultLogo.data.isNullOrBlank()) {
                        GlobalData.stationLogoFileName.set(resultLogo.data)
                    }

                    initView()
                    DFSToastUtil.success(R.string.refresh_success)

                    // 支付配置
                    SystemApi.paymentParam()
                }
            }
        }
    }

    private val printManager = PrintManager()
    override fun onLongClick(v: View?): Boolean {
        return when (v) {
            binding.clock -> {
                PreferenceActivity.startForResult(this)
                true
            }
            else -> false
        }
    }

    override fun onFusionStatus(status: FusionStatus) {
        DFSLog.i("Fusion output status: ${status.name.toLowerCase(Locale.CHINESE)}")
        lifecycleScope.launchWhenStarted {
            dialogFusionLinking?.dismiss()
            when (status) {
                FusionStatus.Connecting -> {
                    setFusionLinkingLoading()
                }
                FusionStatus.Connected -> {
                    DFSToastUtil.success(R.string.connect_fusion_success)
                    initFragmentEntry()
                }
                FusionStatus.ConnectedWithoutInfo -> {
                    DFSToastUtil.fail(R.string.get_fuel_failed)
                    fragmentRouter.popBottom()
                    fragmentRouter.replace(FragmentReconnect.build())
                }
                FusionStatus.Disconnected -> {
                    // Disconnected reason
                    // 1. Network problem.
                    // 2. Communication exception and failed retry.
                    DFSToastUtil.fail(R.string.disconnect_fusion)
                    fragmentRouter.popBottom()
                    fragmentRouter.replace(FragmentReconnect.build())
                }
            }
        }
    }

    override fun onRouteForward() {
        mLoginTokenRefresher.stop()
    }

    override fun onRouteBackward(isBottom: Boolean) {
        if (isBottom) {
            mLoginTokenRefresher.start(this)
            handleUnsolvedOrder()

            GlobalScope.launch {
                // 支付配置
                SystemApi.paymentParam()
            }
        }
    }

    fun blockBackPress(isBlock: Boolean) {
        isBlockBackPress = isBlock
    }

    private fun initView() {
        mainViewModel.stationName.value = GlobalData.belongName.get().let {
            if (it.isEmpty())
                GlobalData.businessName.get()
            else
                "$it\n${GlobalData.businessName.get()}"
        }
        if (GlobalData.stationLogoFileName.get().isNotEmpty()) {
            binding.stationLogo.setImageURI(
                Uri.fromFile(
                    File(
                        filesDir,
                        GlobalData.stationLogoFileName.get()
                    )
                )
            )
        }
    }

    private fun initBanner() {
        binding.banner.run {
            addBannerLifecycleObserver(this@MainActivity)
            scrollTime = 500
            adapter =
                object : BannerImageAdapter<Int>(listOf(R.mipmap.banner_1, R.mipmap.banner_2)) {
                    override fun onBindView(
                        holder: BannerImageHolder,
                        data: Int,
                        position: Int,
                        size: Int
                    ) {
                        holder.imageView.setImageResource(data)
                    }
                }
        }
    }

    fun setFusionLinkingLoading() {
        // Don't dismiss dialog, just show & hide for reuse.
        dialogFusionLinking?.dismiss()
        dialogFusionLinking = LoadingDialogBuilder(this@MainActivity)
            .setTitle(R.string.fusion_in_connect)
            .setLoadingText(R.string.reconnect_fusion_tip)
            .setCancelable(true)
            .show()
        dialogFusionLinking?.window?.let { WindowUtil.setFullscreen(it) }
    }

    fun initFragmentEntry() {
        fragmentRouter.setHomeFragment(
//            if (SPUtil.getString(SPKeys.ORDER_CHOOSE) == "nozzle") {
//                FragmentNozzle.build()
//            } else {
//                FragmentSelect()
//            }
            FragmentNozzle.build()
        )
    }

    private fun handleUnsolvedOrder() {
        GlobalScope.launch(Dispatchers.IO) {

            val lockList = SPUtil.getLockOrderList()
            // 解锁订单
            //先查询云端状态，如果是支付过了，走消单流程；未支付的，走解锁流程
            lockList.let { list ->
                if (list.isEmpty()) return@let

                //查云端状态
                val checkList = list.map { item ->
                    val info = item.split("-")
                    val pumpId = info[0].toInt()
                    val transactionNo = info[1]
                    val token = info[2]
                    val orderListByPump = SPUtil.getOrderListByPump(pumpId)
                    val order = orderListByPump.find {
                                it.pumpNo == pumpId &&
                                it.transactionSeqNo == transactionNo &&
                                (it.releaseTokenAttribute == token || it.releaseTokenElement == token) }
                    async {
                        val deviceClass = DeviceClass()
                        deviceClass.pumpNo = pumpId
                        deviceClass.transactionSeqNo = transactionNo
                        deviceClass.releaseTokenAttribute = token
                        deviceClass.amount = order?.amount
                        deviceClass.endTimeStamp = order?.endTimeStamp
                        SystemApi.getOrderStateForClound(deviceClass)
                    }
                }
                val checkResultList = checkList.map { item -> item.await() }
                val unLockList = arrayListOf<String>()
                checkResultList.forEachIndexed { index, dfsResult ->
                    if (dfsResult.success) {
                        val iListResult = dfsResult.data?.iListResult
                        val find = iListResult?.find { it.resultCode == "0" }
                        if (find != null) { //这笔单已支付了，删去待锁单记录，加入待消单记录，进行消单
                            val info = list[index].split("-")
                            val pumpId = info[0].toInt()
                            val transactionNo = info[1]
                            val token = info[2]
                            val deviceClass = DeviceClass()
                            deviceClass.pumpNo = pumpId
                            deviceClass.transactionSeqNo = transactionNo
                            deviceClass.releaseTokenAttribute = token

                            SPUtil.removeLockOrder(deviceClass)
                            SPUtil.addUnclearedOrder(deviceClass)
                        } else {            //这笔单还未支付，加入解锁列表，做解锁
                            unLockList.add(list[index])
                        }
                    }
                }

                //做解锁
                val deferredList = unLockList.map { item ->
                    val info = item.split("-")
                    val pumpId = info[0].toInt()
                    val transactionNo = info[1]
                    val token = info[2].toInt()
                    async {
                        FusionManager.lockOrder(pumpId, transactionNo, token, false)
                    }
                }
                val resultList = deferredList.map { item -> item.await() }
                val remainLockList = resultList.mapIndexed { index, result ->
                    val tip = "auto unlock order ${list[index]}"
                    if (result.success) {
                        DFSLog.d("$tip succeeded")
                        null
                    } else {
                        DFSLog.d("$tip failed")
                        list[index]
                    }
                }.filterNotNull()
                SPUtil.replaceLockOrderList(remainLockList)
            }


            val unclearedList = SPUtil.getUnclearedOrderList()
            // 消除订单
            unclearedList.let { list ->
                if (list.isEmpty()) return@let

                val deferredList = list.map { item ->
                    val info = item.split("-")
                    val pumpId = info[0].toInt()
                    val transactionNo = info[1]
                    val token = info[2].toInt()
                    async {
                        FusionManager.clearOrder(pumpId, transactionNo, token)
                    }
                }
                val resultList = deferredList.map { item -> item.await() }
                val remainLockList = resultList.mapIndexed { index, result ->
                    val tip = "auto clear order ${list[index]}"
                    if (result.success) {
                        DFSLog.d("$tip succeeded")
                        SPUtil.removeWayneOrder(list[index])
                        orderClearCountMap.remove(list[index])
                        null
                    } else {
                        DFSLog.d("$tip failed")
                        /**          消单失败，会记录次数，如果三次消单都失败，便不再对这笔单消单
                         * 场景：这笔单在自助机执行 SPUtil.addUnclearedOrder(deviceClass) 前，被其他设备 clear 了，
                              这个时候自助机再 clear 就肯定失败了，而且也无意义。
                              虽然订单为 clear 状态时会在  FusionManager.onFdcMessageReceived 收到该订单为 clear，
                         并调用 SPUtil.removeUnclearedOrder(dc) 删除，但如果是 FusionManager.onFdcMessageReceived
                         执行完后再 SPUtil.addUnclearedOrder(deviceClass), 就会一直存在 SP 中尝试 clear。因此加了clear 次数
                        */
                        val unclearItem = list[index]
                        val clearTime = orderClearCountMap[unclearItem] ?: 1
                        if (clearTime >= 3) {
                            orderClearCountMap.remove(unclearItem)
                            null
                        } else {
                            orderClearCountMap[unclearItem] = clearTime + 1
                            list[index]
                        }
                    }
                }.filterNotNull()
                SPUtil.replaceUnclearedOrderList(remainLockList)
            }
            // 删除过期云订单
            SPUtil.removeExpiredWayneOrder()
        }
    }

    class MainViewModel : ViewModel() {
        val stationName = MutableLiveData("")
    }


    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (GlobalData.isPaying) {
            when(keyCode) {
                KeyEvent.KEYCODE_BACK -> {
                    DFSToastUtil.warn("当前处于支付状态，请勿退出...")
                    return true
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    override fun onUserLeaveHint() {
        if (GlobalData.isPaying) {
            DFSToastUtil.warn("当前处于支付状态，请勿退出...")
        }
        super.onUserLeaveHint()
    }



}