package com.gingersoft.gsa.delivery_pick_mode.model.viewModel

import android.app.Dialog
import android.content.Context
import android.view.Gravity
import android.view.WindowManager
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.billy.cc.core.component.CC
import com.gingersoft.gsa.cloud.app.GsaCloudApplication
import com.gingersoft.gsa.cloud.common.constans.AppConstans
import com.gingersoft.gsa.cloud.common.constans.FoodSummaryConstans
import com.gingersoft.gsa.cloud.common.constans.PrintConstans
import com.gingersoft.gsa.cloud.common.core.delivery.OrderDetails
import com.gingersoft.gsa.cloud.common.core.delivery.OrderDetails.Companion.verifiAmountTip
import com.gingersoft.gsa.cloud.common.core.delivery.OrderDetails.Companion.verificationAmount
import com.gingersoft.gsa.cloud.print.bean.adapter.PrintContentAdapter
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager
import com.gingersoft.gsa.cloud.common.core.user.UserContext
import com.gingersoft.gsa.cloud.common.service.GetInfoUpdateService
import com.gingersoft.gsa.cloud.common.utils.gson.GsonUtils
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.other.TextUtil
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils
import com.gingersoft.gsa.cloud.common.utils.toast.ToastUtils
import com.gingersoft.gsa.cloud.component.ComponentName
import com.gingersoft.gsa.cloud.order.order.TakeawayOrder
import com.gingersoft.gsa.cloud.pay.bean.PayMethod
import com.gingersoft.gsa.cloud.ui.utils.DialogUtils
import com.gingersoft.gsa.delivery_pick_mode.R
import com.gingersoft.gsa.delivery_pick_mode.data.WeatherRepository
import com.gingersoft.gsa.delivery_pick_mode.data.model.bean.*
import com.gingersoft.gsa.delivery_pick_mode.ui.adapter.DeliveryAdapter
import com.gingersoft.gsa.delivery_pick_mode.util.OtherOrderUtils
import com.gingersoft.gsa.delivery_pick_mode.util.RxTimerUtil
import com.jess.arms.utils.ArmsUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class PageViewModel(private val repository: WeatherRepository) : ViewModel() {

    companion object {
        var fragmentStatus = arrayOf("0,1,2,3,8", "0,1", "2", "3", "3")
        var fragmentType = arrayOf("0", "0", "0", "2", "7")
        val PrintCode = 1001//打印
        val SendCode = 1002//指派送貨
        val OrderDelivery = 1003//訂單配送
        val Closing = 1004//結賬
        val CancelOrder = 1005//取消訂單
        val CancelLogistics = 1006//取消物流
        val ProductionComplete = 1007//製作完成
        val DeliveryPrint = 1008//訂單確認成功，是否成功打印回調
        val Transportation = 1009//修改運輸工具成功
        val AmountError = 1010//訂單金額有錯
        val ErrorCode = 1011//報錯提示
    }

    val restaurantId by lazy { RestaurantInfoManager.newInstance().getRestaurantId() }
    var mOrderNum = arrayListOf<MutableLiveData<Int>>()

    var mOrderList = arrayListOf<MutableLiveData<ArrayList<OrderList.DataBeanX.DataBean>>>()

    var orderList = MutableLiveData<OrderList>()

    //其他的所有數據
    var otherInfo = MutableLiveData<OrderList.DataBeanX.DataBean>()

    var balanceBean = MutableLiveData<BalanceBean>()

    //刷新狀態，值為當前頁面的下標
    var refreshState = MutableLiveData(0)

    //訂單號
    var orderNo: String = ""

    //手機號
    var phone: String = ""

    //派送員信息
    var deliveryBean: DeliveryBean? = null

    //接單超時時間
    var timeOut = 0

    var appointmentType = MutableLiveData(0) //0為即時單，1為預約單
    var instantOrderNum = MutableLiveData(0) //即時單單數
    var bookingOrderNum = MutableLiveData(0) //預約單單數
    var bookingConfigTime = MutableLiveData<Int>()//預約單配置時間

    var addServiceChargeBean = MutableLiveData<AddServiceChargeBean>()

    /**
     * 獲取訂單數量
     * status
     * 0:未支付;
     * 1:待確認(已支付, 待餐廳確認);
     * 2:制作中（餐廳确認）;
     * 3:外賣是派送中，自取是待取餐
     * 4:确認收貨（完成）;
     * 5:是否評論;6:取消;
     * 已確認，外賣是指派送單，自取是製作完成
     */
    fun getOrderGroupNum(restaurantId: String) {
        launch({
            repository.getOrderGroup(restaurantId).apply {
                //先把所有置0
                for (i in mOrderNum) {
                    i.value = 0
                }
                //遍歷獲得外賣自取的 待確認和製作中的總單數
                for (i in data.selfTakeaway) {
                    when {
                        i.STATUS == 0 -> //未支付的待確認
                            mOrderNum[1].value = mOrderNum[1].value?.plus(i.SumNum)
                        i.STATUS == 1 -> //已支付的待確認
                            mOrderNum[1].value = mOrderNum[1].value?.plus(i.SumNum)
                        i.STATUS == 2 -> //製作中
                            mOrderNum[2].value = i.SumNum
                    }
                }
                //狀態為三時，下標為3(送貨中)的值為外賣的數量，下標為4(待取餐)的值為自取的數量
                for (i in data.takeaway) {
                    if (i.STATUS == 3) {
                        mOrderNum[3].value = i.SumNum
                    }
                }
                for (i in data.self) {
                    if (i.STATUS == 3) {
                        mOrderNum[4].value = i.selfSumNum
                    }
                }

                //下標為0時是全部，把集合所有值加起來
                var num = 0
                for (i in mOrderNum) {
                    //五個模塊
                    if (i.value != null) {
                        num += i.value!!
                    }
                }
                mOrderNum[0].value = num
            }
        }, {
            it.printStackTrace()
        })
    }

    /**
     * 獲取訂單列表
     */
    fun getOrderList(restaurantId: String, position: Int, page: String, isLoadMore: Boolean) {
        launch({
            var orderType = appointmentType.value
            if (position > 1) {
                orderType = 0
            }
            repository.requestOrderList(restaurantId, fragmentStatus[position], fragmentType[position], page, orderNo, phone, orderType
                    ?: 0).apply {
                if (isSuccess()) {
                    getOrderGroupNum(restaurantId)
                    loadInfo(isLoadMore, position)
                } else {
                    orderList.postValue(this)
                    mOrderList[position].value = null
                    OkHttp3Utils.noticePersonnel(AppConstans.RP_ORDER_LIST_ERROR, "獲取訂單列表失敗")
                }
            }
        }, {
            //出錯
            mOrderList[position].value = null
            OkHttp3Utils.noticePersonnel(AppConstans.RP_ORDER_LIST_ERROR, "獲取訂單列表報錯" + it.message)
            OtherOrderUtils.initSoundPool(GsaCloudApplication.getAppContext(), R.raw.raw_get_order_list_error)
        })
    }

    /**
     * 開始自動確認訂單
     */
    fun startAutoConfirmOrder() {
        RxTimerUtil.interval({
            launch({
                //獲取即時單
                repository.requestOrderList(restaurantId.toString(), fragmentStatus[1] + ",8", fragmentType[0], "1", orderNo, phone, 0).apply {
                    if (isSuccess()) {
                        val data = getData()
                        if (data != null) {
                            val dataList = data.data
                            //這裡判斷數量大於1，默認有一條配置數據，忽略掉
                            if (dataList != null && dataList.size > 1) {
                                //確認訂單之前得先獲取訂單詳情
                                val orderInfo = repository.getOrderInfo(dataList[0].Id.toString())
                                if (orderInfo.data != null && orderInfo.data!!.isNotEmpty()) {
                                    orderInfo.data?.let { it ->
                                        val orderDetail = it[0]
                                        if (verificationAmount(orderDetail)) return@launch
                                        orderDetail.order_type = dataList[0].order_type
                                        orderDetail.orderPayType = dataList[0].orderPayType
                                        if (orderDetail.order_type == 7) {
                                            //如果是自取單，將物流類型改為本店
                                            orderDetail.companyType = 0
                                        }
                                        var trafficType = ""
                                        if (orderDetail.companyType == 2) {
                                            //lalamove
                                            val transportationBean = getTransportationConfig(restaurantId)
                                            if (transportationBean.success && transportationBean.data != null && transportationBean.data.list != null) {
                                                for (value in transportationBean.data.list) {
                                                    if (value.status == 1) {
                                                        //默認交通工具，判斷價格是不是在這個金額範圍內，如果在，則不提示，如果不在，提示用戶修改交通工具
                                                        trafficType = value.type.toString()
                                                    }
                                                }
                                            }
                                        }
                                        confirmOrder(orderDetail, 2, trafficType, restaurantId, isPrintPrj = true, isPrintBill = true) {
                                            //確認之後，刷新列表
                                            refreshState.postValue(0)
                                        }


                                    }
                                }
                            } else {

                            }
                        } else {

                        }
                    } else {

                    }
                }
                //獲取預約單
                repository.requestOrderList(restaurantId.toString(), fragmentStatus[1], fragmentType[0], "1", orderNo, phone, 1).apply {
                    if (isSuccess()) {
                        val data = getData()
                        if (data != null) {
                            val dataList = data.data
                            //這裡判斷數量大於1，默認有一條配置數據，忽略掉
                            if (dataList != null && dataList.size > 1) {
                                //確認訂單之前得先獲取訂單詳情
                                val orderInfo = repository.getOrderInfo(dataList[0].Id.toString())
                                if (orderInfo.data != null && orderInfo.data!!.isNotEmpty()) {
                                    val orderDetail = orderInfo.data!![0]
                                    if (verificationAmount(orderDetail)) return@launch
                                    updateOrderAndPrint(restaurantId, orderDetail, 8, false) {
                                        refreshState.postValue(0)
                                    }
                                }
                            }
                        }
                    }
                }
            }, {
            })
        }, 10 * 1000)
    }

    fun stopAutoConfirmOrder() {
        RxTimerUtil.cancelInterval()
    }


    private fun OrderList.loadInfo(isLoadMore: Boolean, position: Int) {
        getData()?.statistics?.let {
            bookingOrderNum.value = it.reservationNumber
            instantOrderNum.value = it.immediateNumber
            bookingConfigTime.value = it.reservationConfigTime
        }
        if (getData() != null && getData()?.data != null) {
            val myData: ArrayList<OrderList.DataBeanX.DataBean> = getData()?.data as ArrayList<OrderList.DataBeanX.DataBean>
            if (myData.isNotEmpty()) {
                //取得最後一個對象，裡面有營業狀態和外賣訂單數，自取訂單數
                val dataBean: OrderList.DataBeanX.DataBean = myData[myData.size - 1]
                if (dataBean.Open_Status != null) {
                    restaurantState.value = dataBean.Open_Status!!.toInt()
                }
                if (position == 0) {//查詢全部訂單時才加載這些數據
                    otherInfo.value = myData[myData.size - 1]
                }
                //移除掉最後一個對象
                myData.removeAt(myData.size - 1)
                //如果是加載更多
                if (isLoadMore) {
                    if (mOrderList[position].value != null) {
                        mOrderList[position].value!!.addAll(myData)
                        mOrderList[position].postValue(mOrderList[position].value)
                    }
                } else {
                    mOrderList[position].value = myData
                }
            } else {
                mOrderList[position].value = null
            }
        } else {
            mOrderList[position].value = null
        }
    }

    //餐廳營業狀態，控制按鈕
    var restaurantState = MutableLiveData<Int>()

    /**
     * 修改餐廳營業狀態
     * 0=休息中, 1=營業中,2=繁忙中不可接單,3繁忙可接單
     */
    fun updateRestOpenStatus(state: Int, restaurantId: String) {
        launch({
            repository.updateRestOpenStatus(state, restaurantId).apply {
                if (success) {
                    restaurantState.value = state
                }
            }
        }, {
            it.printStackTrace()
        })
    }

    /**
     * 根據訂單id獲取訂單詳細信息
     */
    fun getOrderInfo(orderId: String, listener: (OrderDetails?) -> Unit) {
        launch({
            repository.getOrderInfo(orderId).apply {
                listener.invoke(this)
            }
        }, {
            //出錯
            it.printStackTrace()
            listener.invoke(null)
        })
    }


    var orderDetails = MutableLiveData<OrderDetails>()

    //獲取訂單詳情和物流送達時間
    fun getShipanyAndOrderInfo(restaurantId: Int, orderId: String) {
        launch({
            withContext(Dispatchers.IO) {
                val orderDetail = withContext(Dispatchers.Default) { repository.getOrderInfo(orderId) }
                orderDetails.postValue(orderDetail)
                if (orderDetail.data != null && orderDetail.data!!.isNotEmpty()) {
                    //訂單詳情不為空
                    if (orderDetail.data!![0].isDelete == 0) {//為0是第三方物流單
                        if (orderDetail.data!![0].curStat != 0) {
                            val data = orderDetail.data!![0]
                            val type: Int
                            val estimatedTime: String
                            when (orderDetail.data!![0].curStat) {
                                1 -> {
                                    type = 2
                                    estimatedTime = "預計配送員接單時間："
                                }
                                2, 3 -> {
                                    type = 3
                                    estimatedTime = "預計配送員到店時間："
                                }
                                4, 5, 6 -> {
                                    type = 4
                                    estimatedTime = "配送員預計送達時間："
                                }
                                else -> {
                                    type = 1
                                    estimatedTime = "預計整張訂單完成時間："
                                }
                            }
                            val estimatedBean = withContext(Dispatchers.Default) { repository.getShipanyOrderTime(restaurantId.toString(), orderId, type) }//1、预计整张订单完成时间2、預計配送員接單時間3、預計配送員到店時間4、配送員預計送達時間
                            if (estimatedBean.data != null) {
                                data.estimatedTime = estimatedTime + ("${estimatedBean.data.estimated_time}分鐘後")
                            }
                            orderDetails.postValue(orderDetail)
                        }
                    }
                }
            }
        }, {
            OkHttp3Utils.noticePersonnel("", "獲取訂單詳情失敗")
            orderDetails.postValue(null)
        })
    }

    var serviceChargeRecordBeans = MutableLiveData<ServiceChargeRecordBean>()

    fun getAdditionalByOrderId(orderId: String) {
        launch({
            serviceChargeRecordBeans.postValue(repository.getAdditionalByOrderId(orderId, "0"))
        }, {
            serviceChargeRecordBeans.postValue(null)
            it.printStackTrace()
        })
    }

    //設置為已讀
    fun updateIsRead(orderId: String) {
        launch({
            repository.updateIsRead(orderId)
        }, {
            it.printStackTrace()
        })
    }

    fun confirmOrder(dataBean: OrderDetails.DataBean, status: Int, trafficType: String = "", restaurantId: Int, isPrintPrj: Boolean = true, isPrintBill: Boolean = true, listener: (MessageBean) -> Unit) {
        if (verificationAmount(dataBean)) {
            listener.invoke(getMsgBean(0, verifiAmountTip, false))
            return
        }
        launch({
            when (dataBean.companyType) {
                0 -> {
                    //本店
                    updateOrderAndPrint(restaurantId, dataBean, status, isPrintPrj, listener)
                }
                1 -> {
                    //zeek
                    thirdSend(restaurantId, dataBean, trafficType, status, isPrintPrj, isPrintBill, listener)
                }
                2 -> {
                    //lalamove
                    thirdSend(restaurantId, dataBean, trafficType, status, isPrintPrj, isPrintBill, listener)
                }
            }
        }, {
            listener.invoke(getMsgBean(0, "", false))
            it.printStackTrace()
            GetInfoUpdateService.loginfo.append("錯誤信息111：" + it.message + "  LOCALIZEDMESSAGE：" + it.localizedMessage + it.cause)
            GetInfoUpdateService.loginfo.append("\n")
        })
    }

    /**
     * 獲取lalamove交通工具
     */
    fun getIsUpdateTransportation(restaurantId: Int, listener: (List<TransportationBean.DataX.Transportation>?) -> Unit) {
        launch({
            val data = getTransportationConfig(restaurantId)
            if (data.success) {
                data.data?.list?.let {
                    listener.invoke(it)
                    return@launch
                }
            }
            listener.invoke(null)
        }, {
            listener.invoke(null)
        })
    }

    /**
     * 獲取交通工具實際金額
     */
    fun getActualAmount(orderId: String, uid: Int, restaurantId: Int, block: (TransportAmountBean?) -> Unit) {
        launch({
            block.invoke(repository.getActualAmount(orderId, uid.toString(), restaurantId.toString()))
        }, {
            block.invoke(null)
            it.printStackTrace()
        })
    }

    /**
     * 獲取餘額
     */
    fun getBanlance(brandId: Int) {
        launch({
            balanceBean.postValue(repository.getBanlance(brandId.toString()))
        }, {
            balanceBean.postValue(null)
            it.printStackTrace()
        })
    }


    fun closingBill(orderDetails: OrderDetails.DataBean, payMethods: List<PayMethod>, listener: (Int, Boolean) -> Unit) {
        launch({
            val payMultiple = ArrayList<OrderDetails.DataBean.PayMultiple>()

            payMethods.forEach {
                payMultiple.add(OrderDetails.DataBean.PayMultiple(it.id.toString(), it.payMoney, it.payName, 0.0))
            }
            repository.updateOrderPay(orderDetails.ID, 4, orderDetails.order_type, 3, orderPayInfoVO = payMultiple).apply {
                orderDetails.payMultiple = payMultiple
                orderDetails.payTime = TimeUtils.getCurrentTimeInString(TimeUtils.DEFAULT_DATE_FORMAT)
                val bean = GsonUtils.GsonToBean(GsonUtils.GsonString(data), OrderClosingBean::class.java)
                if (bean != null) {
                    orderDetails.oldPoints = bean.oldPoints
                    orderDetails.nowPoints = bean.nowPoints
                    orderDetails.addPoints = bean.addPoints
                }
                printOrderClosing(orderDetails, listener)
            }
        }, {
            listener.invoke(OrderDelivery, false)
            it.printStackTrace()
//            integralBean.postValue(null)
        })
    }


    fun gsUpdateOrderStatus(orderDetails: OrderDetails.DataBean, orderPayInfoVO: List<OrderDetails.DataBean.PayMultiple>?, listener: (Int, Boolean) -> Unit) {
        //驗證訂單金額是否正確
        if (verificationAmount(orderDetails)) {
            listener.invoke(AmountError, false)
            return
        }
        launch({
            repository.gsUpdateOrderStatus(orderDetails.ID, 4, orderDetails.order_type, 3, orderFrom = 0).apply {
                if (orderPayInfoVO != null && orderPayInfoVO.isNotEmpty()) {
                    orderDetails.payMultiple = orderPayInfoVO
                }
                orderDetails.payTime = TimeUtils.getCurrentTimeInString(TimeUtils.DEFAULT_DATE_FORMAT)
                val bean = GsonUtils.GsonToBean(GsonUtils.GsonString(data), OrderClosingBean::class.java)
                orderDetails.oldPoints = bean.oldPoints
                orderDetails.nowPoints = bean.nowPoints
                orderDetails.addPoints = bean.addPoints
                printOrderClosing(orderDetails, listener)
            }
        }, {
            listener.invoke(ErrorCode, false)
            it.printStackTrace()
        })
    }

    fun updateOrderAndPrint(restaurantId: Int, dataBean: OrderDetails.DataBean, status: Int, isPrint: Boolean = true, listener: (MessageBean) -> Unit) {
        updateOrderAndPrint(restaurantId, dataBean, status, isPrint, isPrint, listener)
    }

    /**
     * 修改訂單狀態並打印，狀態為0,1,2才打印
     */
    fun updateOrderAndPrint(restaurantId: Int, dataBean: OrderDetails.DataBean, status: Int, isPrintPrj: Boolean = true, isPrintBill: Boolean = true, listener: (MessageBean) -> Unit) {
        if (verificationAmount(dataBean)) {
            listener.invoke(getMsgBean(0, verifiAmountTip, false))
            return
        }
        launch({
            repository.gsUpdateOrderStatus(dataBean.ID, status, dataBean.order_type, 1, "", "", "", "0", "", 1, 0).apply {
                if (status == 0 || status == 1 || status == 2 || status == 8) {
                    if (this.code == "1") {
                        //確認送單
                        //添加數據到prj
                        if (isPrintPrj) {
                            val ids = StringBuffer()
                            dataBean.PRODUCT_NAME.let {
                                if (it != null) {
                                    for (i in it) {
                                        if (i.child != null) {
                                            for (j in i.child!!) {
                                                if (j.child != null) {
                                                    for (x in j.child!!) {
                                                        ids.append(x.odsId)
                                                        ids.append(",")
                                                    }
                                                }
                                                ids.append(j.odsId)
                                                ids.append(",")
                                            }
                                        }
                                        ids.append(i.odsId)
                                        ids.append(",")
                                    }
                                }
                            }
                            launch({
                                //添加PRJ
                                //單獨包起來，哪怕這接口報錯也不要影響到正常的邏輯
                                repository.addPrj(dataBean.Order_ID.toString(), restaurantId.toString(), ids.toString())
                                GetInfoUpdateService.loginfo.append("添加PRJ：orderId：" + dataBean.Order_ID.toString() + "restaurantId：" + restaurantId + "orderDetailsIds：" + ids.toString())
                                GetInfoUpdateService.loginfo.append("\n")
                            }, {
                                it.printStackTrace()
                                GetInfoUpdateService.loginfo.append("錯誤信息222：" + it.message + "  LOCALIZEDMESSAGE：" + it.localizedMessage + it.cause)
                                GetInfoUpdateService.loginfo.append("\n")
                            })
                        }
                        if (isPrintBill) {
                            // 打印印單
                            // 初始化用於打印的view
                            // 送單成功後，再調用接口獲取取餐碼
                            repository.getOrderInfo(dataBean.ID.toString()).apply {
                                if (data != null && data!!.isNotEmpty()) {
                                    data?.get(0)?.let {
                                        it.order_type = dataBean.order_type
                                        it.orderPayType = dataBean.orderPayType
                                        printOrder(DeliveryPrint, it, listener)
                                    }
                                } else {
                                    if (errorMsg != null) {
                                        listener.invoke(getMsgBean(OrderDelivery, errorMsg!!, false))
                                    } else {
                                        listener.invoke(getMsgBean(OrderDelivery, "", false))
                                    }
                                }
                            }
                        } else {
                            listener.invoke(getMsgBean(OrderDelivery, "", true))
                        }
                    } else {
                        OkHttp3Utils.noticePersonnel(AppConstans.RP_UPDATE_ORDER_STATE_ERROR, "修改訂單狀態未成功：$errorMsg")
                        listener.invoke(getMsgBean(OrderDelivery, errorMsg, false))
                    }
                } else {
                    listener.invoke(getMsgBean(ProductionComplete, errorMsg, code == "1"))
                }
            }
        }, {
            OkHttp3Utils.noticePersonnel(AppConstans.RP_UPDATE_ORDER_STATE_ERROR, "訂單狀態" + status + it.message)
            listener.invoke(getMsgBean(OrderDelivery, "", false))
        })
    }


    /**
     * 獲取交通工具配置
     */
    private suspend fun getTransportationConfig(restaurantId: Int) = withContext(Dispatchers.IO) {
        repository.getTransportationConfig(restaurantId.toString())
    }


    /**
     * 添加服務費
     */
    fun additionalServiceCharge(uid: String, orderId: String, paymentValue: Int) {
        launch({
            addServiceChargeBean.value?.paymentValue = paymentValue
            addServiceChargeBean.postValue(repository.additionalServiceCharge(uid, orderId, paymentValue))
        }, {
            addServiceChargeBean.postValue(null)
            it.printStackTrace()
        })
    }


    /**
     * 打印訂單
     */
    fun printOrder(code: Int, dataBean: OrderDetails.DataBean, listener: (MessageBean) -> Unit) {
        //訂單信息和廚房單，打印前需要修改dataBean的order_type和orderPayType
        TakeawayOrder.getInstance().shoppingCart.deliveryAndPickupData = dataBean

        var contentAdapter = PrintContentAdapter()
        var printContent = contentAdapter.adaptationPrintTakeawayFormContent(dataBean)

        CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
                .addParam(PrintConstans.PRINT_TYPE, PrintConstans.PRINT_OTHER_ORDER)
                .addParam(PrintConstans.PRINT_CONTENT, printContent)
                .setActionName("printActivity")
                .build()
                .callAsyncCallbackOnMainThread { _, result ->
                    TakeawayOrder.getInstance().shoppingCart.deliveryAndPickupData = null
                    listener.invoke(getMsgBean(code, "打印", result.isSuccess))
                }
    }

    /**
     * 打印結賬單
     */
    private fun printOrderClosing(dataBean: OrderDetails.DataBean, listener: (Int, Boolean) -> Unit) {
        TakeawayOrder.getInstance().shoppingCart.deliveryAndPickupData = dataBean

        val contentAdapter = PrintContentAdapter()
        val printContent = contentAdapter.adaptationPrintTakeawayCheckoutContent(TakeawayOrder.getInstance().shoppingCart.deliveryAndPickupData)

        CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
                .addParam(PrintConstans.PRINT_TYPE, PrintConstans.PRINT_OTHER_CLOSING)
                .setActionName("printActivity")
                .addParam(PrintConstans.PRINT_CONTENT, printContent)
                .build()
                .callAsyncCallbackOnMainThread { _, result ->
                    TakeawayOrder.getInstance().shoppingCart.deliveryAndPickupData = null
                    listener.invoke(PrintCode, result.isSuccess)
                }


    }

    /**
     * 打開錢箱
     */
    fun openCashBox() {
//        launch({
//            //單獨包起來，哪怕這接口報錯也不要影響到正常的邏輯
//            repository.addPrj("11112364", "153", "48863119")
//        }, {
//            it.printStackTrace()
//        })
        CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
                .addParam(PrintConstans.PRINT_TYPE, PrintConstans.PRINT_INSTRUCTION)
                .addParam(PrintConstans.PRINT_LOADING, false)
                .setActionName("printActivity")
                .build()
                .callAsyncCallbackOnMainThread { _, _ ->

                }
    }

    /**
     * 第三方派送
     */
    private fun thirdSend(restaurantId: Int, dataBean: OrderDetails.DataBean, trafficType: String, status: Int, isPrintPrj: Boolean = true, isPrintBill: Boolean = true, listener: (MessageBean) -> Unit) {
        val third = ThirdItem()
        //將食品數據轉為第三方需要的數據
        dataBean.PRODUCT_NAME?.let {
            for (i in it) {
                val price = ThirdItem.ThirdItemItem.UntPrice(`val` = i.PRICE!!.toDouble())
                val thirdItem = if (i.PRODUCT_NAME != null) {
                    ThirdItem.ThirdItemItem(name = i.PRODUCT_NAME!!, qty = 1, unt_price = price)
                } else {
                    ThirdItem.ThirdItemItem(name = "", qty = 1, unt_price = price)
                }
                third.add(thirdItem)
            }
        }
        //調用第三方物流接口
        callThird(dataBean, trafficType, third, restaurantId, status, isPrintPrj, isPrintBill, listener)
    }

    private fun callThird(dataBean: OrderDetails.DataBean, trafficType: String, third: ThirdItem, restaurantId: Int, status: Int, isPrintPrj: Boolean = true, isPrintBill: Boolean = true, listener: (MessageBean) -> Unit) {
        launch({
            repository.thirdDelivery(dataBean.ID.toString(), trafficType, third).apply {
                if (success) {
                    if (isPrintPrj || isPrintBill) {
                        updateOrderAndPrint(restaurantId, dataBean, status, isPrintPrj, isPrintBill, listener)
                    } else {
                        //都不打印，說明是修改交通工具
                        listener(getMsgBean(Transportation, errMsg ?: "修改運輸工具成功", success))
                    }
                } else if (!TextUtil.isEmptyOrNullOrUndefined(errMsg)) {
                    listener.invoke(getMsgBean(OrderDelivery, errMsg!!, false))
                    //第三方物流接口異常
                    OkHttp3Utils.noticePersonnel(AppConstans.RP_THIRE_LOGISTICS_ERROR, "第三方物流請求失敗：$errMsg")
                } else if (!TextUtil.isEmptyOrNullOrUndefined(message)) {
                    listener.invoke(getMsgBean(OrderDelivery, message, false))
                    //第三方物流接口異常
                    OkHttp3Utils.noticePersonnel(AppConstans.RP_THIRE_LOGISTICS_ERROR, "第三方物流請求失敗：$message")
                } else {
                    listener.invoke(getMsgBean(OrderDelivery, "指派物流失敗", false))
                    OkHttp3Utils.noticePersonnel(AppConstans.RP_THIRE_LOGISTICS_ERROR, "第三方物流請求失敗")
                }
            }
        }, { it ->
            if (it is java.io.InterruptedIOException) {
                //超時了，獲取訂單詳情，如果訂單未指派物流，那麼再次調用第三方物流接口
                getOrderInfo(dataBean.ID.toString()) {
                    if (it?.data != null && it.data!!.isNotEmpty() && it.data!![0].isDelete == 0) {
                        //已經指派第三方物流，就調用修改訂單狀態接口
                        updateOrderAndPrint(restaurantId, dataBean, status, isPrintPrj, isPrintBill, listener)
                    } else {
                        callThird(dataBean, trafficType, third, restaurantId, status, isPrintPrj, isPrintBill, listener)
                    }
                }
            } else {
                OkHttp3Utils.noticePersonnel(AppConstans.RP_THIRE_LOGISTICS_ERROR, "請求第三方物流接口報錯：" + it.message)
                listener.invoke(getMsgBean(OrderDelivery, "", false))
            }
        })
    }

    /**
     * 選擇派送員
     */
    fun selectorDelivery(context: Context, dataBean: OrderDetails.DataBean, status: Int, listener: (Int, Boolean) -> Unit) {
        launch({
            repository.getDeliveryInfo(RestaurantInfoManager.newInstance().getRestaurantId().toString(), UserContext.newInstance().getMemberId().toString()).apply {
                deliveryBean = this
                if (this.data.isEmpty()) {
                    ToastUtils.show(context, "沒有配置配送員信息")
                    return@apply
                }
                //顯示選擇派送員
                object : DialogUtils(context, R.layout.other_order_layout_assign_deliveryman) {
                    override fun initLayout(hepler: ViewHepler?, dialog: Dialog?) {
                        hepler!!.getView<TextView>(R.id.tv_delivery_cancel).setOnClickListener {
                            dialog!!.dismiss()
                        }
                        val confirmBtn: TextView = hepler.getView(R.id.tv_delivery_confirm)
                        var selectIndex = -1

                        val recycler = hepler.getView<RecyclerView>(R.id.rv_delivery)
                        recycler.layoutManager = GridLayoutManager(context, 4)

                        val data = ArrayList<String>()
                        for (value in deliveryBean!!.data) {
                            data.add(value.userName)
                        }
                        val deliveryAdapter = DeliveryAdapter(data)
                        recycler.adapter = deliveryAdapter

                        deliveryAdapter.setOnItemClickListener { adapter, _, position ->
                            selectIndex = position
                            deliveryAdapter.selectIndex = position
                            adapter.notifyDataSetChanged()

                            confirmBtn.background = ContextCompat.getDrawable(context, R.drawable.shape_green_btn)
                        }

                        confirmBtn.setOnClickListener {
                            if (selectIndex != -1) {
                                //驗證訂單金額是否正確
                                if (verificationAmount(dataBean)) {
                                    ToastUtils.show(context, verifiAmountTip)
                                    return@setOnClickListener
                                }
                                launch({
                                    repository.gsUpdateOrderStatus(dataBean.ID, status, dataBean.order_type, 1, "", deliveryBean!!.data[deliveryAdapter.selectIndex].userName, deliveryBean!!.data[deliveryAdapter.selectIndex].mobile, "0", "", 1, 0).apply {
                                        if (code == "1") {
                                            dialog?.dismiss()
                                            //回調
                                            listener.invoke(OrderDelivery, code == "1")//刷新頁面
                                            ToastUtils.show(context, "訂單開始派送")
                                        } else {
                                            ToastUtils.show(context, "訂單派送失敗")
                                        }
                                    }
                                }, {
                                    it.printStackTrace()
                                })
                            } else {
                                ToastUtils.show(context, "請至少選擇一個送貨員")
                            }
                        }
                    }
                }.setWidth(WindowManager.LayoutParams.MATCH_PARENT)
                        .setHeight((ArmsUtils.getScreenHeidth(context) * 0.5).toInt())
                        .setGravity(Gravity.BOTTOM)
                        .show()
            }
        }, {
            it.printStackTrace()
        })
    }

    /**
     * 選擇取消原因
     */
    fun selectorCancelReason(context: Context, cancelReason: CancelReason, title: String, listener: (Int) -> Unit) {
        object : DialogUtils(context, R.layout.other_order_layout_assign_deliveryman) {
            override fun initLayout(hepler: ViewHepler?, dialog: Dialog?) {
                hepler!!.getView<TextView>(R.id.tv_delivery_cancel).setOnClickListener {
                    dialog!!.dismiss()
                }
                hepler.getView<TextView>(R.id.tv_title).text = title

                val confirmBtn: TextView = hepler.getView(R.id.tv_delivery_confirm)
                var selectIndex = -1

                val recycler = hepler.getView<RecyclerView>(R.id.rv_delivery)
                if (cancelReason.data.isNotEmpty() && cancelReason.data.size < 3) {
                    recycler.layoutManager = GridLayoutManager(context, cancelReason.data.size)
                } else {
                    recycler.layoutManager = GridLayoutManager(context, 3)
                }

                val cancelReasons = ArrayList<DeliveryBean.Data>()
                for (bean in cancelReason.data) {
                    val data = DeliveryBean.Data(bean.id, "", bean.content)
                    cancelReasons.add(data)
                }

                val data = ArrayList<String>()
                for (value in cancelReasons) {
                    data.add(value.userName)
                }
                val deliveryAdapter = DeliveryAdapter(data)
                recycler.adapter = deliveryAdapter

                deliveryAdapter.setOnItemClickListener { adapter, _, position ->
                    selectIndex = position
                    deliveryAdapter.selectIndex = position
                    adapter.notifyDataSetChanged()

                    confirmBtn.background = ContextCompat.getDrawable(context, R.drawable.shape_green_btn)
                }

                confirmBtn.setOnClickListener {
                    if (selectIndex != -1) {
                        listener.invoke(selectIndex)
                    } else {
                        ToastUtils.show(context, "請選擇一個取消原因")
                    }
                }
            }
        }.setWidth(WindowManager.LayoutParams.MATCH_PARENT)
                .setHeight((ArmsUtils.getScreenHeidth(context) * 0.5).toInt())
                .setGravity(Gravity.BOTTOM)
                .show()
    }

    /**
     * 獲取配送員信息
     */
    fun getDeliveryInfo(restaurantId: String, memberId: String) {
        launch({
            repository.getDeliveryInfo(restaurantId, memberId).apply {
                deliveryBean = this
            }
        }, {

        })
    }

    /**
     * 獲取餐廳第三方物流信息
     */
    fun getDeliveryConfigDTO(restaurantId: String, listener: (DeliveryConfig?) -> Unit) {
        launch({
            repository.getDeliveryConfigDTO(restaurantId).apply {
                listener.invoke(this)
            }
        }, {

        })
    }

    /**
     * 取消物流
     */
    fun cancelLogistics(restaurantId: Int, orderId: String, reasonId: String, reasonDesc: String, listener: (String) -> Unit) {
        launch({
            repository.cancelLogistics(restaurantId.toString(), orderId, reasonId, reasonDesc).apply {
                if (success) {
                    listener.invoke("已取消物流")
                } else {
                    listener.invoke(this.errMsg)
                }
            }
        }, {
            listener.invoke("取消物流失敗")
        })
    }

    /**
     * 取消訂單
     */
    fun cancelOrder(memberId: String, memberName: String, orderId: String, reasonId: String, reasonDesc: String, listener: (Boolean) -> Unit) {
        launch({
            repository.updateOrderStates(memberId, orderId, "6", memberName, reasonId, reasonDesc).apply {
                listener.invoke(code == "1")
            }
        }, {
            listener.invoke(false)
        })
    }

    /**
     * 獲取餐廳配置的取消原因
     */
    fun getCancelReason(brandId: Int, restaurantId: Int, type: Int, listener: (CancelReason?) -> Unit) {
        launch({
            repository.getCancelReason(brandId, restaurantId, type).apply {
                listener.invoke(this)
            }
        }, {
            listener.invoke(null)
        })
    }

    fun getMsgBean(what: Int, msg: String, state: Boolean): MessageBean {
        return MessageBean(what.toString(), msg, state, System.currentTimeMillis(), null)
    }

    var payTypeBean = MutableLiveData<List<PayMethod>>()

    /**
     * 獲取支付方式
     */
    fun getPayMethod(brandId: Int, restaurantId: Int) {
        launch({
            repository.getPayMethod(brandId, restaurantId, FoodSummaryConstans.TAKEAWAY_TYPE).apply {
                if (isSuccess && data != null && data.size > 0) {
                    payTypeBean.postValue(this.data)
                } else {
                    payTypeBean.postValue(null)
                }
            }
        }, {
            payTypeBean.postValue(null)
        })
    }

    private fun launch(block: suspend () -> Unit, error: suspend (Throwable) -> Unit) = viewModelScope.launch {
        try {
            block()
        } catch (e: Throwable) {
            error(e)
            e.printStackTrace()
        }
    }

}