package com.ypsx.yppos.utils

import android.device.PrinterManager
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.Utils.runOnUiThread
import com.elvishew.xlog.XLog
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.ypsx.base.ext.util.toJson
import com.ypsx.base.util.dXLog
import com.ypsx.yppos.http.data.bean.ActivityInfoDTO
import com.ypsx.yppos.http.data.bean.OrderActivityResponse
import com.ypsx.yppos.http.data.bean.OrderDetailsResponse
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.room.entity.PosBuy
import com.ypsx.yppos.room.entity.PosBuyPart
import com.ypsx.yppos.room.entity.PosBuyPayment
import com.ypsx.yppos.room.entity.PosConfig
import java.math.BigDecimal
import java.math.RoundingMode


object PrintUtils {
    private const val PRNSTS_OK = 0 //OK

    private const val PRNSTS_OUT_OF_PAPER = -1 //Out of paper

    private const val PRNSTS_OVER_HEAT = -2 //Over heat

    private const val PRNSTS_UNDER_VOLTAGE = -3 //under voltage

    private const val PRNSTS_BUSY = -4 //Device is busy

    private const val PRNSTS_ERR = -256 //Common error

    private const val PRNSTS_ERR_DRIVER = -257 //Printer Driver error
    private lateinit var printerManager: PrinterManager
    fun init() {
        try {
            printerManager = PrinterManager()
            printerManager.open()
        } catch (e: Exception) {
            "打印机打开失败"
        }
    }


    fun print(posConfig: PosConfig, orderResponse: OrderDetailsResponse) {
        val fontSize = 24
        val fontStyle = 0x0000
        val fontBold = 0x0001
        val fontName = "simsun"
        var status: Int = printerManager.status
        var height = 0
        if (status == PRNSTS_OK) {
            printerManager.setupPage(384, -1)
            val header = getSpace("欢迎光临谊品生鲜")
            val tag1 = "==============================="
            val tag2 = "- - - - - - - - - - - - - - - - "
            val qrcodeUrl = posConfig.einvoiceQrcodeUrlPrefix + "?orderId=" + orderResponse.orderNo

            height += printerManager.drawTextEx(
                header, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            height += printerManager.drawTextEx(
                getSpace(posConfig.storeName!!),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            height += printerManager.drawTextEx(
                getSpace("销售小票"), 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                "机号：${posConfig.code}", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            val loginResponse = CacheUtil.getLoginResponse()
            var realName = loginResponse!!.loginUser.realName
            if (realName!!.length >= 2) {
                val first = realName.substring(0, 1)
                val end = realName.substring(2)
                realName = "$first*$end"
            }
            height += printerManager.drawTextEx(
                "收银员：${realName}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "小票号：${orderResponse.orderNo}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            height += printerManager.drawTextEx(
                "日期：${orderResponse.createTime}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )
            height += printerManager.drawTextEx(
                "商品名称      数量  单价  成交价", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            var buyNum = 0
            var discountTime = 0.0 //分时
            var discountSpecial = 0.0 //特价
            var discountMoney = 0.0 //满减

            orderResponse.activitys?.forEach { item ->
                discountMoney += item.discountMoney
            }

            for ((index, product) in orderResponse.products.withIndex()) {
                var discountMoney = 0.0
                if (product.activitys != null) {
                    product.activitys!!.forEach { item ->
                        discountMoney = (product.price - item.activityPrice) * product.quantity
                        if (item.activityType == ProductActivityType.TIMESHARE_ACTIVITY.name) {
                            discountTime += discountMoney
                        } else {
                            if (discountMoney > 0.0) {
                                discountSpecial += discountMoney
                            }
                        }
                    }
                }
                var isPromotion = false

                orderResponse.activitys?.forEach { item ->
                    for (productPromotionDetailDTO in item.productIds) {
                        if (productPromotionDetailDTO.productId == product.productId) {
                            isPromotion = true
                            break
                        }
                    }
                }
                if (product.style == PosProductStyle.WEIGHT.name) {
                    buyNum += 1
                } else if (product.style == PosProductStyle.SINGLE.name) {
                    buyNum += product.quantity.toInt()
                }

                var name = if (discountMoney > 0.0 && isPromotion) {
                    "${index + 1} *${product.name}*"
                } else {
                    "${index + 1} ${product.name}"
                }
                if (name.length > 17) {
                    name = name.substring(0, 15) + "..."
                }
                height += printerManager.drawTextEx(
                    name,
                    0,
                    height,
                    384,
                    -1,
                    fontName,
                    fontSize,
                    0,
                    fontStyle,
                    0
                )

                height += printerManager.drawTextEx(
                    getPriceSpace(
                        product.barCode,
                        product.paymentProductQuantity,
                        product.price,
                        product.productAmount
                    ), 0, height, 384, -1, fontName, 22, 0, 0, 0
                )
            }

//            height += printerManager.drawTextEx(
//                "      ",
//                0,
//                height,
//                384,
//                -1,
//                fontName,
//                fontSize,
//                0,
//                fontStyle,
//                0
//            )
            height += printerManager.drawTextEx(
                "促销特价优惠：${BigDecimalUtils.forPlus(discountSpecial)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "分时折扣优惠：${BigDecimalUtils.forPlus(discountTime)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "满金额减免优惠：${BigDecimalUtils.forPlus(discountMoney)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )

            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "应付款：${orderResponse.payAmount}",
                    "数量:${buyNum}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            val minus = BigDecimal.valueOf(orderResponse.payAmount)
                .minus(BigDecimal.valueOf(orderResponse.roundPrice))
            val scale1 =
                minus.plus(BigDecimal.valueOf(orderResponse.changeAmount))
                    .setScale(2).toDouble()
            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "实付款：${scale1}",
                    "找零金额：${orderResponse.changeAmount}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )
            var payments = orderResponse.payments
            var payMethod = ""
            var total = orderResponse.totalAmount
            if (payments.isNotEmpty()) {

                payMethod = when (payments[0].payMethod) {
                    PosPayMethod.CCB_BAR_PAY.name, PosPayMethod.LCSW_BAR_PAY.name -> {
                        "扫码支付"
                    }
                    PosPayMethod.CARDPAY.name -> {
                        "会员余额支付"
                    }
                    PosPayMethod.CASHPAY.name -> {
                        "现金支付"
                    }
                    else -> {
                        ""
                    }
                }
            } else {
                payMethod = "现金支付"
            }
            height += printerManager.drawTextEx(
                "付款方式：$payMethod    $total", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            val scale = minus.setScale(2).toDouble()
            height += printerManager.drawTextEx(
                "  实际扣款：${scale}", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )


            height += printerManager.drawTextEx(
                posConfig.ticketBottom, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            if (posConfig.printTicketBar) {
                printerManager.drawBarcode(
                    orderResponse.orderNo,
                    80,
                    height,
                    58,
                    8,
                    180,
                    0
                )
                height += 180

                height += printerManager.drawTextEx(
                    getSpace("小票号"), 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
                )
            }

            if (posConfig.printTicketQrcode) {
                height += printerManager.drawTextEx(
                    tag2, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
                )

                height += printerManager.drawTextEx(
                    "开票日期以开具当天为准，建议您及时下载电子发票",
                    0,
                    height,
                    384,
                    -1,
                    fontName,
                    fontSize,
                    0,
                    fontStyle,
                    0
                )

                printerManager.drawBarcode(
                    qrcodeUrl,
                    30,
                    height,
                    58,
                    8,
                    280,
                    0
                )
                height += 280

                height += printerManager.drawTextEx(
                    tag2, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
                )
            }


            height += printerManager.drawTextEx(
                "\n\n", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

//printerManager.drawText(tag1,)
            status = printerManager.printPage(0) //Execution printing
            printerManager.paperFeed(16) //paper feed
        }
        updatePrintStatus(status)
    }


    fun close() {
        try {
            printerManager.close()
        } catch (e: Exception) {

        }
    }

    private fun getSpace(content: String): String? {
        val lengthTo = 30
        val start = (lengthTo - length(content)) / 2
        val builder = StringBuilder()
        for (i in 0 until start) {
            builder.append(" ")
        }
        builder.append(content)
        return builder.toString()
    }

    private fun getPriceSpace(
        barCode: String,
        paymentProductQuantity: Double,
        price: Double,
        productAmount: Double
    ): String {
        val builder = StringBuilder()
        builder.append(barCode)
        for (i in 0 until 14 - length(barCode)) {
            builder.append(" ")
        }
        builder.append(paymentProductQuantity.toString())
        for (i in 0 until 6 - length(paymentProductQuantity.toString())) {
            builder.append(" ")
        }
        for (i in 0 until 7 - length(price.toString())) {
            builder.append(" ")
        }
        builder.append(price.toString())
        for (i in 0 until 7 - length(productAmount.toString())) {
            builder.append(" ")
        }
        builder.append(productAmount.toString())
        return builder.toString()
    }


    private fun getAmountCenterSpace(start: String, end: String): String {
        val builder = StringBuilder()
        builder.append(start)
        for (i in 0 until 16 - length(start)) {
            builder.append(" ")
        }
        builder.append(end)
        for (i in 0 until 16 - length(end)) {
            builder.append(" ")
        }
        return builder.toString()
    }

    private fun length(value: String): Int {
        var valueLength = 0
        val chinese: String = "[\u0391-\uFFE5]"
        /* 获取字段值的长度，如果含中文字符，则每个中文字符长度为2，否则为1 */
        for (i in value.indices) {
            /* 获取一个字符 */
            val temp = value.substring(i, i + 1)
            /* 判断是否为中文字符 */
            valueLength += if (temp.matches(Regex(chinese))) {
                /* 中文字符长度为2 */
                2
            } else {
                /* 其他字符长度为1 */
                1
            }
        }
        return valueLength
    }

    private fun updatePrintStatus(status: Int) {
        runOnUiThread(Runnable {
            when (status) {
                PRNSTS_OUT_OF_PAPER -> {
                    "缺纸!!!".toastSign()
                }
                PRNSTS_OVER_HEAT -> {
                    "过温保护!!!".toastSign()
                }
                PRNSTS_UNDER_VOLTAGE -> {
                    "电池电压过低!!!".toastSign()
                }
                PRNSTS_BUSY -> {
                    "打印机忙!!!".toastSign()
                }
                PRNSTS_ERR -> {
                    "打印机出错!!!".toastSign()
                }
                PRNSTS_ERR_DRIVER -> {
                    "打印机驱动出错!!!".toastSign()
                }
            }
        })
    }


    fun printLast(
        posConfig: PosConfig,
        posBuyPayment: PosBuyPayment?,
        posBuy: PosBuy,
        posBuyParts: List<PosBuyPart>?
    ) {

        val fontSize = 24
        val fontStyle = 0x0000
        val fontBold = 0x0001
        val fontName = "simsun"
        var status: Int = printerManager.status
        var height = 0
        if (status == PRNSTS_OK) {
            printerManager.setupPage(384, -1)
            val header = getSpace("欢迎光临谊品生鲜")
            val tag1 = "==============================="
            val tag2 = "- - - - - - - - - - - - - - - - "
            val qrcodeUrl = posConfig.einvoiceQrcodeUrlPrefix + "?orderId=" + posBuy.orderNo

            height += printerManager.drawTextEx(
                header, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            height += printerManager.drawTextEx(
                getSpace(posConfig.storeName!!),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            height += printerManager.drawTextEx(
                getSpace("重打销售小票"), 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                "机号：${posConfig.code}", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            val loginResponse = CacheUtil.getLoginResponse()

            var realName = loginResponse!!.loginUser.realName
            if (realName!!.length >= 2) {
                val first = realName.substring(0, 1)
                val end = realName.substring(2)
                realName = "$first*$end"
            }
            height += printerManager.drawTextEx(
                "收银员：${realName}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "小票号：${posBuy.orderNo}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            height += printerManager.drawTextEx(
                "日期：${posBuy.createTime}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )
            height += printerManager.drawTextEx(
                "商品名称      数量  单价  成交价", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )
            var buyNum = 0
            var discountTime = 0.0 //分时
            var discountSpecial = 0.0 //特价
            var discountMoney = 0.0 //满减
            var list: List<OrderActivityResponse>? = null
            if (posBuy.activitys != null && posBuy.activitys != "") {
                list =
                    Gson().fromJson(
                        posBuy.activitys,
                        object : TypeToken<List<OrderActivityResponse>>() {}.type
                    )
                list?.forEach { item ->
                    item.toJson().dXLog()
                    discountMoney += item.discountMoney
                }
            }

//            for ((index, product) in orderResponse.products.withIndex()) {
//                if (product.activitys != null) {
//                    product.activitys!!.forEach { item ->
//                        if (item.activityType == ProductActivityType.TIMESHARE_ACTIVITY.name) {
//                            discountTime += item.discountMoney
//                        } else {
//                            if (item.discountMoney > 0.0) {
//                                discountSpecial += item.discountMoney
//                            }
//                        }
//                    }
//                }
//
            if (!posBuyParts.isNullOrEmpty()) {
                for ((index, product) in posBuyParts.withIndex()) {
                    var discountMoney = 0.0
                    var isPromotion = false

                    if (product.activitys != null && product.activitys != "") {
//                        XLog.d(product.activitys)

                        val activityInfoDTO: List<ActivityInfoDTO> =
                            Gson().fromJson(
                                product.activitys,
                                object : TypeToken<List<ActivityInfoDTO>>() {}.type
                            )
                        activityInfoDTO.forEach { item ->
//                            item.toJson().dXLog()
                            discountMoney = (product.price - item.activityPrice) * product.quantity
                            if (item.activityType == ProductActivityType.TIMESHARE_ACTIVITY.name) {
                                discountTime += discountMoney
                            } else {
                                if (discountMoney > 0.0) {
                                    discountSpecial += discountMoney
                                }
                            }
                        }
                    }
                    list?.forEach { item ->
                        for (productPromotionDetailDTO in item.productIds) {
                            if (productPromotionDetailDTO.productId == product.productId) {
                                isPromotion = true
                                break
                            }
                        }
                    }


//
                    var name = if (discountMoney > 0.0 && isPromotion) {
                        "${index + 1} *${product.name}*"
                    } else {
                        "${index + 1} ${product.name}"
                    }
                    if (product.style == PosProductStyle.WEIGHT.name) {
                        buyNum += 1
                    } else if (product.style == PosProductStyle.SINGLE.name) {
                        buyNum += product.quantity.toInt()
                    }
                    if (name.length > 17) {
                        name = name.substring(0, 15) + "..."
                    }
                    height += printerManager.drawTextEx(
                        name,
                        0,
                        height,
                        384,
                        -1,
                        fontName,
                        fontSize,
                        0,
                        fontStyle,
                        0
                    )

                    height += printerManager.drawTextEx(
                        getPriceSpace(
                            product.barCode,
                            product.quantity,
                            product.price,
                            product.amount
                        ), 0, height, 384, -1, fontName, 22, 0, 0, 0
                    )
                }
            }

//            height += printerManager.drawTextEx(
//                "      ",
//                0,
//                height,
//                384,
//                -1,
//                fontName,
//                fontSize,
//                0,
//                fontStyle,
//                0
//            )
            height += printerManager.drawTextEx(
                "促销特价优惠：${BigDecimalUtils.forPlus(discountSpecial)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "分时折扣优惠：${BigDecimalUtils.forPlus(discountTime)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                "满金额减免优惠：${BigDecimalUtils.forPlus(discountMoney)}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )

            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "应付款：${posBuy.totalAmount}",
                    "数量:${buyNum}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            val minus = BigDecimal.valueOf(posBuy.totalAmount)
                .minus(BigDecimal.valueOf(posBuy.roundPrice))
            val scale1 =
                minus.plus(BigDecimal.valueOf(posBuy.changeAmount))
                    .setScale(2, RoundingMode.HALF_UP).toDouble()
            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "实付款：${scale1}",
                    "找零金额：${posBuy.changeAmount}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )

            var payMethod = ""
            var total = ""
            payMethod = if (posBuyPayment == null) {
                "现金支付"
            } else {
                when (posBuyPayment.payMethod) {
                    PosPayMethod.CCB_BAR_PAY.name, PosPayMethod.LCSW_BAR_PAY.name -> {
                        "扫码支付"
                    }
                    PosPayMethod.CARDPAY.name -> {
                        "会员余额支付"
                    }
                    PosPayMethod.CASHPAY.name -> {
                        "现金支付"
                    }
                    else -> {
                        ""
                    }
                }
            }
            height += printerManager.drawTextEx(
                "付款方式：$payMethod    ${posBuy.totalAmount}",
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )
            val scale = minus.setScale(2).toDouble()
            height += printerManager.drawTextEx(
                "  实际扣款：${scale}", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                tag1, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
            )


            height += printerManager.drawTextEx(
                posConfig.ticketBottom, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            if (posConfig.printTicketBar) {
                printerManager.drawBarcode(
                    posBuy.orderNo,
                    80,
                    height,
                    58,
                    8,
                    180,
                    0
                )
                height += 180

                height += printerManager.drawTextEx(
                    getSpace("小票号"), 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
                )
            }

            if (posConfig.printTicketQrcode) {
                height += printerManager.drawTextEx(
                    tag2, 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
                )

                height += printerManager.drawTextEx(
                    "开票日期以开具当天为准，建议您及时下载电子发票",
                    0,
                    height,
                    384,
                    -1,
                    fontName,
                    fontSize,
                    0,
                    fontStyle,
                    0
                )

                printerManager.drawBarcode(
                    qrcodeUrl,
                    30,
                    height,
                    58,
                    8,
                    280,
                    0
                )
                height += 280

                height += printerManager.drawTextEx(
                    tag2, 0, height, 384, -1, fontName, fontSize, 0, fontBold, 0
                )
            }


            height += printerManager.drawTextEx(
                "\n\n", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

//printerManager.drawText(tag1,)
            status = printerManager.printPage(0) //Execution printing
            printerManager.paperFeed(16) //paper feed
        }
        updatePrintStatus(status)
    }

}