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.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.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

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

object PrintUtils {
    private lateinit var printerManager: PrinterManager
    fun init() {
        printerManager = PrinterManager()
        printerManager.open()
    }


    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()
            height += printerManager.drawTextEx(
                "收银员：${loginResponse!!.loginUser.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 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
                        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
                        }
                    }
                }

                val name = if (discountMoney > 0.0 && isPromotion) {
                    "${index + 1} *${product.name}*"
                } else {
                    "${index + 1} ${product.name}"
                }
                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, fontSize, 0, fontStyle, 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}",
                    "数量:${orderResponse.buyNumber}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "实付款：${orderResponse.payAmount}",
                    "找零金额：${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 = ""
            if (payments.isNotEmpty()) {
                total = payments[0].total.toString()
                payMethod = when (payments[0].payMethod) {
                    PosPayMethod.CCB_BAR_PAY.name -> {
                        "扫码支付"
                    }
                    PosPayMethod.CARDPAY.name -> {
                        "会员余额支付"
                    }
                    else -> {
                        ""
                    }
                }
            }
            height += printerManager.drawTextEx(
                "付款方式：$payMethod    $total", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                "  实际扣款：${total}", 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() {
        printerManager.close()
    }

    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 15 - length(barCode)) {
            builder.append(" ")
        }
        builder.append(paymentProductQuantity.toString())
        for (i in 0 until 5 - length(paymentProductQuantity.toString())) {
            builder.append(" ")
        }
        builder.append(price.toString())
        for (i in 0 until 7 - length(price.toString())) {
            builder.append(" ")
        }

        builder.append(productAmount.toString())
        for (i in 0 until 5 - length(productAmount.toString())) {
            builder.append(" ")
        }
        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()
    }

    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()
            height += printerManager.drawTextEx(
                "收银员：${loginResponse!!.loginUser.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 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
                            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
                            }
                        }
                    }


//
                    val name = if (discountMoney > 0.0 && isPromotion) {
                        "${index + 1} *${product.name}*"
                    }else{
                        "${index + 1} ${product.name}"
                    }
                    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, fontSize, 0, fontStyle, 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}",
                    "数量:${posBuy.buyNumber}"
                ),
                0,
                height,
                384,
                -1,
                fontName,
                fontSize,
                0,
                fontStyle,
                0
            )

            height += printerManager.drawTextEx(
                getAmountCenterSpace(
                    "实付款：${posBuy.payAmount}",
                    "找零金额：${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 = ""
            if (posBuyPayment != null) {
                total = posBuyPayment.total.toString()
                payMethod = when (posBuyPayment.payMethod) {
                    PosPayMethod.CCB_BAR_PAY.name -> {
                        "扫码支付"
                    }
                    PosPayMethod.CARDPAY.name -> {
                        "会员余额支付"
                    }
                    else -> {
                        ""
                    }
                }
            }
            height += printerManager.drawTextEx(
                "付款方式：$payMethod    $total", 0, height, 384, -1, fontName, fontSize, 0, fontStyle, 0
            )

            height += printerManager.drawTextEx(
                "  实际扣款：${total}", 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)
    }

}