package com.czg.service.order.print;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.czg.account.dto.HandoverRecordDTO;
import com.czg.account.entity.HandoverRecord;
import com.czg.account.entity.PrintMachine;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.order.entity.OrderDetail;
import com.czg.order.entity.OrderInfo;
import com.czg.service.order.enums.OrderStatusEnums;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 云享印打印机
 *
 * @author Administrator
 */
@Slf4j
@Component
public class YxyPrinter extends PrinterHandler implements PrinterImpl {

    //请求地址
    private static final String URL_STR = "https://ioe.car900.com/v1/openApi/dev/customPrint.json";
    //APPID
    private static final String APP_ID = "ZF544";
    //USERCODE
    private static final String USER_CODE = "ZF544";
    //APPSECRET
    private static final String APP_SECRET = "2022bsjZF544GAH";

    @Resource
    private ShopInfoService shopInfoService;

    @Resource
    private RestTemplate restTemplate;

    public YxyPrinter() {
        super("云想印");
    }

    private PrintSignLabel printSignLabel = new PrintSignLabel()
            .setBr("<BR>")
            .setCut("<PCUT>")
            .setOut("OUT")
            .setF(new String[]{"<F>", "</F>"})
            .setL(new String[]{"<L>", "</L>"})
            .setS(new String[]{"<S>", "</S>"})
            .setQr(new String[]{"<QR>", "</QR>"})
            .setCenter(new String[]{"<C>", "</C>"})
            .setCenterBold(new String[]{"<CB>", "</CB>"})
            .setRs("RS")
            .setBold(new String[]{"<B>", "</B>"});

    @Override
    public PrintSignLabel getSignLabelInfo() {
        return printSignLabel;
    }


    @Override
    public <R> R sendPrintRequest(String address, String metaPrintData, String voiceData, String printNum) {
        log.info("开始请求云享印，请求数据：{}, {}", voiceData, metaPrintData);
        //设备名称
        //行为方式 1:只打印数据 2:只播放信息 3:打印数据并播放信息
//        actWay = 3;
        //打印联数
//        int cn = 1;
        //打印内容
        //播报语音数据体,字段参考文档IOT_XY_API11001
        String time = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString();

        Map<String, String> param = getToken(time, uuid);
        //参数
        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("token", param.get("TOKEN"));
        multiValueMap.add("devName", address);
        multiValueMap.add("actWay", 3);
        multiValueMap.add("cn", printNum);
        multiValueMap.add("data", metaPrintData);
        multiValueMap.add("voiceJson", voiceData);
        multiValueMap.add("appId", APP_ID);
        multiValueMap.add("timestamp", time);
        multiValueMap.add("requestId", uuid);
        multiValueMap.add("userCode", USER_CODE);
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(multiValueMap, header);
        String httpResponse = restTemplate.postForObject(URL_STR,
                httpEntity, String.class);

        log.info("请求云享印成功，响应数据: {}", httpResponse);
        return (R) httpResponse;
    }

    @Override
    protected void normalDishesPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) {
        String buildDishPrintData = buildDishPrintData(false, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
                orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
        String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单，请及时处理\"}";
//        String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
        Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
//        sendPrintRequest(voiceJson, 3, 1, machine.getAddress(), data);
        printMachineLogService.save(machine, "新订单", buildDishPrintData, resp);

    }

    @Override
    protected void returnDishesPrint(OrderInfo orderInfo, OrderDetail orderDetail, PrintMachine machine) {
        String buildDishPrintData = buildDishPrintData(true, getPickupNum(orderInfo), DateUtil.format(orderDetail.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), orderDetail.getProductName(), orderDetail.getSkuName(),
                orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
//        String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单，请及时处理\"}";
        String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
        Object resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
        printMachineLogService.save(machine, "退款单", buildDishPrintData, resp);

    }

    @Override
    protected void returnOrderPrint(OrderInfo orderInfo, PrintMachine machine, String balance, List<OrderDetail> detailList) {
        ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
        PrintInfoDTO printInfoDTO = new PrintInfoDTO().setShopName(shopInfo.getShopName()).setPrintType("普通打印").setPickupNum(getPickupNum(orderInfo))
                .setOrderNo(orderInfo.getOrderNo()).setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss")).setOperator("【POS-1】001").setPayAmount(orderInfo.getPayAmount().toPlainString())
                .setOriginalAmount(orderInfo.getOriginAmount().toPlainString()).setReturn(isReturn(orderInfo))
                .setBalance(balance).setPayType((ObjectUtil.isEmpty(orderInfo.getPayType()) || ObjectUtil.isNull(orderInfo.getPayType()) ? "" : orderInfo.getPayType())).setIntegral("0")
                .setOutNumber(orderInfo.getTakeCode()).setPrintTitle("结算单")
                .setRemark(orderInfo.getRemark()).setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());

        String data = buildOrderPrintData(printInfoDTO, detailList);
        String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单，请及时处理\"}";
//        String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
        String printerNum = "1";
        if (StrUtil.isNotBlank(machine.getPrintQty())) {
            printerNum = machine.getPrintQty().split("\\^")[1];
        }
        String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
        printMachineLogService.save(machine, "新订单", data, resp);

    }

    @Override
    protected void normalOrderPrint(OrderInfo orderInfo, boolean isPre, PrintMachine machine, String balance, List<OrderDetail> detailList) {
        ShopInfo shopInfo = shopInfoService.getById(orderInfo.getShopId());
        long count = orderInfoService.count(new QueryWrapper().eq(OrderInfo::getTradeDay, orderInfo.getTradeDay())
                .eq(OrderInfo::getStatus, OrderStatusEnums.DONE.getCode())
                .eq(OrderInfo::getShopId, orderInfo.getShopId())
                .le(OrderInfo::getCreateTime, orderInfo.getCreateTime()));
        PrintInfoDTO printInfoDTO = new PrintInfoDTO().setShopName(shopInfo.getShopName())
                .setPrintType("普通打印").setPickupNum(getPickupNum(orderInfo))
                .setOrderNo(orderInfo.getOrderNo()).setTradeDate(DateUtil.format(orderInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss")).setOperator("【POS-1】001").setPayAmount(orderInfo.getPayAmount().toPlainString())
                .setOriginalAmount((orderInfo.getOriginAmount().add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee())).toPlainString()).setReturn(isReturn(orderInfo))
                .setBalance(balance).setPayType((ObjectUtil.isEmpty(orderInfo.getPayType()) || ObjectUtil.isNull(orderInfo.getPayType()) ? "" : orderInfo.getPayType())).setIntegral("0")
                .setOutNumber(orderInfo.getTakeCode()).setPrintTitle(isPre ? "预结算单" : "结算单")
                .setCount(count)
                .setRemark(orderInfo.getRemark())
                .setDiscountAmount((orderInfo.getOriginAmount().add(orderInfo.getSeatAmount()).add(orderInfo.getPackFee()).subtract(orderInfo.getPayAmount())).toPlainString());
        printInfoDTO.setPrintTitle(printInfoDTO.getPrintTitle());
        if(orderInfo.getSeatNum() != null && orderInfo.getSeatAmount().compareTo(BigDecimal.ZERO) > 0){
            printInfoDTO.setSeatNum(orderInfo.getSeatNum().toString());
            printInfoDTO.setSeatAmount(orderInfo.getSeatAmount().toPlainString());
        }
        if(orderInfo.getPackFee().compareTo(BigDecimal.ZERO) > 0){
            printInfoDTO.setPackFee(orderInfo.getPackFee().toPlainString());
        }

        String data = buildOrderPrintData(printInfoDTO, detailList);
        String voiceJson = "{\"PbizType\":\"2\",\"content\":\"您有一笔新的订单，请及时处理\"}";
//        String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
        String printerNum = "1";
        if (StrUtil.isNotBlank(machine.getPrintQty())) {
            printerNum = machine.getPrintQty().split("\\^")[1];
        }
        String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
//        printMachineLogService.save(machine, printType, data, resp);
        printMachineLogService.save(machine, "新订单", data, resp);

    }

    @Override
    protected void callNumPrint(PrintMachine machine, String callNum, String shopName, String tableName, String tableNote, String preNum, String codeUrl, LocalDateTime takeTime, String shopNote) {
        String resp = buildCallTicketData(shopName, tableName, callNum, preNum, codeUrl, shopNote, takeTime);
        sendPrintRequest(machine.getAddress(), resp, null, "1");
    }

    @Override
    protected void handoverPrint(PrintMachine machine, HandoverRecordDTO record) {
        String string = buildHandoverData(record);
        String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
        sendPrintRequest(machine.getAddress(), string, voiceJson, "1");
    }

    /**
     * 获取TOKEN值
     *
     * @param timestamp 时间戳，13位
     * @param requestId 请求ID，自定义
     * @return token信息
     */
    private static Map<String, String> getToken(String timestamp, String requestId) {
        StringBuilder token = new StringBuilder();
        StringBuilder encode = new StringBuilder();
        SortedMap<String, Object> map = new TreeMap<>();
        map.put("appId", APP_ID);
        map.put("timestamp", timestamp);
        map.put("requestId", requestId);
        map.put("userCode", USER_CODE);
        for (Map.Entry<String, Object> next : map.entrySet()) {
            String key = next.getKey();
            Object value = next.getValue();
            token.append(key).append(value);
            encode.append(key).append("=").append(value).append("&");
        }
        Map<String, String> finalMap = new HashMap<>();
        finalMap.put("ENCODE", encode.toString());
        finalMap.put("TOKEN", SecureUtil.md5(token + APP_SECRET).toUpperCase());
        return finalMap;
    }


}
