package core.ui.activity

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.viewbinding.ViewBinding
import com.blankj.utilcode.util.LogUtils
import core.util.ifNullOrEmpty
import http.client.ApiRepository
import http.exception.NetException
import http.vo.request.CommonSignInReq
import http.vo.response.SignFaceVo
import http.vo.response.SignInCheckResp
import org.greenrobot.eventbus.EventBus
import xn.xxp.app.LabApp
import xn.xxp.home.auth.PickSignTypeDialog
import xn.xxp.home.auth.ResultEnum
import xn.xxp.home.auth.SafetyCheckResultDialog
import xn.xxp.home.auth.SignType
import xn.xxp.home.leave.LeaveActivity
import xn.xxp.home.sign.SignInActivity
import xn.xxp.mqtt.event.OnlineUserEvent
import xn.xxp.room.RoomTool
import xn.xxp.room.bean.DeviceConfig
import xn.xxp.room.bean.LabConfig
import xn.xxp.utils.Tool

/**
 * info
 *
 * @author ReiChin_
 */
abstract class BaseSignActivity<VB : ViewBinding> : BaseCountDownActivity<VB>() {
    private lateinit var labConfig: LabConfig
    protected lateinit var deviceConfig: DeviceConfig
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        labConfig = RoomTool.getInstance().labConfigDao().labConfig
        deviceConfig = RoomTool.getInstance().deviceConfigDao().deviceConfig
    }

    protected fun dispatchSignIn() {
        LabApp.userVo ?: return

        if ("1" == LabApp.userVo?.pageType) {
            // 一类人员：巡查签到
            dispatchPatrolSign()
        } else {
            if ("1" == LabApp.userVo?.isDutyUser) {
                // 值班人员：选择巡查签到/准入签到
                PickSignTypeDialog(this) { type ->
                    if (SignType.PATROL.code == type) {
                        dispatchPatrolSign()
                    } else {
                        dispatchAccessSign()
                    }
                }.show()
            } else {
                // 其它人员：准入签到
                dispatchAccessSign()
            }
        }
    }

    protected fun dispatchSignOut() {
        LabApp.userVo ?: return

        if ("1" == LabApp.userVo?.pageType) {
            // 一类人员：巡查签退
            callLeaveApi(SignType.PATROL)
        } else {
            if ("1" == LabApp.userVo?.isDutyUser) {
                // 值班人员：选择巡查签退/准入签退
                queryLeaveType {
                    // 准入签退
                    dispatchAccessLeave()
                }
            } else {
                // 其它人员：准入签退
                dispatchAccessLeave()
            }
        }
    }

    protected open fun onSignInFinish(completed: Boolean) {
    }

    protected open fun onSignOutFinish(completed: Boolean) {
    }

    private fun dispatchAccessSign() {
        val param = CommonSignInReq().apply {
            labId = labConfig.labId.toString()
            userId = LabApp.userVo.userId
        }
        if (false == mustAccessInCheck()) {
            // 直接签到
            callSignApi(SignType.ACCESS, param)
        } else {
            accessSignCheck(param) { result ->
                val intent = Intent(this, SignInActivity::class.java)
                intent.putExtra("sign_type", SignType.ACCESS.code)
                intent.putExtra("sign_face", result)
                startActivity(intent)
                onSignInFinish(false)
            }
        }
    }

    // 准入签到检测
    private fun accessSignCheck(param: CommonSignInReq, callback: (result: SignFaceVo) -> Unit) {
        showLoading("请稍等...")
        val disposable = ApiRepository.accessSignCheck(param)
            .subscribe({
                dismissLoading()
                callback.invoke(it)
            }, { throwable ->
                dismissLoading()
                if (!pretreatmentError(throwable, "签到核验")) {
                    throwable.printStackTrace()
                    showNetError(throwable)
                }
            })
        addDisposable(disposable)
    }

    private fun dispatchPatrolSign() {
        val param = CommonSignInReq().apply {
            num = deviceConfig.devId
            labId = labConfig.labId.toString()
            userId = LabApp.userVo.userId
        }
        if (false == mustPatrolAiCheck()) {
            // 直接签到
            callSignApi(SignType.PATROL, param)
        } else {
            patrolSignCheck(param) {
                val intent = Intent(this, SignInActivity::class.java)
                intent.putExtra("sign_type", SignType.PATROL.code)
                startActivity(intent)
                onSignInFinish(false)
            }
        }
    }

    // 巡查签到检测
    private fun patrolSignCheck(param: CommonSignInReq, callback: () -> Unit) {
        showLoading("请稍等...")
        val disposable = ApiRepository.patrolSignCheck(param)
            .subscribe({
                dismissLoading()
                callback.invoke()
            }, { throwable ->
                dismissLoading()
                if (!pretreatmentError(throwable, "签到核验")) {
                    throwable.printStackTrace()
                    showNetError(throwable)
                }
            })
        addDisposable(disposable)
    }

    private fun callSignApi(signType: SignType, param: CommonSignInReq) {
        showLoading("签到中...")
        val disposable = ApiRepository.commonSignIn(signType.code, param)
            .subscribe({
                dismissLoading()
                EventBus.getDefault().post(OnlineUserEvent())
                SafetyCheckResultDialog(
                    this,
                    ResultEnum.SUCCESS,
                    "签到成功",
                    1500
                ).apply {
                    setCancelable(false)
                    setOnDismissListener { onSignInFinish(true) }
                    show()
                }
            }, { throwable ->
                LogUtils.e(Log.getStackTraceString(throwable))
                dismissLoading()
                showNetError(throwable)
            })
        addDisposable(disposable)
    }

    private fun pretreatmentError(throwable: Throwable, text: String): Boolean {
        if (throwable is NetException) {
            val message = throwable.message.ifNullOrEmpty("${text}失败，请联系实验室管理员。")
            //AudioPlayerManager.speakVoice(R.raw.audio_failed_sign_admin)
            SafetyCheckResultDialog(this, ResultEnum.FAIL, message, 3000).apply {
                setCancelable(false)
                show()
            }
            return true
        }
        return false
    }

    private fun dispatchAccessLeave() {
        if (false == mustAccessOutCheck()) {
            // 直接准入签退
            callLeaveApi(SignType.ACCESS)
        } else {
            accessLeaveCheck { resp ->
                val intent = Intent(this, LeaveActivity::class.java)
                intent.putExtra("data", resp)
                startActivity(intent)
                onSignOutFinish(false)
            }
        }
    }

    private fun accessLeaveCheck(callback: (resp: SignInCheckResp) -> Unit) {
        if (null == labConfig || null == LabApp.userVo) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return
        }

        showLoading("请稍等...")
        val disposable =
            ApiRepository.signOutCheck(true, labConfig.labId.toString(), LabApp.userVo!!.userId)
                .subscribe({ data ->
                    dismissLoading()
                    if (data.state) {
                        callback.invoke(data)
                    } else {
                        val message =
                            if (data.message.isNullOrEmpty()) "核验失败，请联系管理员！" else data.message[0]
                        SafetyCheckResultDialog(this, ResultEnum.FAIL, message, 3000).apply {
                            setCancelable(false)
                            show()
                        }
                    }
                }, { throwable ->
                    dismissLoading()
                    if (!pretreatmentError(throwable, "签退核验")) {
                        throwable.printStackTrace()
                        showNetError(throwable)
                    }
                })
        addDisposable(disposable)
    }

    private fun queryLeaveType(callback: () -> Unit) {
        if (null == labConfig || null == LabApp.userVo) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return
        }

        showLoading("请稍等...")
        val disposable =
            ApiRepository.isSignInType(labConfig.labId.toString(), LabApp.userVo!!.userId)
                .subscribe({ patrol ->
                    dismissLoading()
                    if (patrol) {
                        callLeaveApi(SignType.PATROL)
                    } else {
                        callback.invoke()
                    }
                }, { throwable ->
                    dismissLoading()
                    if (!pretreatmentError(throwable, "签退")) {
                        throwable.printStackTrace()
                        showNetError(throwable)
                    }
                })
        addDisposable(disposable)
    }

    private fun callLeaveApi(signType: SignType) {
        if (null == labConfig || null == LabApp.userVo) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return
        }

        showLoading("签退中...")
        val disposable = ApiRepository.commonLeave(
            signType.code,
            labConfig.labId.toString(),
            LabApp.userVo.userId
        )
            .subscribe({
                dismissLoading()
                EventBus.getDefault().post(OnlineUserEvent())
                SafetyCheckResultDialog(
                    this,
                    ResultEnum.SUCCESS,
                    "离开成功",
                    3000
                ).apply {
                    setCancelable(false)
                    setOnDismissListener { onSignOutFinish(true) }
                    show()
                }
            }, { throwable ->
                dismissLoading()
                if (!pretreatmentError(throwable, "离开")) {
                    throwable.printStackTrace()
                    showNetError(throwable)
                }
            })
        addDisposable(disposable)
    }

    // 是否配置了离开检查项
    private fun mustAccessOutCheck(): Boolean? {
        val laboratoryVo = LabApp.laboratory
        if (null == laboratoryVo || null == labConfig) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return null
        }
        return !laboratoryVo.outCheck.isNullOrEmpty()
    }

    // 是否需要准入AI检测
    private fun mustAccessInCheck(): Boolean? {
        val laboratoryVo = LabApp.laboratory
        if (null == laboratoryVo || null == labConfig) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return null
        }
        return !laboratoryVo.inCheck.isNullOrEmpty()
    }

    // 是否需要巡查AI检测
    private fun mustPatrolAiCheck(): Boolean? {
        val laboratoryVo = LabApp.laboratory
        if (null == laboratoryVo || null == labConfig) {
            showToast("暂无实验室信息，即将重新获取")
            Tool.INSTANCE.reStartApp("暂无实验室信息，即将重新获取")
            return null
        }
        return !laboratoryVo.inspectInCheck.isNullOrEmpty()
    }

}