package com.ypsx.yppos.viewmodel.request

import android.util.ArrayMap
import androidx.lifecycle.MutableLiveData
import com.elvishew.xlog.XLog
import com.ypsx.base.base.viewmodel.BaseViewModel
import com.ypsx.base.ext.launch
import com.ypsx.base.ext.request
import com.ypsx.base.ext.requestNoCheck
import com.ypsx.base.ext.util.toJson
import com.ypsx.base.util.dXLog
import com.ypsx.yppos.http.apiService
import com.ypsx.yppos.http.data.bean.*
import com.ypsx.yppos.http.data.entity.PosPayMethod
import com.ypsx.yppos.http.data.entity.PosProductStyle
import com.ypsx.yppos.http.data.entity.ProductActivityType
import com.ypsx.yppos.http.data.request.*
import com.ypsx.yppos.http.repository.request.HttpRequestCoroutine
import com.ypsx.yppos.http.state.UpdateUiState
import com.ypsx.yppos.room.entity.PosBuyPart
import com.ypsx.yppos.room.entity.PosConfig
import com.ypsx.yppos.room.entity.PosProduct
import com.ypsx.yppos.room.repository.PosBuyRepository
import com.ypsx.yppos.room.repository.PosConfigRepository
import com.ypsx.yppos.room.repository.PosProductRepository
import com.ypsx.yppos.utils.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap

/**
 * 本地扫描条码，如果是称重码，则搜索称重码商品，
 */
class RequestMainViewModel : BaseViewModel() {

    var posProduct = MutableLiveData<PosProduct>()
    var productItemData = MutableLiveData<ProductItem>()
    var productPromotionsResponse = MutableLiveData<ProductPromotionsResponse>()
    var posBuyPartData = MutableLiveData<List<PosBuyPart>>()
    var posBuyPartList = MutableLiveData<MutableList<InsertOrderProductDTO>>()
    var payAmountBean = MutableLiveData<PayAmountBean>()
    var map = HashMap<String, String>()
    var posConfig: PosConfig? = null
    var orderPromotions: List<OrderActivityResponse>? = null
    var payState = MutableLiveData<UpdateUiState<UploadOrderResponse>>()

    val paySuccessState = MutableLiveData<UpdateUiState<String>>()
    val paySuccessStateCash = MutableLiveData<UpdateUiState<CashPaySuccess>>()
    val memberInfoState = MutableLiveData<UpdateUiState<MemberInfoResponse>>();
    val cancelCouponState = MutableLiveData<UpdateUiState<String>>();


    val syncProductsState = MutableLiveData<UpdateUiState<String>>()

    var pluList = arrayListOf<PluRelation>()

    init {
        launch({ PosConfigRepository.getInstance().loadConfig() }, {
            posConfig = it
        })
    }


    fun getPlu(barCode: String) {
        val plu = barCode.substring(2, 7)

        val mnemonicCode = plu.toInt().toString()
        var price: Double = 0.0
        var weightCode: Double = 0.0
        if (barCode.length > 13) {
            val priceCode = barCode.substring(7, 12)
            price = priceCode.toDouble().div(100)

            val weight = barCode.substring(12, 17)
            weightCode = weight.toDouble().div(1000)
        } else {
            val weight = barCode.substring(7, 12)
            weightCode = weight.toDouble().div(1000)
        }
        "$mnemonicCode $weightCode".dXLog()

        launch({ PosProductRepository.getInstance().queryByMnemonicCode(mnemonicCode) }, {
            if (it == null) {
                "没找到该商品".toastSign()
            } else {
                it.toJson().dXLog()
                pluList.add(PluRelation(barCode, it.id))
//                map[barCode] = it.id
                val productItem = ProductItem(
                    it.merchantItemId!!,
                    it.id,
                    weightCode,
                    if (barCode.length > 13) price else it.sellPrice
                )
                productItem.toJson().dXLog()

                productItemData.postValue(productItem)
            }
        }, {

        })
    }

    fun getKeyWords(key: String) {
        if (key.isEmpty()) {
            "搜索商品条码/PLU".toast()
            return
        }
        launch({ PosProductRepository.getInstance().queryKeyWords(key) }, {
            if (it == null) {
                "没找到该商品".toastSign()
            } else {
                it.toJson().dXLog()
                when {
                    it.mnemonicCode.isEmpty() -> {
                        val productItem =
                            ProductItem(
                                it.merchantItemId!!,
                                it.id,
                                it.spec.toDouble(),
                                it.sellPrice
                            )
                        productItem.toJson().dXLog()
                        productItemData.postValue(productItem)
                    }
                    it.mnemonicCode == key -> {
                        posProduct.postValue(it)

                    }
                    else -> {
                        val productItem =
                            ProductItem(
                                it.merchantItemId!!,
                                it.id,
                                it.spec.toDouble(),
                                it.sellPrice
                            )
                        productItem.toJson().dXLog()
                        productItemData.postValue(productItem)
                    }
                }
            }
        }, {

        }

        )
    }

    fun addPluRelation(barcode: String, id: String) {
        pluList.add(PluRelation(barcode, id))
    }

    fun removePluRelation(position: Int) {
        if (pluList.size > position) {
            pluList.removeAt(position)
        }
    }

    fun request(request: ProductPromotionRequest) {
        request({ apiService.getProductPromotions(request) }, {
            "操作成功".toastSuccess()
            queryAllIn(it, request.confirm)
//            productPromotionsResponse.postValue(it)
        }, {
            it.errorMsg.toastFailed()
            orderPromotions = null
            errorAllIn(request)
        })
    }

    private fun errorAllIn(request: ProductPromotionRequest) {
        val products = request.products
        val list = ArrayList<String>(products.size)
        for (item in products) {
            list.add(item.productId)
        }

        launch({ PosProductRepository.getInstance().queryAllIn(list) }, {
            var list = mutableListOf<InsertOrderProductDTO>()
            var posProduct: PosProduct? = null
            var listNum = 0

            var amountTotal = 0.0 //总价值
            for ((index, product) in products.withIndex()) {
                for (item in it) {
                    if (product.productId == item.id) {
                        posProduct = item
                        break
                    }
                }

                if (posProduct?.style == PosProductStyle.WEIGHT.name) {
                    listNum += 1
                } else if (posProduct?.style == PosProductStyle.SINGLE.name) {
                    listNum += product.quantity.toInt()
                }
                val amount: Double = product.price.times(product.quantity) ?: 0.0
                amountTotal = BigDecimalUtils.forPlus(amountTotal.plus(amount))
                var weightCode = ""
                if (pluList.size > index) {
                    weightCode =
                        if (pluList[index].id == posProduct?.id) pluList[index].plu else ""

                }
                val posBuyPart = InsertOrderProductDTO(
                    activitys = null,
                    activityPrice = 0.0,
                    amount = amount ?: 0.0,
                    discountTotal = 0.0,
                    memberPrice = 0.0,
                    barCode = posProduct?.barCode!!,
                    cardNumber = null,
                    conversionRatio = posProduct.conversionRatio,
                    deleted = false,
                    priceType = "SALE_TYPE",
                    productId = posProduct.id,
                    price = product.price ?: 0.0,
                    quantity = product.quantity ?: 0.0,
                    tailAmount = 0,
                    weightCode = weightCode,
                    name = posProduct.name,
                    spec = posProduct.spec,
                    unit = posProduct.unit,
                    style = posProduct.style,
                    pluLevel = posProduct.pluLevel,
                    merchantItemId = posProduct.merchantItemId,
                    productNumber = posProduct.productNumber,
                    mnemonicCode = posProduct.mnemonicCode,discountCouponPrice = 0.0
                )
                posBuyPart.toJson().dXLog()
                list.add(posBuyPart)
            }
            posBuyPartList.postValue(list)
            payAmountBean.postValue(
                PayAmountBean(
                    payApportionAmount = amountTotal,
                    amount = amountTotal,
                    listNum = listNum
                )
            )
        })
    }

    fun queryAllIn(productPromotionsResponse: ProductPromotionsResponse, confirm: ConfirmRequest) {
        orderPromotions = productPromotionsResponse.orderPromotions

        var discountTotal = 0.0
        var payApportionAmount = 0.0
        var discountMoney = 0.0 //满减促销
        var discountTime = 0.0//分时促销
        var discountSpecial = 0.0//特价促销
        var discountMember = 0.0//会员优惠
        var discountCoupon = 0.0//优惠券优惠金额
        var amount = 0.0 //总价值

        productPromotionsResponse.orderPromotions?.forEach { item ->
            discountMoney += item.discountMoney
        }
        productPromotionsResponse.productPromotions.forEach { item ->
            amount = amount.plus(item.price.times(item.quantity))
            payApportionAmount = payApportionAmount.plus(item.payApportionAmount)
            if (item.activityInfo != null) {
                if (item.activityInfo?.activityType == ProductActivityType.TIMESHARE_ACTIVITY.name) {
                    discountTime += item.discountTotal
                } else {
                    if (item.activityInfo?.activityPrice!! > 0.0) {
                        discountSpecial += item.discountTotal
                    }
                }
            }
            if (item.priceType == "MEMBER_TYPE") {
                discountMember =
                    discountMoney.plus((item.price.minus(item.memberPrice!!)).times(item.quantity))
            }
            discountCoupon = discountCoupon.plus(item.couponDivideTotal)
        }
        discountTotal = discountMoney + discountSpecial + discountTime + discountMember

        val productPromotions = productPromotionsResponse.productPromotions
        val list = ArrayList<String>(productPromotions.size)
        for (item in productPromotions) {
            list.add(item.productId)
        }
        launch({ PosProductRepository.getInstance().queryAllIn(list) }, {
            var list = mutableListOf<InsertOrderProductDTO>()
            XLog.d("数量大小：${list.size}")
            var posProduct: PosProduct? = null
            var listNum = 0

            for ((index, product) in productPromotions.withIndex()) {
                for (item in it) {
                    if (product.productId == item.id) {
                        posProduct = item
                        break
                    }
                }
                var isPromotion = false
                if (!orderPromotions.isNullOrEmpty()) {
                    for (orderPromotion in orderPromotions!!) {
                        for (productPromotionDetailDTO in orderPromotion.productIds) {
                            if (productPromotionDetailDTO.productId == product.productId) {
                                isPromotion = true
                                break
                            }
                        }
                    }
                }
                if (posProduct?.style == PosProductStyle.WEIGHT.name) {
                    listNum += 1
                } else if (posProduct?.style == PosProductStyle.SINGLE.name) {
                    listNum += product.quantity.toInt()
                }
                var activityInfo = product.activityInfo
                var activitys: ArrayList<ActivityInfoDTO> = arrayListOf()
                if (activityInfo != null) {
                    activitys.add(activityInfo)
                }
                var activityPrice = activityInfo?.activityPrice ?: 0.0

                var weightCode = ""
                if (pluList.size > index) {

                    weightCode =
                        if (pluList[index].id == posProduct?.id) pluList[index].plu else ""
                    XLog.d("we$weightCode $index")

                }
                val posBuyPart = InsertOrderProductDTO(
                    activitys = activitys,
                    activityPrice = activityPrice,
                    amount = product.payApportionAmount ?: 0.0,
                    discountTotal = product.discountTotal ?: 0.0,
                    discountPrice = product.discountTotal.div(product.quantity),
                    memberPrice = product.memberPrice,
                    barCode = posProduct?.barCode!!,
                    cardNumber = null,
                    conversionRatio = posProduct.conversionRatio,
                    deleted = false,
                    priceType = product.priceType ?: "SALE_TYPE",
                    productId = posProduct.id,
                    price = product.price ?: 0.0,
                    quantity = product.quantity ?: 0.0,
                    tailAmount = 0,
                    weightCode = weightCode,
                    name = posProduct.name,
                    spec = posProduct.spec,
                    unit = posProduct.unit,
                    style = posProduct.style,
                    pluLevel = posProduct.pluLevel,
                    merchantItemId = posProduct.merchantItemId,
                    productNumber = posProduct.productNumber,
                    payApportionAmount = product.payApportionAmount,
                    isPromotion = isPromotion,
                    isVirtual = posProduct.isVirtual,
                    mnemonicCode = posProduct.mnemonicCode,
                    couponDivideTotal = product.couponDivideTotal,
                    discountCouponPrice = if (product.priceType == "MEMBER_TYPE"){
                        product.memberPrice?.minus(product.payApportionAmount)
                    }else{
                        product.price.minus(product.payApportionAmount)
                    }
                )
                posBuyPart.toJson().dXLog()
                list.add(posBuyPart)
            }
            posBuyPartList.postValue(list)

            payAmountBean.postValue(
                PayAmountBean(
                    BigDecimalUtils.forPlus(discountTotal),
                    BigDecimalUtils.forPlus(payApportionAmount),
                    BigDecimalUtils.forPlus(discountMoney),
                    BigDecimalUtils.forPlus(discountTime),
                    BigDecimalUtils.forPlus(discountSpecial),
                    BigDecimalUtils.forPlus(amount),
                    listNum,
                    BigDecimalUtils.forPlus(discountMember),
                    BigDecimalUtils.forPlus(discountCoupon),
                    productPromotionsResponse.coupon?.coupon,
                    isFinal = confirm.isFinal
                )
            )
        })
    }

    /**
     * 创建订单并支付
     */
    fun createOrder(
        orderNo: String,
        totalAmount: Double,
        payAmount: Double,
        promotionOnSaleTotal: Double,
        discountTotal: Double,
        productList: List<InsertOrderProductDTO>,
        payMethod: PosPayMethod,
        barcode: String,
        roundMoney: Double = 0.0,
        changeMoney: Double = 0.0,
        memberId: String,
        memberMobile: String,
        memberPoint: String,
        couponResponse: CouponInfoResponse?
    ) {
        val status = when (payMethod) {
            PosPayMethod.CASHPAY -> "FINISHED"
            else -> "CREATED"
        }
        val loginResponse = CacheUtil.getLoginResponse()
        val dataTime = DateUtil.getTodayDateTime()

        val insertOrderRequest = InsertOrderRequest(
            activitys = orderPromotions,
            couponResponse,
            createTime = dataTime,
            creatorId = loginResponse!!.loginUser.username ?: "",
            creatorName = loginResponse.loginUser.realName ?: "",
            orderNo = orderNo,
            einvoiceQrcodeUrl = "",
            memberId = memberId,
            mobile = memberMobile,
            posId = posConfig?.id ?: "",
            storeId = posConfig?.storeId ?: "",
            status = status,
            products = productList,
            totalAmount = totalAmount,
            promotionOnSaleTotal = promotionOnSaleTotal,
            discountTotal = discountTotal,
            payAmount = payAmount,
            roundPrice = roundMoney,
            changeAmount = changeMoney,
            payments = if (payMethod == PosPayMethod.CASHPAY)
                arrayListOf(
                    OrderPayment(
                        payMethod = payMethod.name,
                        payTime = dataTime,
                        total = totalAmount
                    )
                ) else null

        )
        requestNoCheck({
            HttpRequestCoroutine.createOrder(insertOrderRequest, barcode, payMethod)
        }, {
            if (it.payMethod == PosPayMethod.CASHPAY.name) {
                getOrderDetailById(it.orderId, "",  memberPoint)
                val cashPaySuccess = CashPaySuccess(payAmount, changeMoney, roundMoney, orderNo)
                val uiState = UpdateUiState(isSuccess = true, cashPaySuccess)
                paySuccessStateCash.postValue(uiState)
            } else {
                val uiState = UpdateUiState(isSuccess = true, it)
                payState.postValue(uiState)
            }
        }, {
            val uiState = UpdateUiState(isSuccess = false, data = "", it.errorMsg)
            paySuccessState.postValue(uiState)
        })
    }

    /**
     * 每隔2s轮询一次，获取支付订单状态
     */
    fun getStateByOrderId(
        orderId: String,
        totalAmount: Double,
        authCode: String,
        memberPoint: String
    ) {
        request({ HttpRequestCoroutine.getOrderStatusById(orderId) }, {
            getOrderDetailById(orderId, authCode,  memberPoint)
            val uiState = UpdateUiState(isSuccess = true, totalAmount.toString())
            paySuccessState.postValue(uiState)
        }, {
            if (it.errCode == 100001) {
                //付款超时
                return@request
            }
            val uiState = UpdateUiState(isSuccess = false, data = "", errorMsg = it.errorMsg)
            paySuccessState.postValue(uiState)
        })
    }


    /**
     * 获取订单详情，并保存数据库打印小票
     */
    private fun getOrderDetailById(
        orderId: String,
        authCode: String,
        memberPoint: String
    ) {
        request({ apiService.getOrderDetailById(orderId) }, {
            "${CacheUtil.getRealName()}付款成功，保存数据库并打印".dXLog()
            pluList.clear()
            launch({
                val currentTimeMillis = System.currentTimeMillis()
//                PrintUtils.print(posConfig!!, it,memberPoint)
                PosBuyRepository.getInstance().savePosBuy(it, authCode,memberPoint)
                "打印和保存数据库使用耗时：：${System.currentTimeMillis() - currentTimeMillis}".dXLog()
            }, {
                "打印完成".dXLog()
                "打印完成".toastSuccess()
            })

        })
    }


    /**
     * 获取阿里云配置
     */
    fun getOptions() {
        request({ apiService.getOptionsByKeys() }, {
            for (optionsResponse in it) {
                CacheUtil.setAliYunKey(optionsResponse.key, optionsResponse.value)
            }
        }, {
            CacheUtil.setAliYunKey(dfs_aliyunAccessKeyId, "")
            CacheUtil.setAliYunKey(dfs_aliyunAccessKeySecret, "")
            CacheUtil.setAliYunKey(dfs_aliyunBucketName, "")
            CacheUtil.setAliYunKey(dfs_aliyunDomain, "")
            CacheUtil.setAliYunKey(dfs_aliyunEndPoint, "")
            CacheUtil.setAliYunKey(dfs_aliyunPrefix, "")
        })
    }

    fun syncProducts() {
        request({ HttpRequestCoroutine.syncProducts(posConfig?.storeId!!) }, {
            val uiState = UpdateUiState(isSuccess = true, data = "", errorMsg = "")
            syncProductsState.postValue(uiState)
        }, {
            val uiState = UpdateUiState(isSuccess = false, data = "", errorMsg = it.errorMsg)
            syncProductsState.postValue(uiState)
        })
    }

    /**
     * 根据手机号获取会员信息
     */
    fun getMemberByMobile(mobile: String) {
        requestNoCheck({ apiService.getMemberByMobile(mobile) }, {
            val uiState = UpdateUiState(isSuccess = it.isSuccess(), it.data, mobile)
            memberInfoState.value = uiState
        })
    }

    /**
     * 注册会员
     */
    fun registerMember(mobile: String, gender: Int, ageGroup: String, shopId: String) {
        request({
            apiService.registerMember(
                RegisterMemberRequest(
                    ageGroup,
                    gender,
                    mobile,
                    shopId
                )
            )
        }, {
            val uiState = UpdateUiState(isSuccess = true, it, mobile)
            memberInfoState.value = uiState
        }, {
            it.errorMsg.toast()
        })
    }

    /**
     * 释放优惠券
     */
    fun cancelCoupon(
        shopId: String,
        memberId: String,
        orderNo: String,
        couponResponse: CouponInfoResponse
    ) {
        val cancelCouponRequest = CancelCouponRequest(shopId, memberId, orderNo, couponResponse)
        requestNoCheck({ apiService.cancelCoupon(cancelCouponRequest) }, {
            val uiState = UpdateUiState(it.isSuccess(), "",it.getResponseMsg())
            cancelCouponState.value = uiState
        })
    }


}