package com.sckw.payment.service;

import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.common.enums.NumberConstant;
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.OrderRuleEnum;
import com.sckw.core.model.enums.RedisOrderGenerateEnum;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.model.vo.TableTop;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.utils.OrderGenerateSeqNoUtils;
import com.sckw.core.utils.StringTimeUtil;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.payment.dao.KwpLedgerLogisticsMapper;
import com.sckw.payment.model.*;
import com.sckw.payment.model.constant.LedgerEnum;
import com.sckw.payment.model.constant.LogisticsUnitType;
import com.sckw.payment.model.constant.SettlementEnum;
import com.sckw.payment.model.dto.*;
import com.sckw.payment.model.vo.req.*;
import com.sckw.payment.model.vo.res.LedgerCountSumVo;
import com.sckw.payment.model.vo.res.LedgerLogisticsDetailVo;
import com.sckw.stream.enums.MessageEnum;
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.api.dubbo.TransportService;
import com.sckw.transport.api.model.dto.AccountCheckingBindDTO;
import com.sckw.transport.api.model.dto.LogisticsOrderDTO;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xucaiqin
 * @date 2023-07-10 16:38:36
 */
@Service
@Slf4j
public class KwpLedgerLogisticsService extends AbsLedger {
    @Resource
    private KwpLedgerLogisticsTrackService logisticsTrackService;
    @Resource
    private KwpSettlementLogisticsService kwpSettlementLogisticsService;
    @Resource
    private KwpLedgerLogisticsUnitService logisticsUnitService;
    @Resource
    private KwpLedgerLogisticsOrderService logisticsOrderService;
    @Resource
    private MessageSender messageSender;

    @Resource
    private KwpLedgerLogisticsMapper logisticsMapper;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false)
    private TransportService transportDubboService;

    private void changeDict(List<? extends ILedger> list) {
        List<SysDictResDto> taxRateDict = remoteSystemService.queryDictByType(DictTypeEnum.TAX_RATE.getType());
        Map<String, String> taxRateMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        Map<String, String> tradingMap = new HashMap<>(Global.NUMERICAL_SIXTEEN);

        if (!CollectionUtils.isEmpty(taxRateDict)) {
            taxRateMap = taxRateDict.stream().collect(Collectors.toMap(SysDictResDto::getValue, SysDictResDto::getLabel, (a, b) -> a));
        }
        List<SysDictResDto> tradingDict = remoteSystemService.queryDictByType(DictTypeEnum.TRADE_TYPE.getType());
        if (!CollectionUtils.isEmpty(tradingDict)) {
            tradingMap = tradingDict.stream().collect(Collectors.toMap(SysDictResDto::getValue, SysDictResDto::getLabel, (a, b) -> a));
        }
        for (ILedger logisticsDto : list) {
            String trading = logisticsDto.getTrading();
            logisticsDto.setTradingLabel(tradingMap.get(trading));
            Integer taxRate = logisticsDto.getTaxRate();
            logisticsDto.setTaxRateLabel(taxRateMap.get(String.valueOf(taxRate)));

            logisticsDto.setStatusLabel(LedgerEnum.getDesc(logisticsDto.getStatus()));

            UserCacheResDto userCacheResDto = remoteSystemService.queryUserCacheById(logisticsDto.getCreateBy());
            if (Objects.nonNull(userCacheResDto)) {
                logisticsDto.setCreateByName(userCacheResDto.getName());
            }
        }
    }

    private void fillPara(LogisticsReq logisticsReq) {
        logisticsReq.setEntId(LoginUserHolder.getEntId());
        if (StringUtils.isNotBlank(logisticsReq.getStartCreateTime())) {
            logisticsReq.setStartCreateTime(StringTimeUtil.fillStart(logisticsReq.getStartCreateTime()));
        }
        if (StringUtils.isNotBlank(logisticsReq.getEndCreateTime())) {
            logisticsReq.setEndCreateTime(StringTimeUtil.fillEnd(logisticsReq.getEndCreateTime()));
        }
    }

    /**
     * 托运方物流对账单列表查询
     *
     * @param logisticsReq
     * @return 托运方对账订单分页数据
     */
    public PageRes<ILedger> shipperList(LogisticsReq logisticsReq) {
        fillPara(logisticsReq);
        logisticsReq.setUnitType(LogisticsUnitType.CARRIER);
        logisticsReq.setUnitTypeTwo(LogisticsUnitType.SHIPPER);
        PageHelper.startPage(logisticsReq.getPage(), logisticsReq.getPageSize());
        List<LedgerShipperDto> kwpLedgerLogisticsList = logisticsMapper.shipperSelect(logisticsReq, LoginUserHolder.getAuthUserIdList());
        PageInfo<ILedger> ledgerShipperDtoPageInfo = new PageInfo<>(kwpLedgerLogisticsList);
        //字典转换
        if (!CollectionUtils.isEmpty(kwpLedgerLogisticsList)) {
            changeDict(ledgerShipperDtoPageInfo.getList());
            return new PageRes<>(ledgerShipperDtoPageInfo);
        }
        return new PageRes<>(ledgerShipperDtoPageInfo);
    }

    /**
     * 托运方 统计物流对账单
     *
     * @param logisticsReq
     * @return
     */
    public LedgerCountSumVo shipperSum(LogisticsReq logisticsReq) {
        fillPara(logisticsReq);
        logisticsReq.setUnitType(LogisticsUnitType.CARRIER);
        logisticsReq.setUnitTypeTwo(LogisticsUnitType.SHIPPER);
        List<Integer> status = new ArrayList<>() {{
            add(LedgerEnum.SAVE.getStatus());
            add(LedgerEnum.REVOCATION.getStatus());
        }};
        Long aLong = logisticsMapper.countSum(logisticsReq, status);
        BigDecimal bigDecimal = logisticsMapper.countSumMoney(logisticsReq, status);
        return new LedgerCountSumVo(bigDecimal, aLong);
    }

    public PageRes<ILedger> carrierList(LogisticsReq logisticsReq) {
        fillPara(logisticsReq);
        logisticsReq.setUnitType(LogisticsUnitType.SHIPPER);
        logisticsReq.setUnitTypeTwo(LogisticsUnitType.CARRIER);
        PageHelper.startPage(logisticsReq.getPage(), logisticsReq.getPageSize());
        List<Long> authUserIdList = LoginUserHolder.getAuthUserIdList();
        List<LedgerCarrierDto> kwpLedgerLogisticsList = logisticsMapper.carrierSelect(logisticsReq, authUserIdList);
        PageInfo<ILedger> ledgerShipperDtoPageInfo = new PageInfo<>(kwpLedgerLogisticsList);
        //字典转换
        if (!CollectionUtils.isEmpty(kwpLedgerLogisticsList)) {
            changeDict(ledgerShipperDtoPageInfo.getList());
            return new PageRes<>(ledgerShipperDtoPageInfo);
        }
        return new PageRes<>();
    }

    public LedgerCountSumVo carrierSumCount(LogisticsReq logisticsReq) {
        fillPara(logisticsReq);
        logisticsReq.setUnitType(LogisticsUnitType.SHIPPER);
        logisticsReq.setUnitTypeTwo(LogisticsUnitType.CARRIER);
        List<Integer> status = new ArrayList<>();
        Long aLong = logisticsMapper.countSum(logisticsReq, status);
        BigDecimal bigDecimal = logisticsMapper.countSumMoney(logisticsReq, status);
        return new LedgerCountSumVo(bigDecimal, aLong);
    }

    /**
     * 保存物流对账单
     *
     * @param logisticsReq
     * @return
     */
    @GlobalTransactional(name = "default_tx_group", rollbackFor = Exception.class)
    public String sendLedger(LogisticsSendReq logisticsReq) {
        log.info("保存物流对账单：{}", JSONObject.toJSONString(logisticsReq));
        if (Objects.nonNull(logisticsReq.getIdLong())) {
            removeDraft(logisticsReq.getIdLong());
        }
        logisticsReq.setGenerateTime(LocalDateTime.now());
        logisticsReq.setStatus(LedgerEnum.TO_LEDGER.getStatus());
        IdNo idNo = saveDraft(logisticsReq);
        logisticsTrackService.saveTrack(idNo.id(), Global.EMPTY_STRING, LedgerEnum.TO_LEDGER);

        //托运方
        KwpLedgerLogisticsUnit logisticsUnit = logisticsUnitService.queryCustomerEnt(idNo.id(), LogisticsUnitType.SHIPPER);
        //承运方
        KwpLedgerLogisticsUnit logisticsUnit2 = logisticsUnitService.queryCustomerEnt(idNo.id(), LogisticsUnitType.CARRIER);
        //推送创建人
        messageSender.sendCreate(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", idNo.no());
            put("name", logisticsReq.getName());
        }}, new UserInfo().setUserId(LoginUserHolder.getUserId()).setEntId(LoginUserHolder.getEntId()), MessageEnum.LEDGER_CARRIER);
        //推送系统管理员
        messageSender.sendManager(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", idNo.no());
            put("name", logisticsReq.getName());
        }}, logisticsUnit.getEntId(), MessageEnum.LEDGER_SHIPPER);

        return "保存对账单成功";
    }

    /**
     * 删除物流对账单相关联的其它数据
     *
     * @param id 物流对账单id
     */
    public void removeDraft(Long id) {
        //删除 kwp_ledger_logistics_order
        logisticsOrderService.remove(id);
        //删除 kwp_ledger_logistics_track
        logisticsTrackService.remove(id);
        //删除 kwp_ledger_logistics_unit
        logisticsUnitService.remove(id);
    }

    /**
     * 物流对账单保存草稿
     *
     * @param logisticsSendReq 物流对账单新增参数
     * @return
     */
    public IdNo saveDraft(LogisticsSendReq logisticsSendReq) {
        KwpLedgerLogistics kwpLedgerLogistics = new KwpLedgerLogistics();
        kwpLedgerLogistics.setId(Objects.isNull(logisticsSendReq.getIdLong()) ? new IdWorker(1).nextId() : logisticsSendReq.getIdLong());
        kwpLedgerLogistics.setEntId(LoginUserHolder.getEntId());
        kwpLedgerLogistics.setName(logisticsSendReq.getName());
        if (StringUtils.isNotBlank(logisticsSendReq.getStartTime())) {
            kwpLedgerLogistics.setStartTime(StringTimeUtil.startDateTime(logisticsSendReq.getStartTime()));
        }
        if (StringUtils.isNotBlank(logisticsSendReq.getEndTime())) {
            kwpLedgerLogistics.setEndTime(StringTimeUtil.endDateTime(logisticsSendReq.getEndTime()));
        }
        kwpLedgerLogistics.setTaxRate(logisticsSendReq.getTaxRate());
        kwpLedgerLogistics.setTrading(logisticsSendReq.getTrading());
        kwpLedgerLogistics.setTotalPrice(logisticsSendReq.getTotalPrice());
        //todo-xcq 不含税金额计算方式：订单含税金额总和/1.13(税率)
        kwpLedgerLogistics.setExTaxPrice(logisticsSendReq.getTotalPrice());
        kwpLedgerLogistics.setSettlePrice(logisticsSendReq.getSettlePrice());
        kwpLedgerLogistics.setActualPrice(new BigDecimal("0.0"));
        kwpLedgerLogistics.setDeductPrice(logisticsSendReq.getDeductPrice());
        kwpLedgerLogistics.setAuditUser(Global.EMPTY_STRING);
        kwpLedgerLogistics.setAuditPhone(Global.EMPTY_STRING);
        kwpLedgerLogistics.setReceiptTime(null);
        kwpLedgerLogistics.setOrderCount(logisticsSendReq.getIdList().size());
        kwpLedgerLogistics.setUrl(Global.EMPTY_STRING);
        kwpLedgerLogistics.setGenerateTime(logisticsSendReq.getGenerateTime());
        kwpLedgerLogistics.setRemark(logisticsSendReq.getRemark());
        kwpLedgerLogistics.setStatus(logisticsSendReq.getStatus());
        kwpLedgerLogistics.setDelFlag(Global.UN_DELETED);
        //id为空，新增对账单
        if (Objects.isNull(logisticsSendReq.getIdLong())) {
            kwpLedgerLogistics.setCreateBy(LoginUserHolder.getUserId());
            kwpLedgerLogistics.setCreateTime(LocalDateTime.now());
            kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
            kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
            kwpLedgerLogistics.setLLedgerNo(OrderGenerateSeqNoUtils.getOtherSeqNo(RedisOrderGenerateEnum.LEDGER_CHECKING, OrderRuleEnum.LEDGER_LOGISTICS_ORDER));
            logisticsMapper.insert(kwpLedgerLogistics);
        } else {
            //校验是否可以修改对账单
            KwpLedgerLogistics ledgerLogistics = logisticsMapper.selectById(logisticsSendReq.getIdLong());
            orderCheck(ledgerLogistics);
            updateCheck(ledgerLogistics.getStatus());
            //修改对账单
            kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
            kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
            logisticsMapper.updateById(kwpLedgerLogistics);
        }
        /*保存物流订单关联数据*/
        List<Long> ids = logisticsSendReq.getIdList();
        //验当前订单是否已存在绑定的对账单
        logisticsOrderService.check(ids);
        List<LogisticsOrderDTO> acceptCarriageOrderDetail = transportDubboService.getAcceptCarriageOrderList(logisticsSendReq.getIdsList());
        if (CollectionUtils.isEmpty(acceptCarriageOrderDetail) || acceptCarriageOrderDetail.size() < ids.size()) {
            throw new BusinessException("未找到物流订单!");
        }
        //更新物流订单状态为已绑定
        AccountCheckingBindDTO accountCheckingBindDTO = new AccountCheckingBindDTO();
        accountCheckingBindDTO.setLOrderList(ids);
        accountCheckingBindDTO.setStatus("1");
        accountCheckingBindDTO.setUpdateBy(LoginUserHolder.getUserId());
        accountCheckingBindDTO.setUpdateName(LoginUserHolder.getUserName());
        HttpResult httpResult = transportDubboService.logisticsOrderAccountCheckingBind(accountCheckingBindDTO);
        if (httpResult.getCode() != 60200) {
            throw new BusinessException(httpResult.getMsg());
        }

        List<KwpLedgerLogisticsOrder> collect = acceptCarriageOrderDetail.stream().map(a -> {
            KwpLedgerLogisticsOrder logisticsOrder = new KwpLedgerLogisticsOrder();
            logisticsOrder.setId(new IdWorker(NumberConstant.ONE).nextId());
            logisticsOrder.setLLedgerId(kwpLedgerLogistics.getId());
            logisticsOrder.setLOrderId(Long.parseLong(a.getLOrderId()));
            logisticsOrder.setLOrderNo(a.getLOrderNO());
            logisticsOrder.setRemark(Global.EMPTY_STRING);
            logisticsOrder.setStatus(NumberConstant.ZERO);
            logisticsOrder.setCreateBy(LoginUserHolder.getUserId());
            logisticsOrder.setCreateTime(LocalDateTime.now());
            logisticsOrder.setUpdateBy(LoginUserHolder.getUserId());
            logisticsOrder.setUpdateTime(LocalDateTime.now());
            logisticsOrder.setDelFlag(Global.UN_DELETED);
            return logisticsOrder;
        }).collect(Collectors.toList());

        logisticsOrderService.saveList(collect);
        /*保存企业相关信息*/
        Long checkEntId = Long.parseLong(logisticsSendReq.getCheckEntId());

        Map<Long, EntCacheResDto> entMap = remoteSystemService.queryEntTreeByIds(Collections.singletonList(checkEntId));
        EntCacheResDto entCacheResDto = entMap.get(checkEntId);
        if (Objects.isNull(entCacheResDto)) {
            entCacheResDto = new EntCacheResDto();
        }

        List<KwpLedgerLogisticsUnit> logisticsUnits = new ArrayList<>();
        KwpLedgerLogisticsUnit kwpLedgerLogisticsUnit = new KwpLedgerLogisticsUnit();
        kwpLedgerLogisticsUnit.setId(new IdWorker(NumberConstant.ONE).nextId());
        kwpLedgerLogisticsUnit.setLLedgerId(kwpLedgerLogistics.getId());
        kwpLedgerLogisticsUnit.setLLedgerNo(kwpLedgerLogistics.getLLedgerNo());
        kwpLedgerLogisticsUnit.setUnitType(LogisticsUnitType.SHIPPER);
        kwpLedgerLogisticsUnit.setEntId(checkEntId);
        kwpLedgerLogisticsUnit.setTopEntId(entCacheResDto.getId());
        kwpLedgerLogisticsUnit.setFirmName(entCacheResDto.getFirmName());
        kwpLedgerLogisticsUnit.setContacts(entCacheResDto.getContacts());
        kwpLedgerLogisticsUnit.setContactsId(entCacheResDto.getContactsId());
        kwpLedgerLogisticsUnit.setPhone(entCacheResDto.getPhone());
        kwpLedgerLogisticsUnit.setRemark(Global.EMPTY_STRING);
        kwpLedgerLogisticsUnit.setStatus(NumberConstant.ZERO);
        kwpLedgerLogisticsUnit.setCreateBy(LoginUserHolder.getUserId());
        kwpLedgerLogisticsUnit.setCreateTime(LocalDateTime.now());
        kwpLedgerLogisticsUnit.setUpdateBy(LoginUserHolder.getUserId());
        kwpLedgerLogisticsUnit.setUpdateTime(LocalDateTime.now());
        kwpLedgerLogisticsUnit.setDelFlag(Global.UN_DELETED);

        logisticsUnits.add(kwpLedgerLogisticsUnit);
        Long entId = LoginUserHolder.getEntId();
        Map<Long, EntCacheResDto> entCarrierMap = remoteSystemService.queryEntTreeByIds(Collections.singletonList(entId));
        EntCacheResDto entCacheResDto1 = entCarrierMap.get(entId);
        if (Objects.isNull(entCacheResDto1)) {
            entCacheResDto1 = new EntCacheResDto();
        }
        KwpLedgerLogisticsUnit carrierUnit = new KwpLedgerLogisticsUnit();
        carrierUnit.setId(new IdWorker(NumberConstant.ONE).nextId());
        carrierUnit.setLLedgerId(kwpLedgerLogistics.getId());
        carrierUnit.setLLedgerNo(kwpLedgerLogistics.getLLedgerNo());
        carrierUnit.setUnitType(LogisticsUnitType.CARRIER);
        //顶级企业id
        carrierUnit.setEntId(entId);
        //顶级企业id
        carrierUnit.setTopEntId(entCacheResDto1.getId());
        carrierUnit.setFirmName(entCacheResDto1.getFirmName());
        carrierUnit.setContacts(entCacheResDto1.getContacts());
        carrierUnit.setContactsId(entCacheResDto1.getContactsId());
        carrierUnit.setPhone(entCacheResDto1.getPhone());
        carrierUnit.setRemark(Global.EMPTY_STRING);
        carrierUnit.setStatus(NumberConstant.ZERO);
        carrierUnit.setCreateBy(LoginUserHolder.getUserId());
        carrierUnit.setCreateTime(LocalDateTime.now());
        carrierUnit.setUpdateBy(LoginUserHolder.getUserId());
        carrierUnit.setUpdateTime(LocalDateTime.now());
        carrierUnit.setDelFlag(Global.UN_DELETED);

        logisticsUnits.add(carrierUnit);
        logisticsUnitService.saveList(logisticsUnits);
        return new IdNo(kwpLedgerLogistics.getId(), kwpLedgerLogistics.getLLedgerNo());
    }

    /**
     * 保存物流对账单草稿
     *
     * @param logisticsReq 物流对账单保存的参数
     * @return
     */
    @GlobalTransactional(name = "default_tx_group", rollbackFor = Exception.class)
    public String sendLedgerDraft(LogisticsSendReq logisticsReq) {
        log.info("物流对账单草稿：{}", JSONObject.toJSONString(logisticsReq));
        logisticsReq.setGenerateTime(null);
        logisticsReq.setStatus(LedgerEnum.SAVE.getStatus());
        IdNo aLong = saveDraft(logisticsReq);
        logisticsTrackService.saveTrack(aLong.id(), Global.EMPTY_STRING, LedgerEnum.SAVE);
        return "草稿保存成功";
    }

    /**
     * 删除物流对账单
     *
     * @param id 物流对账单id
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    public String remove(Long id) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(id);
        if (Objects.isNull(kwpLedgerLogistics)) {
            throw new BusinessException("对账单不存在!");
        }
        deleteCheck(kwpLedgerLogistics.getStatus());
        kwpLedgerLogistics.setDelFlag(Global.DELETED);
        logisticsMapper.updateById(kwpLedgerLogistics);
        List<KwpLedgerLogisticsOrder> kwpLedgerLogisticsOrders = logisticsOrderService.queryList(id);
        //更新物流订单状态为已解绑
        AccountCheckingBindDTO accountCheckingBindDTO = new AccountCheckingBindDTO();
        accountCheckingBindDTO.setLOrderList(kwpLedgerLogisticsOrders.stream().map(KwpLedgerLogisticsOrder::getLOrderId).collect(Collectors.toList()));
        accountCheckingBindDTO.setStatus("0");
        accountCheckingBindDTO.setUpdateBy(LoginUserHolder.getUserId());
        accountCheckingBindDTO.setUpdateName(LoginUserHolder.getUserName());
        HttpResult httpResult = transportDubboService.logisticsOrderAccountCheckingBind(accountCheckingBindDTO);
        if (httpResult.getCode() != 60200) {
            throw new BusinessException(httpResult.getMsg());
        }
        logisticsOrderService.remove(id);
        return "删除成功";
    }

    /**
     * 撤回物流对账单
     *
     * @param id 物流对账单id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String backOrder(Long id) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(id);
        if (Objects.isNull(kwpLedgerLogistics)) {
            throw new BusinessException("对账单不存在!");
        }
        revokeCheck(kwpLedgerLogistics.getStatus());

        kwpLedgerLogistics.setStatus(LedgerEnum.REVOCATION.getStatus());
        kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
        kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
        logisticsMapper.updateById(kwpLedgerLogistics);
        logisticsTrackService.saveTrack(id, Global.EMPTY_STRING, LedgerEnum.REVOCATION);

        //托运方
        KwpLedgerLogisticsUnit logisticsUnit = logisticsUnitService.queryCustomerEnt(id, LogisticsUnitType.SHIPPER);
        //承运方
        KwpLedgerLogisticsUnit logisticsUnit2 = logisticsUnitService.queryCustomerEnt(id, LogisticsUnitType.CARRIER);
        //推送创建人
        messageSender.sendCreate(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, new UserInfo().setUserId(LoginUserHolder.getUserId()).setEntId(LoginUserHolder.getEntId()), MessageEnum.LEDGER_REVOCATION_CARRIER);
        //推送系统管理员
        messageSender.sendManager(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, logisticsUnit.getEntId(), MessageEnum.LEDGER_REVOCATION_SHIPPER);
        return "撤回成功";
    }

    /**
     * 查询物流对账单驳回记录
     *
     * @param id 物流对账单id
     * @return 物流对账单驳回记录
     */
    public KwpLedgerLogisticsTrack queryBack(Long id) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(id);
        orderCheck(kwpLedgerLogistics);
        backQueryCheck(kwpLedgerLogistics.getStatus());
        return logisticsTrackService.selectOne(id, LedgerEnum.BACK);
    }

    /**
     * 驳回物流对账单
     *
     * @param ledgerReq 驳回参数
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String doBack(LedgerReq ledgerReq) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(ledgerReq.getIdLong());
        if (Objects.isNull(kwpLedgerLogistics)) {
            throw new BusinessException("对账单不存在!");
        }
        backCheck(kwpLedgerLogistics.getStatus());
        kwpLedgerLogistics.setStatus(LedgerEnum.BACK.getStatus());
        kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
        kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
        logisticsMapper.updateById(kwpLedgerLogistics);
        logisticsTrackService.saveTrack(ledgerReq.getIdLong(), ledgerReq.getRemark(), LedgerEnum.BACK);


        //托运方
        KwpLedgerLogisticsUnit logisticsUnit = logisticsUnitService.queryCustomerEnt(ledgerReq.getIdLong(), LogisticsUnitType.SHIPPER);
        //承运方
        KwpLedgerLogisticsUnit logisticsUnit2 = logisticsUnitService.queryCustomerEnt(ledgerReq.getIdLong(), LogisticsUnitType.CARRIER);
        //推送创建人
        messageSender.sendCreate(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, new UserInfo().setUserId(LoginUserHolder.getUserId()).setEntId(LoginUserHolder.getEntId()), MessageEnum.LEDGER_BACK_CARRIER);
        //推送系统管理员和变更人
        messageSender.sendPurchaseBoth(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, ledgerReq.getIdLong(), logisticsUnit.getEntId(), MessageEnum.LEDGER_BACK_SHIPPER);
        return "驳回成功";
    }

    /**
     * 对账确认
     * 订单变更为已对账
     *
     * @param confirmReq 对账确认请求参数
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String confirmOrder(LedgerConfirmReq confirmReq) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(confirmReq.getIdLong());
        orderCheck(kwpLedgerLogistics);
        confirmCheck(kwpLedgerLogistics.getStatus());
        kwpLedgerLogistics.setStatus(LedgerEnum.LEDGERED.getStatus());
        kwpLedgerLogistics.setAuditPhone(confirmReq.getAuditPhone());
        kwpLedgerLogistics.setAuditUser(confirmReq.getAuditUser());
        kwpLedgerLogistics.setAuditUserId(confirmReq.getAuditUserId());
        kwpLedgerLogistics.setUrl(confirmReq.getUrl());
        kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
        kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
        logisticsMapper.updateById(kwpLedgerLogistics);
        logisticsTrackService.saveTrack(confirmReq.getIdLong(), Global.EMPTY_STRING, LedgerEnum.LEDGERED);


        //托运方
        KwpLedgerLogisticsUnit logisticsUnit = logisticsUnitService.queryCustomerEnt(confirmReq.getIdLong(), LogisticsUnitType.SHIPPER);
        //承运方
        KwpLedgerLogisticsUnit logisticsUnit2 = logisticsUnitService.queryCustomerEnt(confirmReq.getIdLong(), LogisticsUnitType.CARRIER);
        //推送创建人
        messageSender.sendCreate(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, new UserInfo().setUserId(LoginUserHolder.getUserId()).setEntId(LoginUserHolder.getEntId()), MessageEnum.LEDGER_CONFIRM_SHIPPER);
        //推送系统管理员和变更人
        messageSender.sendPurchaseBoth(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, confirmReq.getIdLong(), logisticsUnit.getEntId(), MessageEnum.LEDGER_CONFIRM_SHIPPER);
        return "对账确认成功";
    }

    /**
     * 对账完成
     *
     * @param ledgerReq 对账完成参数
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String orderSuccess(LedgerSuccessReq ledgerReq) {
        KwpLedgerLogistics kwpLedgerLogistics = logisticsMapper.selectById(ledgerReq.getIdLong());
        orderCheck(kwpLedgerLogistics);

        successCheck(kwpLedgerLogistics.getStatus());
        //更新对账单状态
        LocalDateTime receiptTime = null;

        if (Objects.nonNull(ledgerReq.getReceiptTime())) {
            receiptTime = LocalDateTime.of(ledgerReq.getReceiptTime(), LocalTime.MIN);
            kwpLedgerLogistics.setReceiptTime(receiptTime);
        }
        kwpLedgerLogistics.setSuccessPhone(ledgerReq.getSuccessPhone());
        kwpLedgerLogistics.setSuccessUser(ledgerReq.getSuccessUser());
        kwpLedgerLogistics.setSuccessUserId(ledgerReq.getSuccessUserId());
        kwpLedgerLogistics.setStatus(LedgerEnum.SUCCESS.getStatus());
        kwpLedgerLogistics.setUpdateBy(LoginUserHolder.getUserId());
        kwpLedgerLogistics.setUpdateTime(LocalDateTime.now());
        logisticsMapper.updateById(kwpLedgerLogistics);
        //生成结算单
        KwpSettlementLogistics kwpSettlementLogistics = new KwpSettlementLogistics();
        kwpSettlementLogistics.setId(new IdWorker(NumberConstant.ONE).nextId());
        kwpSettlementLogistics.setEntId(LoginUserHolder.getEntId());
        kwpSettlementLogistics.setLLedgerId(kwpLedgerLogistics.getId());
        kwpSettlementLogistics.setSlOrderNo(OrderGenerateSeqNoUtils.getOtherSeqNo(RedisOrderGenerateEnum.LEDGER_CHECKING, OrderRuleEnum.SETTLEMENT_LOGISTICS_ORDER));
        //取物流对账单名称
        kwpSettlementLogistics.setName(kwpLedgerLogistics.getName());
        //实际结算金额就是结算单实际需付金额
        kwpSettlementLogistics.setTotalPrice(kwpLedgerLogistics.getSettlePrice());
        kwpSettlementLogistics.setActualPrice(kwpLedgerLogistics.getActualPrice());
        kwpSettlementLogistics.setTrading(kwpLedgerLogistics.getTrading());
        kwpSettlementLogistics.setRemark(Global.EMPTY_STRING);
        kwpSettlementLogistics.setAuditUserId(kwpLedgerLogistics.getAuditUserId());
        kwpSettlementLogistics.setAuditUser(kwpLedgerLogistics.getAuditUser());
        kwpSettlementLogistics.setAuditPhone(kwpLedgerLogistics.getAuditPhone());
        kwpSettlementLogistics.setSuccessUserId(ledgerReq.getSuccessUserId());
        kwpSettlementLogistics.setSuccessUser(ledgerReq.getSuccessUser());
        kwpSettlementLogistics.setSuccessPhone(ledgerReq.getSuccessPhone());
        kwpSettlementLogistics.setReceiptTime(receiptTime);
        //1-待结算
        kwpSettlementLogistics.setStatus(SettlementEnum.WAITING_PAYMENT.getStatus());
        kwpSettlementLogistics.setCreateBy(LoginUserHolder.getUserId());
        kwpSettlementLogistics.setCreateTime(LocalDateTime.now());
        kwpSettlementLogistics.setUpdateBy(LoginUserHolder.getUserId());
        kwpSettlementLogistics.setUpdateTime(LocalDateTime.now());
        kwpSettlementLogistics.setDelFlag(Global.UN_DELETED);

        kwpSettlementLogisticsService.save(kwpSettlementLogistics);

        logisticsTrackService.saveTrack(ledgerReq.getIdLong(), Global.EMPTY_STRING, LedgerEnum.SUCCESS);


        //托运方
        KwpLedgerLogisticsUnit logisticsUnit = logisticsUnitService.queryCustomerEnt(ledgerReq.getIdLong(), LogisticsUnitType.SHIPPER);
        //承运方
        KwpLedgerLogisticsUnit logisticsUnit2 = logisticsUnitService.queryCustomerEnt(ledgerReq.getIdLong(), LogisticsUnitType.CARRIER);
        //推送创建人
        messageSender.sendCreate(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, new UserInfo().setUserId(LoginUserHolder.getUserId()).setEntId(LoginUserHolder.getEntId()), MessageEnum.LEDGER_SUCCESS_CARRIER);
        //推送系统管理员和变更人
        messageSender.sendPurchaseBoth(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", kwpLedgerLogistics.getLLedgerNo());
            put("name", kwpLedgerLogistics.getName());
        }}, ledgerReq.getIdLong(), logisticsUnit.getEntId(), MessageEnum.LEDGER_SUCCESS_SHIPPER);


        //推送双方系统管理员
        messageSender.sendManager(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit.getFirmName());
            put("number", kwpSettlementLogistics.getSlOrderNo());
        }}, logisticsUnit2.getEntId(), MessageEnum.SETTLEMENT_CARRIER);
        messageSender.sendManager(LoginUserHolder.getUserId(), new HashMap<>() {{
            put("company", logisticsUnit2.getFirmName());
            put("number", kwpSettlementLogistics.getSlOrderNo());
        }}, logisticsUnit.getEntId(), MessageEnum.SETTLEMENT_SHIPPER);
        return "对账完成";
    }

    /**
     * 按类型统计表头的数据
     * 1-托运方 2-承运方
     *
     * @param logisticsReq 查询参数
     * @return 统计数据
     */
    public List<TableTop> orderCount(LogisticsReq logisticsReq) {
        logisticsReq.setEntId(LoginUserHolder.getEntId());
        Map<String, Long> map;
        List<Long> authUserIdList = LoginUserHolder.getAuthUserIdList();
        if (Objects.equals(logisticsReq.getUnitType(), LogisticsUnitType.SHIPPER)) {
            map = logisticsMapper.countSendOrder(logisticsReq, authUserIdList);
        } else {
            map = logisticsMapper.countAuditOrder(logisticsReq, authUserIdList);
        }
        TableTop ledgerCountVo;
        /*统计数据转换*/
        List<TableTop> res = new ArrayList<>();
        for (LedgerEnum value : LedgerEnum.values()) {
            ledgerCountVo = new TableTop();
            ledgerCountVo.setTotal(Math.toIntExact(map.get(value.getLabel())));
            ledgerCountVo.setName(value.getDesc());
            ledgerCountVo.setValue(value.getStatus());
            res.add(ledgerCountVo);
        }
        return res;
    }

    /**
     * 托运方 查询物流对账单
     *
     * @param ids 对账单id列表
     * @return 物流对账单列表
     */
    public List<ILedger> selectShipperList(List<Long> ids) {
        List<LedgerShipperDto> ledgerLogisticsDto = logisticsMapper.selectShipperIds(ids);
        List<ILedger> ledgerLogistics = new ArrayList<>(ledgerLogisticsDto);
        changeDict(ledgerLogistics);
        return ledgerLogistics;
    }

    /**
     * 承运方 查询物流对账单
     *
     * @param ids 对账单id列表
     * @return 物流对账单列表
     */
    public List<ILedger> selectCarrierList(List<Long> ids) {
        List<LedgerCarrierDto> ledgerLogisticsDto = logisticsMapper.selectCarrierIds(ids);
        List<ILedger> ledgerLogistics = new ArrayList<>(ledgerLogisticsDto);
        changeDict(ledgerLogistics);
        return ledgerLogistics;
    }

    /**
     * 根据物流订单id查询对账单详情
     *
     * @param id 物流对账单id
     * @return
     */
    public LedgerLogisticsDetailVo queryUpdate(Long id) {
        LedgerLogisticsDto ledgerLogisticsDto = logisticsMapper.selectId(id, LogisticsUnitType.SHIPPER);
        orderCheck(ledgerLogisticsDto);
        updateCheck(ledgerLogisticsDto.getStatus());
        return getLedgerLogisticsDetailVo(ledgerLogisticsDto);
    }

    /**
     * 查询物流对账单详情
     *
     * @param id       物流对账单id
     * @param unitType 企业单位类型
     * @return
     */
    public LedgerLogisticsDetailVo queryDetail(Long id, Integer unitType) {
        LedgerLogisticsDto ledgerLogisticsDto = logisticsMapper.selectId(id, unitType);
        orderCheck(ledgerLogisticsDto);
        LedgerLogisticsDetailVo detailVo = getLedgerLogisticsDetailVo(ledgerLogisticsDto);
        //1-托运方 展示
        if (unitType == 1) {
            detailVo.setUser(ledgerLogisticsDto.getAuditUser());
            detailVo.setPhone(ledgerLogisticsDto.getAuditPhone());
        } else {
            //对账发起方
            detailVo.setUser(ledgerLogisticsDto.getSuccessUser());
            detailVo.setPhone(ledgerLogisticsDto.getSuccessPhone());
        }
        return detailVo;
    }

    /**
     * 转换物流对账单详情数据
     *
     * @param ledgerLogisticsDto
     * @return
     */
    private LedgerLogisticsDetailVo getLedgerLogisticsDetailVo(LedgerLogisticsDto ledgerLogisticsDto) {
        /*获取物流对账单关联的物流订单*/
        List<KwpLedgerLogisticsOrder> kwpLedgerLogisticsOrders = logisticsOrderService.queryList(ledgerLogisticsDto.getId());
        LedgerLogisticsDetailVo ledgerLogisticsDetailVo = new LedgerLogisticsDetailVo();
        SysDictResDto trading = remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.TRADE_TYPE.getType(), ledgerLogisticsDto.getTrading());
        SysDictResDto taxRate = remoteSystemService.queryDictByTypeAndValue(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(ledgerLogisticsDto.getTaxRate()));

        ledgerLogisticsDetailVo.setId(ledgerLogisticsDto.getId());
        ledgerLogisticsDetailVo.setCheckEntId(ledgerLogisticsDto.getCheckEntId());
        ledgerLogisticsDetailVo.setLLedgerNo(ledgerLogisticsDto.getLLedgerNo());
        ledgerLogisticsDetailVo.setName(ledgerLogisticsDto.getName());
        ledgerLogisticsDetailVo.setFirmName(ledgerLogisticsDto.getFirmName());
        ledgerLogisticsDetailVo.setTrading(ledgerLogisticsDto.getTrading());
        ledgerLogisticsDetailVo.setTradingLabel(Objects.nonNull(trading) ? trading.getLabel() : "");

        ledgerLogisticsDetailVo.setTaxRate(ledgerLogisticsDto.getTaxRate());
        ledgerLogisticsDetailVo.setTaxRateLabel(Objects.nonNull(taxRate) ? taxRate.getLabel() : "");
        ledgerLogisticsDetailVo.setTotalPrice(ledgerLogisticsDto.getTotalPrice());
        ledgerLogisticsDetailVo.setSettlePrice(ledgerLogisticsDto.getSettlePrice());
        ledgerLogisticsDetailVo.setActualPrice(ledgerLogisticsDto.getActualPrice());
        ledgerLogisticsDetailVo.setDeductPrice(ledgerLogisticsDto.getDeductPrice());
        ledgerLogisticsDetailVo.setStartTime(ledgerLogisticsDto.getStartTime());
        ledgerLogisticsDetailVo.setEndTime(ledgerLogisticsDto.getEndTime());
        ledgerLogisticsDetailVo.setRemark(ledgerLogisticsDto.getRemark());
        /*查询物流订单详情*/
        if (!CollectionUtils.isEmpty(kwpLedgerLogisticsOrders)) {
            List<LogisticsOrderDTO> acceptCarriageOrderList = transportDubboService.getAcceptCarriageOrderList(kwpLedgerLogisticsOrders.stream().map(a -> Long.toString(a.getLOrderId())).collect(Collectors.toList()));
            if (CollectionUtils.isEmpty(acceptCarriageOrderList)) {
                ledgerLogisticsDetailVo.setOrderList(new ArrayList<>());
            } else {
                ledgerLogisticsDetailVo.setOrderList(acceptCarriageOrderList);
            }
        }
        return ledgerLogisticsDetailVo;
    }

    public PageRes<LogisticsOrderDTO> orderList(LedgerListReq ledgerListReq) {
        PageHelper.startPage(ledgerListReq.getPage(), ledgerListReq.getPageSize());
        List<KwpLedgerLogisticsOrder> kwpLedgerLogisticsOrders = logisticsOrderService.queryList(ledgerListReq.getIdLong());
        if (CollectionUtils.isEmpty(kwpLedgerLogisticsOrders)) {
            return new PageRes<>();
        }
        PageInfo<KwpLedgerLogisticsOrder> pageInfo = new PageInfo<>(kwpLedgerLogisticsOrders);
        List<LogisticsOrderDTO> acceptCarriageOrderList = transportDubboService.getAcceptCarriageOrderList(kwpLedgerLogisticsOrders.stream().map(a -> String.valueOf(a.getLOrderId())).toList());
        return PageRes.build(pageInfo, acceptCarriageOrderList);
    }


    public List<LogisticsOrderDTO> queryOrderList(LedgerListReq ledgerListReq) {
        List<KwpLedgerLogisticsOrder> kwpLedgerLogisticsOrders = logisticsOrderService.queryList(ledgerListReq.getIdLong());
        if (CollectionUtils.isEmpty(kwpLedgerLogisticsOrders)) {
            return new ArrayList<>();
        }
        List<LogisticsOrderDTO> res = transportDubboService.getAcceptCarriageOrderList(kwpLedgerLogisticsOrders.stream().map(a -> String.valueOf(a.getLOrderId())).toList());
        if (!CollectionUtils.isEmpty(res)) {
            return res.stream().filter(o -> StringUtils.contains(o.getLOrderNO(), ledgerListReq.getKeywords()) ||
                    StringUtils.contains(o.getGoodsName(), ledgerListReq.getKeywords())).toList();
        }
        return new ArrayList<>();
    }

    /**
     * 合作单位-合作管理 校验订单
     *
     * @param entId 企业id 托运方
     */
    public List<String> checkOrder(Long entId, Long entTarget) {
        return logisticsMapper.selectJoin(entId, entTarget);
    }

    public LedgerSize count(Long entId) {
        return logisticsMapper.countSize(entId);
    }

    public List<LedgerLogisticsDto> exportList(LogisticsReq logisticsReq, List<Long> idList) {
        fillPara(logisticsReq);
        List<LedgerLogisticsDto> ledgerLogisticsDtos = logisticsMapper.exportList(logisticsReq, idList, LoginUserHolder.getAuthUserIdList());
        changeDict(ledgerLogisticsDtos);
        return ledgerLogisticsDtos;
    }
}
