package com.sckw.transport.dubbo;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.model.enums.LogisticsOrderEnum;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwLogisticsOrder;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.OrderDetailRes;
import com.sckw.order.api.model.UnitInfoDetailRes;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.redis.utils.RedissonUtils;
import com.sckw.stream.model.SckwBusSum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.transport.api.dubbo.TransportService;
import com.sckw.transport.api.model.dto.AccountCheckingBindDTO;
import com.sckw.transport.api.model.dto.AddressResDTO;
import com.sckw.transport.api.model.dto.LogisticsOrderDTO;
import com.sckw.transport.api.model.dto.RWaybillOrderDto;
import com.sckw.transport.api.model.param.ContractSignLogisticsParam;
import com.sckw.transport.api.model.param.LogisticsOrderParam;
import com.sckw.transport.api.model.vo.KwtLogisticsOrderVO;
import com.sckw.transport.api.model.vo.RTruckMonitorVo;
import com.sckw.transport.api.model.vo.RWaybillOrderVo;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.*;
import com.sckw.transport.service.CommonService;
import jakarta.annotation.Resource;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author lfdc
 * @description 运输服务dubbo接口
 * @date 2023-07-11 14:07:28
 */
@Slf4j
@Service
@DubboService(group = "design", version = "1.0.0", timeout = 50000)
public class TransportServiceImpl implements TransportService {

    @Autowired
    public CommonService commonService;

    @Resource
    private StreamBridge streamBridge;

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

    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
    private TradeOrderInfoService tradeOrderInfoService;

    @Autowired
    private KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    private KwtLogisticsOrderUnitMapper logisticsOrderUnitMapper;

    @Autowired
    private KwtLogisticsOrderAddressMapper logisticsOrderAddressMapper;

    @Autowired
    private KwtLogisticsOrderContractMapper logisticsOrderContractMapper;

    @Autowired
    private KwtLogisticsOrderTrackMapper logisticsOrderTrackMapper;

    @Autowired
    private KwtLogisticsOrderGoodsMapper logisticsOrderGoodsMapper;

    @Autowired
    private KwtWaybillOrderMapper waybillOrderDao;

    @Autowired
    private KwtWaybillOrderTrackMapper waybillOrderTrackDao;

    /**
     * 对账管理-ids查询
     *
     * @param ids
     * @return
     */
    @Override
    public List<KwtLogisticsOrderVO> getAcceptCarriageOrderDetail(List<String> ids) {
        List<KwtLogisticsOrderVO> list = new ArrayList<>();
        List<KwtLogisticsOrder> kwtLogisticsOrders = logisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>().in(KwtLogisticsOrder::getId, ids));
        if (CollectionUtils.isNotEmpty(kwtLogisticsOrders)) {
            for (KwtLogisticsOrder kwtLogisticsOrder : kwtLogisticsOrders) {
                KwtLogisticsOrderVO vo = new KwtLogisticsOrderVO();
                BeanUtils.copyProperties(kwtLogisticsOrder, vo);
                list.add(vo);
            }
        }
        return list;
    }

    /**
     * 对账页面数据接口
     *
     * @param ids
     * @return
     */
    @Override
    public List<LogisticsOrderDTO> getAcceptCarriageOrderList(List<String> ids) {
        List<LogisticsOrderDTO> list = logisticsOrderMapper.selectLogisticOrderList(ids, LogisticsOrderEnum.HAVE_FINISHED.getCode());
        /**计量单位*/
        Map<String, String> unitTypeDictData = getDictData(DictTypeEnum.UNIT_TYPE.getType());
        /**运价方式*/
        Map<String, String> priceDictData = getDictData(DictTypeEnum.PRICE_TYPE.getType());
        /**计费方式*/
        Map<String, String> chargingDictData = getDictData(DictTypeEnum.CHARGING_TYPE.getType());
        /**结算周期*/
        Map<String, String> settlementDictData = getDictData(DictTypeEnum.SETTLEMENT_CYCLE.getType());
        /**合理损耗*/
        Map<String, String> taxRateTypeDictData = getDictData(DictTypeEnum.TAX_RATE_TYPE.getType());
        if (CollectionUtils.isNotEmpty(list)) {
            for (LogisticsOrderDTO logisticsOrderDTO : list) {
                String tOrderId = logisticsOrderDTO.getTOrderId();
                if (StringUtils.isNotBlank(tOrderId)) {
                    try {
                        OrderDetailRes orderDetailById = tradeOrderInfoService.getOrderDetailById(Long.parseLong(tOrderId));
                        if (orderDetailById != null) {
                            List<UnitInfoDetailRes> unitInfo = orderDetailById.getUnitInfo();
                            if (CollectionUtils.isNotEmpty(unitInfo)) {
                                for (UnitInfoDetailRes detailRes : unitInfo) {
                                    if ("1".equals(detailRes.getUnitType())) {
                                        logisticsOrderDTO.setConsignee(detailRes.getFirmName());
                                    }
                                    if ("2".equals(detailRes.getUnitType())) {
                                        logisticsOrderDTO.setForwardingUnit(detailRes.getFirmName());
                                    }
                                }
                            }
                        }
                    } catch (NumberFormatException e) {
                        System.out.println("查询不到贸易订单数据,id" + tOrderId);
                    }
                }

                KwtLogisticsOrderUnit consignOrderUnit = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.ONE));
                KwtLogisticsOrderUnit carrierOrderUnit = logisticsOrderUnitMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                        .eq(KwtLogisticsOrderUnit::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderUnit::getUnitType, NumberConstant.TWO));
                KwtLogisticsOrderAddress loadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                        .eq(KwtLogisticsOrderAddress::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE)
                );
                KwtLogisticsOrderAddress unloadOrderAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                        .eq(KwtLogisticsOrderAddress::getLOrderId, logisticsOrderDTO.getLOrderId())
                        .eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO)
                );
                KwtLogisticsOrderContract contract = logisticsOrderContractMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                        .eq(KwtLogisticsOrderContract::getLOrderId, logisticsOrderDTO.getLOrderId())
                );

                KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                        .eq(KwtLogisticsOrderGoods::getLOrderId, logisticsOrderDTO.getLOrderId())
                );
                logisticsOrderDTO.setGoodsName(orderGoods == null ? null : orderGoods.getGoodsName());
                String billingMode = logisticsOrderDTO.getBillingMode();

                /**
                 * 一、罚款值计算：
                 * 1、合理损耗值=实装量*合理损耗（‰）
                 *  1.1 亏吨量= 实装量-实卸量
                 * 2、扣亏量=亏吨量-合理损耗值【要求大于0，如果小于0则扣亏货量取0】
                 * 3、罚款值=扣亏量 * 扣亏货值
                 *
                 * 二、运价计算：
                 * 1、按装货量：总运价=实装量*运价-罚款值
                 * 2、按卸货量：总运价=实卸量*运价-罚款值
                 * 3、按趟次：总运价=运价*趟次【后期加】
                 */
                //运价
                BigDecimal price = logisticsOrderDTO.getPrice() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getPrice();


                /**亏吨量/吨->装货量-卸货量
                 扣亏量/吨->亏吨量-合理损耗值
                 扣亏量/吨->亏吨量-合理损耗值(装货量*合理损耗)*/
                BigDecimal loadAmount = logisticsOrderDTO.getTotalLoadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalLoadAmount();
                BigDecimal unloadAmount = logisticsOrderDTO.getTotalUnloadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalUnloadAmount();

                BigDecimal loss = logisticsOrderDTO.getLoss() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getLoss();
                //亏吨量
                BigDecimal defectiveWeighNumber = loadAmount.subtract(unloadAmount);
                //合理损耗值
                BigDecimal lossAmount = loadAmount.multiply(logisticsOrderDTO.getLoss() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getLoss());
                //扣亏量
//                BigDecimal deductWeighNumber = defectiveWeighNumber.subtract(lossAmount);
                BigDecimal deductWeighNumber = commonService.deficitLossAmount(loadAmount, defectiveWeighNumber, loss, logisticsOrderDTO.getLossUnit());
                if (deductWeighNumber.compareTo(new BigDecimal("0")) < 0) {
                    deductWeighNumber = new BigDecimal("0.00");
                }
                //罚款值
                BigDecimal fineValue = (logisticsOrderDTO.getGoodsPrice() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getGoodsPrice()).multiply(deductWeighNumber);
                /**
                 *
                 * 二、运价计算：
                 * 1、按装货量：总运价=实装量*运价-罚款值
                 * 2、按卸货量：总运价=实卸量*运价-罚款值
                 * 3、按趟次：总运价=运价*趟次【后期加】
                 */
                //todo 2023-10-10 含税金额不减去罚款值 另指定罚款值进行返回数据
                BigDecimal actualAmount = new BigDecimal("0.00");
                if (DictEnum.CHARGING_TYPE_1.getValue().equals(billingMode)) {
                    actualAmount = (logisticsOrderDTO.getTotalLoadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalLoadAmount()).multiply(price);
//                    actualAmount = (logisticsOrderDTO.getTotalLoadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalLoadAmount()).multiply(price).subtract(fineValue);
                } else if (DictEnum.CHARGING_TYPE_2.getValue().equals(billingMode)) {
                    actualAmount = (logisticsOrderDTO.getTotalUnloadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalUnloadAmount()).multiply(price);
//                    actualAmount = (logisticsOrderDTO.getTotalUnloadAmount() == null ? new BigDecimal("0.00") : logisticsOrderDTO.getTotalUnloadAmount()).multiply(price).subtract(fineValue);
                }
                logisticsOrderDTO.setDeductPrice(fineValue);
                logisticsOrderDTO.setTaxMoney(actualAmount);
//                logisticsOrderDTO.setContractId();
                logisticsOrderDTO.setContractName(contract.getContractName());
                logisticsOrderDTO.setContractNo(contract.getContractNo());
                logisticsOrderDTO.setGoodsPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                logisticsOrderDTO.setCreateByName(remoteSystemService.queryUserCacheById(logisticsOrderDTO.getCreateBy()) == null ? null : remoteSystemService.queryUserCacheById(logisticsOrderDTO.getCreateBy()).getName());
                logisticsOrderDTO.setLoadAddress(loadOrderAddress.getDetailAddress());
                logisticsOrderDTO.setLoadName(loadOrderAddress.getName());
                logisticsOrderDTO.setLoadContacts(loadOrderAddress.getContacts());
                logisticsOrderDTO.setLoadPhone(loadOrderAddress.getPhone());
                logisticsOrderDTO.setUnloadAddress(unloadOrderAddress.getDetailAddress());
                logisticsOrderDTO.setUnloadName(unloadOrderAddress.getName());
                logisticsOrderDTO.setUnloadContacts(unloadOrderAddress.getContacts());
                logisticsOrderDTO.setUnloadPhone(unloadOrderAddress.getPhone());
                logisticsOrderDTO.setCarrierCompany(carrierOrderUnit == null ? null : carrierOrderUnit.getFirmName());
                logisticsOrderDTO.setCarrierPhone(carrierOrderUnit == null ? null : carrierOrderUnit.getPhone());
                logisticsOrderDTO.setCarrierContacts(carrierOrderUnit == null ? null : carrierOrderUnit.getContacts());
                logisticsOrderDTO.setConsignCompany(consignOrderUnit == null ? null : consignOrderUnit.getFirmName());
                logisticsOrderDTO.setConsignPhone(consignOrderUnit == null ? null : consignOrderUnit.getPhone());
                logisticsOrderDTO.setConsignContacts(consignOrderUnit == null ? null : consignOrderUnit.getContacts());
                logisticsOrderDTO.setSettlementCycleLabel(logisticsOrderDTO.getSettlementCycle() == null ? null : settlementDictData.get(logisticsOrderDTO.getSettlementCycle().toString()));
                logisticsOrderDTO.setBillingModeLabel(chargingDictData.get(logisticsOrderDTO.getBillingMode()));
                logisticsOrderDTO.setPriceLabel(priceDictData.get(logisticsOrderDTO.getPriceType()));
                logisticsOrderDTO.setLossUnitLabel(taxRateTypeDictData.get(logisticsOrderDTO.getLossUnit()));
                logisticsOrderDTO.setAmountLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                logisticsOrderDTO.setIgnoreAmountLabel(unitTypeDictData.get(logisticsOrderDTO.getUnit()));
                logisticsOrderDTO.setLoadAmount(logisticsOrderDTO.getTotalLoadAmount());
                logisticsOrderDTO.setUnloadAmount(logisticsOrderDTO.getTotalUnloadAmount());
//                logisticsOrderDTO.setCount(waybillOrderMapper.selectCount(new LambdaQueryWrapper<KwtWaybillOrder>().eq(KwtWaybillOrder::getLOrderId, logisticsOrderDTO.getLOrderId())));
            }
        }
        return list;
    }

    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;
    }

    /**
     * 获取当前企业下物流订单地址信息
     *
     * @return
     */
    @Override
    public List<Integer> getLogisticsOrderAddressList() {
        return logisticsOrderMapper.getAddressList(LoginUserHolder.getEntId());
    }

    /**
     * 根据企业id 获取物流订单相关地址信息
     *
     * @param entId 企业id
     * @return
     */
    @Override
    public List<AddressResDTO> getLogisticsOrderAddressListByEntId(Long entId) {
        return null;
    }

    /**
     * 贸易订单验证物流订单是否已完成
     *
     * @param tOrderId 贸易订单id
     * @return false 无操作中的物流订单  ture 存在操作中的物流订单
     */
    @Override
    public boolean checkLogisticsOrderByTradeOrderId(Long tOrderId) {
        boolean flag = false;
        List<Integer> statusList = new ArrayList<>();
        statusList.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        statusList.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        statusList.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        statusList.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        List<KwtLogisticsOrder> logisticsOrders = logisticsOrderMapper.selectList(
                new LambdaQueryWrapper<KwtLogisticsOrder>()
                        .eq(KwtLogisticsOrder::getTOrderId, tOrderId)
                        .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
                        .in(KwtLogisticsOrder::getStatus, statusList)
        );
        if (!org.springframework.util.CollectionUtils.isEmpty(logisticsOrders)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 对账修改物流订单信息
     *
     * @param logisticsOrderParam 请求物流订单数据
     * @return
     */
    @Override
    public HttpResult checkLogisticsOrderStatusById(LogisticsOrderParam logisticsOrderParam) {
        HttpResult httpResult = new HttpResult();
        log.info("对账修改物流订单参数:{}", JSONObject.toJSONString(logisticsOrderParam));
        Long lOrderId = logisticsOrderParam.getLOrderId();
        String status = logisticsOrderParam.getStatus();
        if (lOrderId == null) {
            httpResult.setMsg("物流订单不能为空!");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }

        LambdaQueryWrapper<KwtLogisticsOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwtLogisticsOrder::getId, lOrderId);
        wrapper.eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO);
        KwtLogisticsOrder kwtLogisticsOrder = logisticsOrderMapper.selectOne(wrapper);
        if (kwtLogisticsOrder == null) {
            httpResult.setMsg("物流订单不存在!");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }

        if (LogisticsOrderEnum.HAVE_RECONCILED.getStatus().equals(status)) {
            if (!LogisticsOrderEnum.HAVE_FINISHED.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus()))) {
                httpResult.setMsg("物流单据状态有误,不能修改");
                httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
                return httpResult;
            }
        } else if (LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getStatus().equals(status)) {
            if (!LogisticsOrderEnum.HAVE_RECONCILED.getStatus().equals(String.valueOf(kwtLogisticsOrder.getStatus()))) {
                httpResult.setMsg("物流单据状态有误,不能修改");
                httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
                return httpResult;
            }
        } else {
            httpResult.setMsg("物流单据状态有误");
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return httpResult;
        }
        //修改单据状态
        kwtLogisticsOrder.setStatus(Integer.valueOf(status));
        kwtLogisticsOrder.setUpdateTime(new Date());
        kwtLogisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
        logisticsOrderMapper.updateById(kwtLogisticsOrder);
        //修改mongodb状态
        SckwLogisticsOrder order = new SckwLogisticsOrder();
        order.set_id(kwtLogisticsOrder.getId());
        order.setLOrderId(kwtLogisticsOrder.getId());
        order.setStatus(status);
        order.setUpdateTime(new Date());
        order.setUpdateByName(LoginUserHolder.getUserName());
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
        busSum.setMethod(NumberConstant.TWO);
        busSum.setObject(order);
        streamBridge.send("sckw-busSum", com.alibaba.fastjson2.JSON.toJSONString(busSum));
        return HttpResult.ok();
    }

    /**
     * 根据企业id 获取物流订单相关地址信息
     *
     * @param entIds 企业id集合
     * @return
     */
    @Override
    public Map<Long, List<AddressResDTO>> getLogisticsOrderAddressListByEntId(List<Long> entIds) {
        Map<Long, List<AddressResDTO>> map = new HashMap<>(entIds.size());
        for (Long entId : entIds) {
            List<AddressResDTO> list = logisticsOrderMapper.getAddressDetailListByEntId(entId);
            if (Objects.nonNull(list)) {
                map.put(entId, list);
            }
        }
        return map;
    }

    /**
     * 运费对账是否进行对账绑定数据
     * accountCheckingBindDTO
     *
     * @return
     */
    @Override
//    @GlobalLock
    @Transactional
    public HttpResult logisticsOrderAccountCheckingBind(AccountCheckingBindDTO accountCheckingBindDTO) {
        log.info("物流订单对账,推送是否绑定,请求数据:{}", JSONObject.toJSONString(accountCheckingBindDTO));
        if (org.springframework.util.CollectionUtils.isEmpty(accountCheckingBindDTO.getLOrderList())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "物流订单不能为空!");
        }
        if (StringUtils.isBlank(accountCheckingBindDTO.getStatus())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "绑定状态不能为空");
        }
        if (!String.valueOf(NumberConstant.ZERO).equals(accountCheckingBindDTO.getStatus()) &&
                !String.valueOf(NumberConstant.ONE).equals(accountCheckingBindDTO.getStatus())) {
            return HttpResult.error(HttpStatus.GLOBAL_EXCEPTION_CODE, "绑定状态类型错误!");
        }
        accountCheckingBindDTO.getLOrderList().forEach(id -> {
            logisticsOrderMapper.update(null,
                    new LambdaUpdateWrapper<KwtLogisticsOrder>()
                            .eq(KwtLogisticsOrder::getId, id)
                            .set(KwtLogisticsOrder::getBindStatus, accountCheckingBindDTO.getStatus())
                            .set(KwtLogisticsOrder::getUpdateBy, accountCheckingBindDTO.getUpdateBy())
                            .set(KwtLogisticsOrder::getUpdateTime, new Date()));
            //修改mongodb数据
            SckwLogisticsOrder order = new SckwLogisticsOrder();
            order.set_id(id);
            order.setLOrderId(id);
            order.setBindStatus(accountCheckingBindDTO.getStatus());
            order.setUpdateTime(new Date());
            order.setUpdateByName(accountCheckingBindDTO.getUpdateName());
            SckwBusSum busSum = new SckwBusSum();
            busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
            busSum.setMethod(NumberConstant.TWO);
            busSum.setObject(order);
            streamBridge.send("sckw-busSum", com.alibaba.fastjson2.JSON.toJSONString(busSum));
        });
        return HttpResult.ok();
    }

    /**
     * 根据企业id查询是否存在有未完结的物流订单
     *
     * @param entId 企业id
     * @return ture 代表还有未完结的  false代表没有未完结的
     */
    @Override
    public boolean checkLogisticsOrderFinishByEntId(Long entId) {
        List<KwtLogisticsOrderUnit> logisticsOrderUnits = logisticsOrderUnitMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderUnit>()
                .eq(KwtLogisticsOrderUnit::getTopEntId, entId)
        );
        if (CollectionUtils.isEmpty(logisticsOrderUnits)) {
            return false;
        }
        List<Integer> orderStatus = new ArrayList<>();
        orderStatus.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        orderStatus.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        orderStatus.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderStatus.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
        List<Long> collect = logisticsOrderUnits.stream().map(KwtLogisticsOrderUnit::getLOrderId).distinct().collect(Collectors.toList());
        Long count = logisticsOrderMapper.selectCount(new LambdaQueryWrapper<KwtLogisticsOrder>()
                .in(KwtLogisticsOrder::getId, collect)
                .in(KwtLogisticsOrder::getStatus, orderStatus)
                .eq(KwtLogisticsOrder::getDelFlag, NumberConstant.ZERO)
        );
        if (count > 0) {
            return true;
        }
        return false;
    }

    /**
     * @param consignEntId        托运企业id
     * @param acceptCarriageEntId 承运企业id
     * @return
     */
    @Override
    public HttpResult checkLogisticsOrderIsFinishByEntId(Long consignEntId, Long acceptCarriageEntId) {
        if (Objects.isNull(consignEntId) || Objects.isNull(acceptCarriageEntId)) {
            throw new BusinessException("企业id不能为空");
        }
        List<Integer> orderStatus = new ArrayList<>();
        orderStatus.add(LogisticsOrderEnum.TO_BE_PLANNED.getCode());
        orderStatus.add(LogisticsOrderEnum.PENDING_ORDER.getCode());
        orderStatus.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderStatus.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderStatus.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
//        orderStatus.add(LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode());
        List<String> logisticsNo = logisticsOrderMapper.checkLogisticsOrderIsFinishByEntId(consignEntId, acceptCarriageEntId, orderStatus);
        if (CollectionUtils.isNotEmpty(logisticsNo)) {
            return HttpResult.error("", logisticsNo);
        } else {
            return HttpResult.ok();
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void contractSignLogisticsCompleted(ContractSignLogisticsParam param) {
        if (Objects.isNull(param.getUpdateBy()) || StringUtils.isBlank(param.getUpdateByName())) {
            throw new BusinessException("操作人信息不能为空!");
        }
        Long contractId = param.getContractId();
        Long updateBy = param.getUpdateBy();

        String lockKey = String.format(RedisConstant.LOGISTICS_ORDER_CONTRACT_UPDATE_KEY, param.getContractId());
        if (Boolean.FALSE.equals(RedissonUtils.tryLock(lockKey, 5L, 10L))) {
            throw new BusinessException("业务繁忙，请稍后再试!");
        }
        try {
            List<KwtLogisticsOrderContract> contracts = logisticsOrderContractMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderContract>()
                    .eq(KwtLogisticsOrderContract::getContractId, contractId)
                    .eq(KwtLogisticsOrderContract::getDelFlag, NumberConstant.ZERO)
            );
            if (CollectionUtils.isEmpty(contracts)) {
                log.info("合同：{}无相关联待签约的物流订单", contractId);
                return;
            }
            List<Long> orderIds = contracts.stream().map(KwtLogisticsOrderContract::getLOrderId).distinct().collect(Collectors.toList());
            List<KwtLogisticsOrder> orders = logisticsOrderMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrder>()
                    .in(KwtLogisticsOrder::getId, orderIds)
                    .eq(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.TO_BE_PLANNED.getCode())
            );
            if (CollectionUtils.isEmpty(orders)) {
                log.info("合同：{}无相关联待签约的物流订单", contractId);
                return;
            }
            List<SckwLogisticsOrder> logisticsOrders = Lists.newArrayList();
            List<Long> ids = orders.stream().map(KwtLogisticsOrder::getId).toList();
            /**改变物流订单状态*/
            for (Long id : ids) {
                logisticsOrderMapper.update(null, new LambdaUpdateWrapper<KwtLogisticsOrder>()
                        .set(KwtLogisticsOrder::getUpdateBy, updateBy)
                        .set(KwtLogisticsOrder::getUpdateTime, new Date())
                        .set(KwtLogisticsOrder::getStatus, LogisticsOrderEnum.PENDING_ORDER.getCode())
                        .eq(KwtLogisticsOrder::getId, id)
                );
                SckwLogisticsOrder logisticsOrder = new SckwLogisticsOrder();
                logisticsOrder.set_id(id);
                logisticsOrder.setLOrderId(id);
                logisticsOrder.setStatus(LogisticsOrderEnum.PENDING_ORDER.getStatus());
                logisticsOrder.setUpdateBy(updateBy);
                logisticsOrder.setUpdateByName(param.getUpdateByName());
                logisticsOrders.add(logisticsOrder);
            }
            /**增加状态表数据*/
            orders.forEach(e -> {
                KwtLogisticsOrderTrack orderTrack = logisticsOrderTrackMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderTrack>()
                        .eq(KwtLogisticsOrderTrack::getLOrderId, e.getId())
                        .eq(KwtLogisticsOrderTrack::getStatus, LogisticsOrderEnum.PENDING_ORDER.getCode())
                );
                if (orderTrack == null) {
                    KwtLogisticsOrderTrack track = new KwtLogisticsOrderTrack();
                    track.setId(new IdWorker(NumberConstant.ONE).nextId());
                    track.setLOrderId(e.getId());
                    track.setStatus(LogisticsOrderEnum.PENDING_ORDER.getCode());
                    track.setCreateBy(updateBy);
                    track.setCreateTime(new Date());
                    track.setUpdateBy(updateBy);
                    track.setUpdateTime(new Date());
                    track.setDelFlag(NumberConstant.ZERO);
                    logisticsOrderTrackMapper.insert(track);
                } else {
                    orderTrack.setUpdateBy(updateBy);
                    orderTrack.setUpdateTime(new Date());
                    logisticsOrderTrackMapper.updateById(orderTrack);
                }
            });
            /** mongodb保存*/
            for (SckwLogisticsOrder logisticsOrder : logisticsOrders) {
                SckwBusSum busSum = new SckwBusSum();
                busSum.setBusSumType(BusinessTypeEnum.LOGISTICS_ORDER_TYPE.getName());
                busSum.setMethod(NumberConstant.TWO);
                busSum.setObject(logisticsOrder);
                streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
            }
        } finally {
            RedissonUtils.unlock(lockKey);
        }
    }

    /**
     * @param params 参数
     * @desc 查询车辆运单
     * @author zk
     * @date 2023/9/6
     **/
    @Override
    public List<RWaybillOrderVo> findWaybillOrder(RWaybillOrderDto params) {
        List<RWaybillOrderVo> waybillOrderVos = new ArrayList<>();
        Map<String, Object> queryParams = new HashMap<>(Global.NUMERICAL_SIXTEEN) {{
            put("truckNo", params.getTruckNo());
            put("busStatus", params.getBusStatus());
        }};
        List<KwtWaybillOrder> waybillOrders = waybillOrderDao.findWaybillOrder(queryParams);
        if (CollectionUtils.isEmpty(waybillOrders)) {
            return waybillOrderVos;
        }

        for (KwtWaybillOrder waybillOrder : waybillOrders) {
            RWaybillOrderVo order = new RWaybillOrderVo();
            BeanUtils.copyProperties(waybillOrder, order);
            KwtWaybillOrderTrack track = waybillOrderTrackDao.findWaybillOrderTrack(waybillOrder.getId(), CarWaybillEnum.EXIT_COMPLETED.getCode());
            order.setDepartureTime(track != null ? track.getOperateTime() : null);
            waybillOrderVos.add(order);
        }

        return waybillOrderVos;
    }

    /**
     * @param checkEntId 托运企业ID
     * @desc 查询托运方关联任务中的车辆
     * @author zk
     * @date 2023/10/8
     **/
    @Override
    public List<RTruckMonitorVo> truckInTask(Long checkEntId) {
        //查询物流订单
        List<Long> orderIds = new ArrayList<>();
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN){{
            put("status", LogisticsOrderEnum.IN_TRANSIT.getCode());
            put("checkEntId", checkEntId);
        }};
        List<KwtLogisticsOrder> orders = logisticsOrderMapper.findLogisticsOrder(params);
        if (!CollectionUtils.isEmpty(orders)) {
            List<Long> idList = new ArrayList<>();
            orders.forEach(order -> idList.add(order.getId()));
            orderIds.addAll(idList);
            findLogisticsOrderChild(orderIds, StringUtil.join(idList, Global.COMMA));
        }

        //查询运单
        List<RTruckMonitorVo> trucks = new ArrayList<>();
        params = new HashMap<>(Global.NUMERICAL_SIXTEEN){{
            put("busStatus", Global.NUMERICAL_THREE);
            put("lOrderIds", orderIds);
        }};
        List<KwtWaybillOrder> waybillOrders = waybillOrderDao.findWaybillOrder(params);
        waybillOrders.forEach(order -> trucks.add(new RTruckMonitorVo(order.getEntId(), order.getTruckNo(), Global.NUMERICAL_ONE)));
        return trucks;
    }

    /**
     * @param orderIds 物流订单ID集合
     * @param ids 当前物流订单ID
     * @desc 查询下级分包 物流订单
     * @author zk
     * @date 2023/10/8
     **/
    public void findLogisticsOrderChild(List<Long> orderIds, String ids) {
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN){{
            put("status", LogisticsOrderEnum.IN_TRANSIT.getCode());
            put("pid", ids);
        }};
        //查询物流订单
        List<KwtLogisticsOrder> orders = logisticsOrderMapper.findLogisticsOrder(params);
        if (!CollectionUtils.isEmpty(orders)) {
            List<Long> idList = new ArrayList<>();
            orders.forEach(order -> idList.add(order.getId()));
            orderIds.addAll(idList);
            findLogisticsOrderChild(orderIds, StringUtil.join(idList, Global.COMMA));
        }
    }
}
