package com.sckw.transport.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.core.model.constant.NumberConstant;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.*;
import com.sckw.core.utils.*;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.vo.RDriverVo;
import com.sckw.mongo.model.TableTops;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.SckwMessage;
import com.sckw.stream.model.UserInfo;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import com.sckw.transport.common.config.MessageUrlConfig;
import com.sckw.transport.dao.KwtLogisticsOrderContractMapper;
import com.sckw.transport.dao.KwtLogisticsOrderMapper;
import com.sckw.transport.dao.KwtWaybillOrderMapper;
import com.sckw.transport.dao.KwtWaybillOrderV1Mapper;
import com.sckw.transport.model.KwtLogisticsOrder;
import com.sckw.transport.model.KwtLogisticsOrderContract;
import com.sckw.transport.model.KwtLogisticsOrderUnit;
import com.sckw.transport.model.dto.AddOrderDTO;
import com.sckw.transport.model.vo.UserInfoVo;
import com.sckw.transport.model.vo.WaybillCountVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @desc 通用Service
 * @date 2023-07-06 13:07:43
 */
@Slf4j
@Service
public class KwtCommonService {

    @Autowired
    private StreamBridge streamBridge;

    @Autowired
    private MessageUrlConfig messageUrlConfig;

    @Value("${message.logistics.order.consignLogisticsOrderUrl}")
    private String consignLogisticsOrderUrl;

    @Value("${message.logistics.order.carriageLogisticsOrderUrl}")
    private String carriageLogisticsOrderUrl;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteContractService remoteContractService;

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    RemoteFleetService remoteFleetService;

    @Autowired
    private KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    private KwtLogisticsOrderContractMapper logisticsOrderContractMapper;

    @Autowired
    private KwtWaybillOrderV1Mapper kwtWaybillOrderV1Mapper;

    /**
     * 组装返回数据
     *
     * @param mappedResults 请求参数
     * @param arrayList     请求参数
     */
    public List<TableTops> packageReturnStatistics(List<com.sckw.mongo.model.TableTops> mappedResults, List<TableTops> arrayList) {
        List<String> codeList = LogisticsOrderEnum.getCodeStringList();
        List<String> collect = mappedResults.stream().map(e -> e.getValue()).collect(Collectors.toList());
        List<String> diffrentList = getDiffrentList(collect, codeList);
        if (CollectionUtils.isNotEmpty(mappedResults)) {
            if (CollectionUtils.isNotEmpty(diffrentList)) {
                for (String s : diffrentList) {
                    TableTops top = new TableTops();
                    top.setValue(s);
                    top.setTotal(NumberConstant.ZERO);
                    arrayList.add(top);
                }
            }
            for (TableTops top : arrayList) {
                top.setName(LogisticsOrderEnum.getName(Integer.valueOf(top.getValue())));
            }
        } else {
            for (LogisticsOrderEnum logisticsOrderEnum : LogisticsOrderEnum.values()) {
                TableTops top = new TableTops();
                top.setName(logisticsOrderEnum.getDestination());
                top.setValue(logisticsOrderEnum.getStatus());
                top.setTotal(NumberConstant.ZERO);
                arrayList.add(top);
            }
        }
        arrayList = arrayList.stream().sorted(Comparator.comparing(TableTops::getValue)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(arrayList)) {
            int total = 0;
            for (TableTops tops : arrayList) {
                if (LogisticsOrderEnum.REJECT_ORDER.getStatus().equals(tops.getValue())) {
                    total = total + tops.getTotal();
                }
                if (LogisticsOrderEnum.CANCEL_ORDER.getStatus().equals(tops.getValue())) {
                    total = total + tops.getTotal();
                }
            }
            for (TableTops tops : arrayList) {
                if (LogisticsOrderEnum.SEND_BACK.getStatus().equals(tops.getValue())) {
                    tops.setTotal(tops.getTotal() + total);
                }
            }
            Iterator iterator = arrayList.iterator();
            while (iterator.hasNext()) {
                TableTops tableTops = (TableTops) iterator.next();
                if (tableTops.getValue().equals(LogisticsOrderEnum.REJECT_ORDER.getStatus())) {
                    iterator.remove();
                }
                if (tableTops.getValue().equals(LogisticsOrderEnum.CANCEL_ORDER.getStatus())) {
                    iterator.remove();
                }
            }
            /**补全统计【全部字段】*/
            Integer sum = Math.toIntExact(arrayList.stream().filter(item -> ObjectUtil.isNotEmpty(item.getTotal())).collect(Collectors.summarizingInt(item -> item.getTotal())).getSum());
            TableTops top = new TableTops();
            top.setName("全部");
            top.setValue("all");
            top.setTotal(sum);
            arrayList.add(0, top);
        }
        return arrayList;
    }

    public List<String> getDiffrentList(List<String> sourceList, List<String> targetList) {
        return targetList.stream().filter(item -> sourceList.stream().allMatch(each -> !item.equals(each))).collect(Collectors.toList());
    }

    public Map<String, String> getDictData(String type) {
        Map<String, String> maps = new HashMap<>(NumberConstant.SIXTEEN);
        List<SysDictResDto> list = remoteSystemService.queryDictByType(type);
        if (CollectionUtils.isNotEmpty(list)) {
            maps = list.stream().collect(Collectors.toMap(SysDictResDto::getValue, SysDictResDto::getLabel, (key1, key2) -> key2));
        }
        return maps;
    }

    /**
     * 获取生成单据号最大值处理(处理redis宕机或者重启情况)
     */
    public void getRedisGenerateOrderNo() {
        Date date = new Date();
        String lockKey = String.format(RedisConstant.LOGISTICS_NO_GENERATE_KEY, DateUtils.formatDateToYYMMDD(date));
        try {
            String key = OrderGenerateSeqNoUtils.getKey(RedisOrderGenerateEnum.LOGISTICS_ORDER, OrderRuleEnum.LOGISTICS_ORDER, date);
            if (Boolean.FALSE.equals(RedissonUtils.exists(key))) {
                if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
                    throw new BusinessException("业务繁忙，请稍后再试！");
                }
                DateTime dateTime = DateUtils.beginOfDay(date);
                String maxOrderNo = logisticsOrderMapper.getMaxOrderNoByDate(dateTime);
                if (StringUtils.isNotBlank(maxOrderNo)) {
                    String substring = maxOrderNo.substring(0, 11);
                    Long maxNum = Long.valueOf(StringUtils.subStrFromIndexToEnd(substring, 4));
                    RedissonUtils.setAtomicLong(key, maxNum, DateUtils.getSecondsDay());
                }
            }
        } catch (Exception e) {
            log.error("物流订单获取生成单据号最大值处理异常：{}", e.getMessage(), e);
        } finally {
            RedissonUtils.unlock(lockKey);
        }
    }

    /**
     * 修改合同履约量
     *
     * @param loadAmount   装货量
     * @param unloadAmount 卸货量
     */
    public void updatePerformed(KwtLogisticsOrder logisticsOrder, BigDecimal loadAmount, BigDecimal unloadAmount) {
        /**
         * 更新合同履约量
         * 根据单据计费方式处理【目前只考虑 按照装货量 按照卸货量 】*/
        String billingMode = logisticsOrder.getBillingMode();
        BigDecimal actualAmount = NumberConstant.ZERO_TWO;
        if (DictEnum.CHARGING_TYPE_1.getValue().equals(billingMode)) {
            actualAmount = loadAmount;
        } else if (DictEnum.CHARGING_TYPE_2.getValue().equals(billingMode)) {
            actualAmount = unloadAmount;
        } else if (DictEnum.CHARGING_TYPE_3.getValue().equals(billingMode)) {
            /*// 物流订单运单趟次数量
            Map<String, Object> map = new HashMap<>(NumberConstant.SIXTEEN) {{
                put("upperlOrderId", logisticsOrder.getId());
                put("passStatus", Global.NUMERICAL_ONE);
            }};
            WaybillCountVo waybillOrderCount = kwtWaybillOrderV1Mapper.findWaybillOrderCount(map);
            actualAmount = waybillOrderCount == null ? NumberConstant.ZERO_TWO : new BigDecimal(waybillOrderCount.getTotalComplete());*/
            actualAmount = BigDecimal.valueOf(logisticsOrder.getTotalTake());
        } else if (DictEnum.CHARGING_TYPE_4.getValue().equals(billingMode)) {
            log.debug("“该方式不处理合同");
        } else {
            throw new BusinessException("单据计费方式错误!");
        }
        KwtLogisticsOrderContract contract = logisticsOrderContractMapper.selectOne(
                new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                        .eq(KwtLogisticsOrderContract::getLOrderId, logisticsOrder.getId()));
        remoteContractService.updatePerformed(contract.getContractId(), actualAmount);
    }

    /**
     * @desc 查询用户信息
     * @param userIds 企业用户ID+司机ID
     * @desc 查询用户信息
     * @author zk
     * @date 2023/9/7
     **/
    public List<UserInfoVo> findUserList(List<Long> userIds) {
        List<UserInfoVo> userList = new ArrayList<>();
        //用户数据集
        userIds = userIds.stream().distinct().collect(Collectors.toList());
        Map<Long, UserCacheResDto> users = remoteSystemService.queryUserCacheMapByIds(userIds);
        users.forEach((key, value) -> {
            UserInfoVo userInfo = new UserInfoVo();
            BeanUtils.copyProperties(value, userInfo);
            userList.add(userInfo);
        });

        Map<Long, RDriverVo> drivers = remoteFleetService.findDriver(userIds);
        drivers.forEach((key, value) -> {
            UserInfoVo userInfo = new UserInfoVo();
            BeanUtils.copyProperties(value, userInfo);
            userList.add(userInfo);
        });
        return userList;
    }


    public void importExcelToMessage(KwtLogisticsOrderUnit consignUnit, KwtLogisticsOrderUnit carriageUnit,
                                     String number, Long createBy, Long entId,
                                     String pcConsignUrl, String appConsignUrl,
                                     String pcCarriageUrl, String appCarriageUrl,
                                     MessageEnum consignMessageEnum,
                                     MessageEnum carriageMessageEnum,
                                     String type) {
        boolean flag = createBy.equals(consignUnit.getContactsId()) || createBy.equals(carriageUnit.getContactsId());
        Map<String, Object> map = new HashMap<>(NumberConstant.SIXTEEN);
        map.put("number", number);
        if (flag && createBy.equals(consignUnit.getContactsId())) {
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
        } else if (flag && createBy.equals(carriageUnit.getContactsId())) {
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
        } else {
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            if ("1".equals(type)) {
                map.put("companyName", consignUnit.getFirmName());
                sendLogisticsCreateByMessage(createBy, entId, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            } else {
                map.put("companyName", carriageUnit.getFirmName());
                sendLogisticsCreateByMessage(createBy, entId, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            }
        }
    }

    /**
     * 发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]
     *
     * @param consignUnit    托运单位
     * @param carriageUnit   承运单位
     * @param orderNo        单据号
     * @param createBy       创建人
     * @param entId          创建数据的企业id
     * @param pcConsignUrl   PC托运地址
     * @param appConsignUrl  app托运地址
     * @param pcCarriageUrl  PC承运地址
     * @param appCarriageUrl app承运地址
     * @param type           1代表给托运创建人发 2代表给承运创建人发
     */
    public void newSendLogisticsOrderToMessage(KwtLogisticsOrderUnit consignUnit, KwtLogisticsOrderUnit carriageUnit,
                                               String orderNo, Long createBy, Long entId,
                                               String pcConsignUrl, String appConsignUrl,
                                               String pcCarriageUrl, String appCarriageUrl,
                                               MessageEnum consignMessageEnum,
                                               MessageEnum carriageMessageEnum,
                                               String type) {
        boolean flag = createBy.equals(consignUnit.getContactsId()) || createBy.equals(carriageUnit.getContactsId());
        Map<String, Object> map = new HashMap<>(NumberConstant.SIXTEEN);
        map.put("orderNo", orderNo);
        if (flag && createBy.equals(consignUnit.getContactsId())) {
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
        } else if (flag && createBy.equals(carriageUnit.getContactsId())) {
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
        } else {
            sendLogisticsConsignMessage(consignUnit, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            sendLogisticsCarriageMessage(carriageUnit, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            if ("1".equals(type)) {
                map.put("companyName", consignUnit.getFirmName());
                sendLogisticsCreateByMessage(createBy, entId, map, pcConsignUrl, appConsignUrl, consignMessageEnum);
            } else {
                map.put("companyName", carriageUnit.getFirmName());
                sendLogisticsCreateByMessage(createBy, entId, map, pcCarriageUrl, appCarriageUrl, carriageMessageEnum);
            }
        }
    }

    /**
     * 发送消息
     *
     * @param createBy    创建人
     * @param entId       企业ID
     * @param map         消息内容
     * @param pcUrl       pc调整地址
     * @param appUrl      app调整地址
     * @param messageEnum 消息模板
     */
    public void sendLogisticsCreateByMessage(Long createBy, Long entId, Map<String, Object> map, String pcUrl, String appUrl, MessageEnum messageEnum) {
        UserCacheResDto userCacheResDto = remoteSystemService.queryUserCacheById(createBy);
        String name = remoteSystemService.queryUserCacheById(createBy).getName();
        //给订单创建人发消息
        List<UserInfo> userInfos = new ArrayList<>();
        UserInfo createUser = new UserInfo();
        createUser.setUserId(createBy).setEntId(entId);
        userInfos.add(createUser);
        SckwMessage msg = new SckwMessage();
        msg.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(messageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(NumberConstant.SIXTEEN) {
                    {
                        put("pc", pcUrl);
                        put("app", appUrl);
                    }
                })
                .setUserInfos(userInfos)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info("发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]-创建人：{}", JSON.toJSONString(msg));
        log.info("发起物流托运-企业:{},消息内容:{},-创建人：{},所有消息:{}", userCacheResDto.getEntInfo().getFirmName(), messageEnum.getContent(), name, JSON.toJSONString(msg));
        streamBridge.send("sckw-message", JSON.toJSONString(msg));
    }

    /**
     * 给业务联系人发消息[承运方]
     *
     * @param carriageUnit 承运单位
     * @param map          消息参数
     * @param pcUrl        pc端调整地址
     * @param appUrl       app调整地址
     * @param messageEnum  消息模板
     */
    public void sendLogisticsCarriageMessage(KwtLogisticsOrderUnit carriageUnit, Map<String, Object> map, String pcUrl, String appUrl, MessageEnum messageEnum) {
        //给业务联系人发消息[承运方]
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo userInfo = new UserInfo();
        UserCacheResDto userCacheResDto = remoteSystemService.queryUserCacheById(carriageUnit.getContactsId());
        userInfo.setUserId(carriageUnit.getContactsId()).setEntId(carriageUnit.getTopEntId());
        userInfoList.add(userInfo);
        map.put("companyName", carriageUnit.getFirmName());
        SckwMessage sckwMessage = new SckwMessage();
        sckwMessage.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(messageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", pcUrl);
                    put("app", appUrl);
                }})
                .setUserInfos(userInfoList)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info("发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]-[承运方]-业务联系人：{}", JSON.toJSONString(sckwMessage));
        log.info("[承运方]-companyName：{}-消息：{}", carriageUnit.getFirmName(), messageEnum.getContent());
        streamBridge.send("sckw-message", JSON.toJSONString(sckwMessage));
    }

    /**
     * 给业务联系人发消息[托运方]
     *
     * @param consignUnit 发货单位
     * @param map         消息参数
     * @param pcUrl       pc端调整地址
     * @param appUrl      app调整地址
     * @param messageEnum 消息模板
     */
    public void sendLogisticsConsignMessage(KwtLogisticsOrderUnit consignUnit, Map<String, Object> map, String pcUrl, String appUrl, MessageEnum messageEnum) {
        //给业务联系人发消息[托运方]
        List<UserInfo> list = new ArrayList<>();
        UserInfo userInfo = new UserInfo();
//        UserCacheResDto userCacheResDto = remoteSystemService.queryUserCacheById(consignUnit.getContactsId());
        userInfo.setUserId(consignUnit.getContactsId()).setEntId(consignUnit.getTopEntId());
        list.add(userInfo);
        map.put("companyName", consignUnit.getFirmName());
        SckwMessage message = new SckwMessage();
        message.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(messageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", pcUrl);
                    put("app", appUrl);
                }})
                .setUserInfos(list)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info("发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]-[托运方]-业务联系人：{}", JSON.toJSONString(message));
        log.info("[托运方]-companyName：{}-消息：{}", consignUnit.getFirmName(), messageEnum.getContent());
        streamBridge.send("sckw-message", JSON.toJSONString(message));
    }

    /**
     * 给承运和托运双方发送消息
     *
     * @param checkUnit    托运单位
     * @param carriageUnit 承运单位
     * @param map          消息参数
     */
    public void sendMessageLogistics(KwtLogisticsOrderUnit checkUnit, KwtLogisticsOrderUnit carriageUnit, Map map) {
        //给业务联系人发消息[承运方]
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(carriageUnit.getContactsId()).setEntId(carriageUnit.getTopEntId());
        userInfoList.add(userInfo);
        map.put("companyName", carriageUnit.getFirmName());
        SckwMessage sckwMessage = new SckwMessage();
        sckwMessage.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(MessageEnum.INITIATING_LOGISTICS_CONSIGNMENT)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("app", consignLogisticsOrderUrl);
                    put("pc", carriageLogisticsOrderUrl);
                }})
                .setUserInfos(userInfoList)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info("发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]-[承运方]-业务联系人：{}", JSON.toJSONString(sckwMessage));
        streamBridge.send("sckw-message", JSON.toJSONString(sckwMessage));

        //给业务联系人发消息[托运方]
        List<UserInfo> list = new ArrayList<>();
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setUserId(checkUnit.getContactsId()).setEntId(checkUnit.getTopEntId());
        list.add(userInfo);
        map.put("companyName", checkUnit.getFirmName());
        SckwMessage message = new SckwMessage();
        message.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(MessageEnum.NEW_CARRIAGE_ORDER)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("app", consignLogisticsOrderUrl);
                    put("pc", carriageLogisticsOrderUrl);
                }})
                .setUserInfos(list)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info("发起物流托运-[贸易订单物流托运确认/承运订单分包托运确认]-[托运方]-业务联系人：{}", JSON.toJSONString(message));
        streamBridge.send("sckw-message", JSON.toJSONString(message));
    }

    public void newLogisticsOrder(AddOrderDTO addOrderDTO, String lOrderNo, Long createBy, Long entId) {
        //发起方
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(Long.parseLong(addOrderDTO.getConsignCompanyId()));
        KwtLogisticsOrderUnit consignUnit = new KwtLogisticsOrderUnit();
        consignUnit.setUnitType(NumberConstant.ONE);
        consignUnit.setEntId(Long.parseLong(addOrderDTO.getConsignCompanyId()));
        consignUnit.setTopEntId(entCacheResDto == null ? null : entCacheResDto.getId());
        consignUnit.setFirmName(addOrderDTO.getAcceptCompany());
        consignUnit.setContactsId(Long.parseLong(addOrderDTO.getConsignContactsId()));

        //接收方
        EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntCacheById(Long.parseLong(addOrderDTO.getAcceptCompanyId()));
        KwtLogisticsOrderUnit carriageUnit = new KwtLogisticsOrderUnit();
        carriageUnit.setUnitType(NumberConstant.TWO);
        carriageUnit.setEntId(Long.parseLong(addOrderDTO.getAcceptCompanyId()));
        carriageUnit.setTopEntId(entCacheResDto1 == null ? null : entCacheResDto1.getId());
        carriageUnit.setFirmName(addOrderDTO.getConsignCompany());
        carriageUnit.setContactsId(Long.parseLong(addOrderDTO.getAcceptContactsId()));

        newSendLogisticsOrderToMessage(consignUnit, carriageUnit, lOrderNo, createBy, entId
                , messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl(), messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl(),
                messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl(), messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl(),
                MessageEnum.NEW_LOGISTICS_ORDER, MessageEnum.NEW_CARRIAGE_ORDER, "1"
        );

    }

    /**
     * 推送消息
     *
     * @param consignUnit        托运单位
     * @param carriageUnit       承运单位
     * @param map                消息参数
     * @param consignMessageEnum 消息模板
     */
    private void sendMessagePublicLogistics(KwtLogisticsOrderUnit consignUnit, KwtLogisticsOrderUnit carriageUnit, Map<String, Object> map, MessageEnum consignMessageEnum) {
        //给业务联系人发消息[承运方]
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(carriageUnit.getContactsId()).setEntId(carriageUnit.getTopEntId());
        userInfoList.add(userInfo);
        map.put("companyName", carriageUnit.getFirmName());
        SckwMessage sckwMessage = new SckwMessage();
        sckwMessage.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(consignMessageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", consignLogisticsOrderUrl);
                    put("app", carriageLogisticsOrderUrl);
                }})
                .setUserInfos(userInfoList)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info(MessageEnum.getDesc(consignMessageEnum) + "-[承运方]-业务联系人：{}", JSON.toJSONString(sckwMessage));
        streamBridge.send("sckw-message", JSON.toJSONString(sckwMessage));


        //给业务联系人发消息[托运方]
        List<UserInfo> list = new ArrayList<>();
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setUserId(consignUnit.getContactsId()).setEntId(consignUnit.getTopEntId());
        list.add(userInfo1);
        map.put("companyName", consignUnit.getFirmName());
        SckwMessage message = new SckwMessage();
        message.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(MessageEnum.NEW_CARRIAGE_ORDER)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", consignLogisticsOrderUrl);
                    put("app", carriageLogisticsOrderUrl);
                }})
                .setUserInfos(list)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info(MessageEnum.getDesc(consignMessageEnum) + "-[托运方]-业务联系人：{}", JSON.toJSONString(message));
        streamBridge.send("sckw-message", JSON.toJSONString(message));
    }


    /**
     * 推送消息
     *
     * @param consignUnit         托运单位
     * @param carriageUnit        承运单位
     * @param map                 参数
     * @param consignMessageEnum  托运枚举
     * @param carriageMessageEnum 承运枚
     */
    private void sendPushMessageByUrlLogistics(KwtLogisticsOrderUnit consignUnit, KwtLogisticsOrderUnit carriageUnit,
                                               Map<String, Object> map,
                                               MessageEnum consignMessageEnum,
                                               MessageEnum carriageMessageEnum) {
        //给业务联系人发消息[承运方]
        List<UserInfo> userInfoList = new ArrayList<>();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(carriageUnit.getContactsId()).setEntId(carriageUnit.getTopEntId());
        userInfoList.add(userInfo);
        map.put("companyName", carriageUnit.getFirmName());
        SckwMessage sckwMessage = new SckwMessage();
        sckwMessage.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(carriageMessageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", messageUrlConfig.getPc().getCarriageLogisticsAddOrderUrl());
                    put("app", messageUrlConfig.getApp().getCarriageLogisticsAddOrderUrl());
                }})
                .setUserInfos(userInfoList)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info(MessageEnum.getDesc(carriageMessageEnum) + "-[承运方]-业务联系人：{}", JSON.toJSONString(sckwMessage));
        streamBridge.send("sckw-message", JSON.toJSONString(sckwMessage));


        //给业务联系人发消息[托运方]
        List<UserInfo> list = new ArrayList<>();
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setUserId(consignUnit.getContactsId()).setEntId(consignUnit.getTopEntId());
        list.add(userInfo1);
        map.put("companyName", consignUnit.getFirmName());
        SckwMessage message = new SckwMessage();
        message.setRequestId(UUIDUtils.get32UUID())
                .setMessageEnum(consignMessageEnum)
                .setParams(map)
                .setMsgUrls(new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
                    put("pc", messageUrlConfig.getPc().getConsignLogisticsAddOrderUrl());
                    put("app", messageUrlConfig.getApp().getConsignLogisticsAddOrderUrl());
                }})
                .setUserInfos(list)
                .setCreateBy(LoginUserHolder.getUserId());
        log.info(MessageEnum.getDesc(consignMessageEnum) + "-[托运方]-业务联系人：{}", JSON.toJSONString(message));
        streamBridge.send("sckw-message", JSON.toJSONString(message));
    }

    /**
     * 验证当前物流订单是否存在未完结的车辆运单
     *
     * @param id 对应物流订单id
     */
    public boolean judgmentWaybillOrderIsFinish(String id) {
        boolean flag = false;
        List<Integer> statusList = new ArrayList<>();
//        statusList.add(CarWaybillEnum.PENDING_ORDER.getCode());
        statusList.add(CarWaybillEnum.PENDING_VEHICLE.getCode());
        statusList.add(CarWaybillEnum.EXIT_COMPLETED.getCode());
        statusList.add(CarWaybillEnum.WAIT_LOADING.getCode());
        statusList.add(CarWaybillEnum.COMPLETION_LOADING.getCode());
        statusList.add(CarWaybillEnum.WAIT_UNLOADING.getCode());
        statusList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        statusList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        statusList.add(CarWaybillEnum.APPROVAL_NO_PASS.getCode());
//        statusList.add(CarWaybillEnum.APPROVAL_PASS.getCode());
        int count = kwtWaybillOrderV1Mapper.selectDataByLorderId(id, statusList);
        if (count > NumberConstant.ZERO) {
            flag = true;
        }
        return flag;
    }

    /**
     * @param loadAmount    装货量
     * @param deficitAmount 亏吨量
     * @param loss          合理损耗
     * @desc 计算扣亏量
     **/
    public BigDecimal deficitAmount(BigDecimal loadAmount, BigDecimal deficitAmount, BigDecimal entrustAmount, BigDecimal loss, String lossUnit) {
        //亏吨<=0
        if (deficitAmount.compareTo(new BigDecimal(Global.AMOUNT)) <= 0) {
            return new BigDecimal(Global.AMOUNT);
        }
        //合理损耗
        loss = loss == null ? new BigDecimal(Global.AMOUNT) : loss;
        if (loss.doubleValue() > 0 && StringUtils.isNotBlank(lossUnit)) {
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.PERCENT.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.PERCENT.getValue()));
            }
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.MILLIMETER.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.MILLIMETER.getValue()));
            }
        }
        /**
         * 一、罚款值计算：
         * 1、合理损耗值=实装量*合理损耗（‰）
         * 1.1 亏吨量= 实装量-实卸量
         * 2、扣亏量=亏吨量-合理损耗值【要求大于0，如果小于0则扣亏货量取0】
         * 3、罚款值=扣亏量 * 扣亏货值
         *
         * 二、运价计算：
         * 1、按装货量：总运价=实装量*运价
         * 2、按卸货量：总运价=实卸量*运价-罚款值
         * 3、按趟次：总运价=运价*趟次【后期加】
         */
        loadAmount = loadAmount == null ? new BigDecimal(Global.AMOUNT) : loadAmount;
        //已委托量
        entrustAmount = entrustAmount == null ? new BigDecimal(Global.AMOUNT) : entrustAmount;
        //合理损耗值
        BigDecimal multiply = loadAmount.multiply(loss.divide(BigDecimal.valueOf(1000L)));
        //亏吨量
        deficitAmount = deficitAmount == null ? new BigDecimal(Global.AMOUNT) : deficitAmount;
        //扣亏量/吨
        deficitAmount = deficitAmount.compareTo(new BigDecimal(Global.AMOUNT)) == 0 ? new BigDecimal(Global.AMOUNT) : deficitAmount.subtract(multiply);
        return deficitAmount;
    }

    /**
     * @param loadAmount    装货量
     * @param deficitAmount 亏吨量
     * @param loss          合理损耗
     * @desc 计算扣亏量
     * @author zk
     * @date 2023/7/27
     **/
    public BigDecimal deficitLossAmount(BigDecimal loadAmount, BigDecimal deficitAmount, BigDecimal loss, String lossUnit) {
        //亏吨<=0
//        if (deficitAmount.compareTo(new BigDecimal(Global.AMOUNT)) <= 0) {
//            return new BigDecimal(Global.AMOUNT);
//        }
//        //承运订单亏吨扣款=（承运订单亏吨量 -（承运订单装货量 * 承运订单合理损耗））* 扣亏货值
//        loss = loss == null ? new BigDecimal(Global.AMOUNT) : loss;
//        if (loss.doubleValue() > 0 && StringUtils.isNotBlank(lossUnit)) {
//            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.PERCENT.getCode()))) {
//                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.PERCENT.getValue()));
//            }
//            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.MILLIMETER.getCode()))) {
//                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.MILLIMETER.getValue()));
//            }
//        }
//        //扣亏量
//        BigDecimal deficitPrice = deficitAmount.subtract(loadAmount.multiply(loss).setScale(4, RoundingMode.HALF_UP));
//        return deficitPrice;

        if (StringUtils.isBlank(lossUnit)) {
            lossUnit = String.valueOf(NumberConstant.ZERO);
        }
        //亏吨<=0
        if (deficitAmount.compareTo(new BigDecimal(Global.AMOUNT)) <= 0) {
            return new BigDecimal(Global.AMOUNT);
        }
        //承运订单亏吨扣款=（承运订单亏吨量 -（承运订单装货量 * 承运订单合理损耗））* 扣亏货值
        loss = loss == null ? new BigDecimal(Global.AMOUNT) : loss;
        if (loss.doubleValue() > 0 && StringUtils.isNotBlank(lossUnit)) {
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.PERCENT.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.PERCENT.getValue()));
            }
            if (lossUnit.equals(String.valueOf(TaxRateTypeEnum.MILLIMETER.getCode()))) {
                loss = loss.divide(new BigDecimal(TaxRateTypeEnum.MILLIMETER.getValue()));
            }
        }
        //扣亏量=亏吨量【合理损耗占比为空或为0】
        if (loss.doubleValue() == Global.NUMERICAL_ZERO) {
            return deficitAmount;
        }
        //扣亏量=亏吨量-合理损耗值【要求大于0，如果小于0则扣亏货量取0】
        BigDecimal deficitLossAmount = deficitAmount.subtract(loadAmount.multiply(loss).setScale(2, RoundingMode.HALF_UP));
        if (deficitLossAmount.doubleValue() <= 0) {
            return new BigDecimal(Global.AMOUNT);
        }
        return deficitLossAmount;
    }
}
