
package com.tmerclub.cloud.delivery.manager;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderDTO;
import com.tmerclub.cloud.api.delivery.dto.DeliveryOrderItemDTO;
import com.tmerclub.cloud.api.platform.config.FeignShopConfig;
import com.tmerclub.cloud.common.bean.Quick100;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.util.Json;
import com.tmerclub.cloud.delivery.bo.DeliveryPrintDataInfoBO;
import com.tmerclub.cloud.delivery.bo.DeliveryPrintInfoBO;
import com.tmerclub.cloud.delivery.bo.DeliveryPrintInfoErrorBO;
import com.tmerclub.cloud.delivery.constant.DeliveryCompanyType;
import com.tmerclub.cloud.delivery.model.OutletConfig;
import com.tmerclub.cloud.delivery.model.Printer;
import com.tmerclub.cloud.delivery.service.OutletConfigService;
import com.tmerclub.cloud.delivery.service.PrinterService;
import com.tmerclub.cloud.order.model.OrderAddr;
import com.tmerclub.cloud.order.model.PurchaseOrderAddr;
import com.tmerclub.cloud.order.service.OrderAddrService;
import com.tmerclub.cloud.order.service.PurchaseOrderAddrService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

/**
 * 电子面单接口
 * API接口调用无测试环境，但下单后不揽收不会计算快递费，快递公司对单号有一定的回收机制，
 * 客户接口调试只需在订单内备注、寄件人或收件人等写明“测试”或“无需取件”字段。
 * @author TRACK
 */
@Component
public class DeliveryPrintManager {
    private static final Logger logger = LoggerFactory.getLogger(DeliveryPrintManager.class);
    private static final Integer MAX_CARGO_LENGTH = 20;

    @Autowired
    private OutletConfigService outletConfigService;
    @Autowired
    private PrinterService printerService;
    @Autowired
    private OrderAddrService orderAddrService;
    @Autowired
    private FeignShopConfig shopConfig;
    @Autowired
    private PurchaseOrderAddrService purchaseOrderAddrService;

    private static final String METHOD = "order";
    private static final int MAP_INIT = 3;
    public static final int SUCCESS_CODE = 200;

    public String deliveryPrint(DeliveryOrderDTO deliveryOrderDTO, Integer sysType, Integer isPurchase) {
        Quick100 quick100 = shopConfig.getQuick100();
        // 检查配置
        checkInfo(deliveryOrderDTO, quick100);
        // 网点配置
        OutletConfig outletConfig = outletConfigService.getByOutletConfig(deliveryOrderDTO.getOutletConfigId(), sysType);
        // 打印机配置
        Printer printer = printerService.getByPrinterId(deliveryOrderDTO.getPrinterId());
        // 快递公司配置
        DeliveryCompanyType deliveryCompanyType = DeliveryCompanyType.instance(outletConfig.getDeliveryCompanyType());
        if (Objects.isNull(deliveryCompanyType)) {
            throw new LuckException("网点关联快递公司配置为空");
        }
        // 收件人信息
        Map<String, Object> recManMap;
        if (Objects.equals(isPurchase, 1)) {
            recManMap = getManInfoMap(deliveryOrderDTO.getConsignee(), deliveryOrderDTO.getMobile(), false, null, sysType, deliveryOrderDTO.getOrderAddrId(), "");
        } else {
            recManMap = getManInfoMap(deliveryOrderDTO.getConsignee(), deliveryOrderDTO.getMobile(), false, deliveryOrderDTO.getOrderAddrId(), sysType, null, "");
        }
        // 寄件人信息
        Map<String, Object> sendManMap = getManInfoMap(outletConfig.getShipper(), outletConfig.getMobile(), true, null, sysType, null, outletConfig.getPrintAddr());
        // 电子面单下单信息
        Map<String, Object> orderReqMap = getOrderReqMap(deliveryOrderDTO, outletConfig, printer, deliveryCompanyType, recManMap, sendManMap, quick100);
        // 电子面单打印请求参数
        Map<String, Object> printReq = new HashMap<>(Constant.INITIAL_CAPACITY);
        printReq.put("method", METHOD);
        printReq.put("key", quick100.getKey());
        String param = JSON.toJSONString(orderReqMap);
        String t = String.valueOf(System.currentTimeMillis());
        String sign = new Digester(DigestAlgorithm.MD5).digestHex(param + t + quick100.getKey() + quick100.getSecret(), "UTF-8").toUpperCase(Locale.ROOT);
        printReq.put("sign", sign);
        printReq.put("t", t);
        printReq.put("param", param);
        String repJson = HttpUtil.post(quick100.getPrintReqUrl(), printReq);
        logger.info("电子面单请求返回：" + repJson);
        DeliveryPrintInfoBO deliveryPrintInfoBO = new DeliveryPrintInfoBO();
        // mock == true
        if (quick100.getMock()) {
            deliveryPrintInfoBO.setSuccess(true);
            deliveryPrintInfoBO.setCode(SUCCESS_CODE);
            DeliveryPrintDataInfoBO deliveryPrintDataInfoBO = new DeliveryPrintDataInfoBO();
            deliveryPrintDataInfoBO.setKuaidinum("666");
            deliveryPrintInfoBO.setData(deliveryPrintDataInfoBO);
        }else {
            deliveryPrintInfoBO = Json.parseObject(repJson, DeliveryPrintInfoBO.class);
        }

        if (Objects.isNull(deliveryPrintInfoBO)) {
            DeliveryPrintInfoErrorBO deliveryPrintInfoErrorBO = Json.parseObject(repJson, DeliveryPrintInfoErrorBO.class);
            if (Objects.isNull(deliveryPrintInfoErrorBO)) {
                throw new LuckException("电子面单请求错误，请检查配置是否正确");
            }
            throw new LuckException(deliveryPrintInfoErrorBO.getMessage());
        }
        if (!deliveryPrintInfoBO.getSuccess() || !Objects.equals(deliveryPrintInfoBO.getCode(), SUCCESS_CODE)) {
            throw new LuckException(deliveryPrintInfoBO.getMessage());
        }
        DeliveryPrintDataInfoBO deliveryPrintDataInfoBO = deliveryPrintInfoBO.getData();
        logger.info("电子面单：订单号{}--快递单号{}", deliveryOrderDTO.getOrderId(), deliveryPrintDataInfoBO.getKuaidinum());
        return deliveryPrintDataInfoBO.getKuaidinum();
    }

    private static void checkInfo(DeliveryOrderDTO deliveryOrderDTO, Quick100 quick100) {
        if (Objects.isNull(quick100) || StrUtil.isBlank(quick100.getKey()) || StrUtil.isBlank(quick100.getSecret())) {
            throw new LuckException("快递100配置为空或缺失");
        }
        if (!quick100.getIsPrint()) {
            throw new LuckException("平台未开启电子面单功能");
        }
        if (Objects.isNull(deliveryOrderDTO.getOutletConfigId())) {
            throw new LuckException("快递公司以及发货地址信息不能为空");
        }
        if (Objects.isNull(deliveryOrderDTO.getPrinterId())) {
            throw new LuckException("打印机信息不能为空");
        }
    }

    private static Map<String, Object> getOrderReqMap(DeliveryOrderDTO deliveryOrderDTO, OutletConfig outletConfig, Printer printer,
                                                      DeliveryCompanyType deliveryCompanyType, Map<String, Object> recManMap,
                                                      Map<String, Object> sendManMap, Quick100 quick100) {
        Map<String, Object> orderReqMap = new HashMap<>(Constant.INITIAL_CAPACITY);
        // 电子面单客户账户或月结账号
        orderReqMap.put("partnerId", outletConfig.getPartnerId());
        // 电子面单密码
        orderReqMap.put("partnerKey", outletConfig.getPartnerKey());
        // 电子面单密钥
        orderReqMap.put("net", outletConfig.getNet());
        // 电子面单承载编号
        orderReqMap.put("code", deliveryCompanyType.getCode());
        // 快递公司编码
        orderReqMap.put("kuaidicom", deliveryCompanyType.getKuaidicom());
        orderReqMap.put("recMan", recManMap);
        orderReqMap.put("sendMan", sendManMap);
        // 包裹总数量
        orderReqMap.put("count", 1);
        // 打印类型 默认云打印
        orderReqMap.put("printType", "CLOUD");
        StringBuilder sb = new StringBuilder(Constant.INITIAL_CAPACITY);
        for (DeliveryOrderItemDTO selectOrderItem : deliveryOrderDTO.getSelectOrderItems()) {
            sb.append(selectOrderItem.getSpuName()).append(StrUtil.COMMA);
        }
        sb.deleteCharAt(sb.length() - 1);
        String spuName = sb.toString();
        if (spuName.length() >= MAX_CARGO_LENGTH) {
            spuName = spuName.substring(0, 16) + "...";
        }
        // 物品名称
        orderReqMap.put("cargo", spuName);
        // 快递100模板id
        orderReqMap.put("tempId", DeliveryCompanyType.getTempId(outletConfig.getDeliveryCompanyType(), outletConfig.getPaperSize()));
        // 打印设备
        orderReqMap.put("siid", printer.getSiid());
        // 沙箱模式，不会提交到快递公司
        if (quick100.getMock()) {
            orderReqMap.put("mock", "kd100@Mock");
        }
        return orderReqMap;
    }

    private Map<String, Object> getManInfoMap(String name, String mobile, Boolean isShop, Long userAddrId, Integer sysType, Long purchaseOrderAddrId, String printAddr) {
        Map<String, Object> manInfoMap = new HashMap<>(MAP_INIT);
        // 姓名
        manInfoMap.put("name", name);
        // 手机号
        manInfoMap.put("mobile", mobile);
        // 所在完整地址
        if (Objects.nonNull(userAddrId)) {
            OrderAddr orderAddr = orderAddrService.getById(userAddrId);
            printAddr = orderAddr.getProvince() + orderAddr.getCity() + orderAddr.getArea() + orderAddr.getAddr();
        } else if (Objects.nonNull(purchaseOrderAddrId)) {
            PurchaseOrderAddr purchaseOrderAddr = purchaseOrderAddrService.getById(purchaseOrderAddrId);
            printAddr = purchaseOrderAddr.getProvince() + purchaseOrderAddr.getCity() + purchaseOrderAddr.getArea() + purchaseOrderAddr.getAddr();
        }
        manInfoMap.put("printAddr", printAddr);
        return manInfoMap;
    }
}
