package com.sckw.transport.dubbo;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.constant.NumberConstant;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.model.enums.CarWaybillV1Enum;
import com.sckw.core.model.enums.LogisticsOrderEnum;
import com.sckw.transport.api.dubbo.TransportRemoteStatisticsService;
import com.sckw.transport.dao.KwtLogisticsOrderMapper;
import com.sckw.transport.dao.KwtWaybillOrderMapper;
import com.sckw.transport.dao.KwtWaybillOrderSubtaskMapper;
import com.sckw.transport.model.KwtLogisticsOrder;
import com.sckw.transport.model.KwtWaybillOrder;
import com.sckw.transport.model.KwtWaybillOrderSubtask;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @description 运输服务统计dubbo Service
 * @date 2023-09-08 11:09:34
 */
@Slf4j
@Service
@DubboService(group = "design", version = "1.0.0")
public class TransportStatisticsServiceImpl implements TransportRemoteStatisticsService {

    @Autowired
    KwtWaybillOrderMapper waybillOrderMapper;

    @Autowired
    KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    KwtWaybillOrderSubtaskMapper waybillOrderSubtaskMapper;

    /**
     * 统计调度派车次数
     *
     * @param topEntId 集团企业id
     * @return
     */
    @Override
    public Integer statisticsWaybillSendCar(Long topEntId) {
        Integer returnCount = 0;
//        if (Objects.isNull(topEntId)) {
//            throw new BusinessException("请求参数不能为空");
//        }
        List<Long> ids = logisticsOrderMapper.statisticsLogistics(topEntId);
        if (CollectionUtils.isEmpty(ids)) {
            return returnCount;
        }
        List<Integer> orderList = new ArrayList<>(NumberConstant.TWELVE);
        orderList.add(CarWaybillEnum.PENDING_ORDER.getCode());
        orderList.add(CarWaybillEnum.PENDING_VEHICLE.getCode());
        orderList.add(CarWaybillEnum.EXIT_COMPLETED.getCode());
        orderList.add(CarWaybillEnum.WAIT_LOADING.getCode());
        orderList.add(CarWaybillEnum.COMPLETION_LOADING.getCode());
        orderList.add(CarWaybillEnum.WAIT_UNLOADING.getCode());
        orderList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        orderList.add(CarWaybillEnum.APPROVAL_TREAT.getCode());
        orderList.add(CarWaybillEnum.APPROVAL_PASS.getCode());
        orderList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        returnCount = logisticsOrderMapper.statisticsWaybillSendCar(ids, orderList);
        return returnCount;
    }

    /**
     * 统计待核运单
     *
     * @param topEntId 集团企业id
     * @return
     */
    @Override
    public Integer statisticsPendingVerificationWaybill(Long topEntId) {
        Integer returnCount = 0;
//        if (Objects.isNull(topEntId)) {
//            throw new BusinessException("请求参数不能为空");
//        }
        List<Long> ids = logisticsOrderMapper.statisticsLogistics(topEntId);
        if (CollectionUtils.isEmpty(ids)) {
            return returnCount;
        }
        List<Integer> orderList = new ArrayList<>(NumberConstant.TWELVE);
        orderList.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode());
        orderList.add(CarWaybillEnum.APPROVAL_TREAT.getCode());
        orderList.add(CarWaybillEnum.APPROVAL_IN.getCode());
        returnCount = logisticsOrderMapper.statisticsWaybillSendCar(ids, orderList);
        return returnCount;
    }

    /**
     * 统计承运接单数量
     *
     * @param topEntId 集团企业id
     * @return
     */
    @Override
    public Integer statisticsLogistics(Long topEntId,List<Long> enterpriseIds) {
        enterpriseIds=enterpriseIds.stream().distinct().collect(Collectors.toList());
        //统计维度
        List<Integer> orderList = new ArrayList<>();
        orderList.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderList.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode());
        Integer count = logisticsOrderMapper.statisticsLogisticsByTopEntIdAndOrderStatus(topEntId, orderList,"2",enterpriseIds);
        return count;
    }

    /**
     * 统计托运订单数量
     *
     * @param topEntId 集团企业id
     * @return
     */
    @Override
    public Integer statisticsLogisticsByConsign(Long topEntId,List<Long> enterpriseIds) {
        enterpriseIds=enterpriseIds.stream().distinct().collect(Collectors.toList());
        //统计维度
        List<Integer> orderList = new ArrayList<>();
        orderList.add(LogisticsOrderEnum.WAIT_DELIVERY.getCode());
        orderList.add(LogisticsOrderEnum.IN_TRANSIT.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_FINISHED.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_RECONCILED.getCode());
        orderList.add(LogisticsOrderEnum.HAVE_ALREADY_SETTLED.getCode());
        Integer count = logisticsOrderMapper.statisticsLogisticsByTopEntIdAndOrderStatus(topEntId, orderList,"1",enterpriseIds);
        return count;
    }
    /**
     * 统计贸易订单已派车次。
     *
     * @param tOrderId 贸易订单ID
     * @return 已派车次数
     */
    @Override
    public Long countDispatchedWaybillsByTradeOrderId(Long tOrderId) {
        if (Objects.isNull(tOrderId)) {
            throw new BusinessException("贸易订单ID不能为空");
        }
        List<Long> logisticsOrderIds = listLogisticsOrderIdsByTradeOrderId(tOrderId);
        log.info("[车次]物流订单id：{}", JSON.toJSONString(logisticsOrderIds));
        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
            return 0L;
        }
        return Optional.ofNullable(waybillOrderMapper.selectCount(new QueryWrapper<KwtWaybillOrder>()
                        .eq("del_flag", Global.NO)
                        .in("l_order_id", logisticsOrderIds)
                        .and(wq -> wq.ne("remark" ,"空载离场").or().isNull("remark"))
                        .eq("status", CarWaybillV1Enum.COMPLETED.getCode())))
                .orElse(0L);
    }

    /**
     * 按时间范围汇总贸易订单已完成运单的运输净重量（完成量）。
     * <p>
     * 统计口径（三步）：
     * <ol>
     *   <li>查询贸易订单下所有未删除的物流订单</li>
     *   <li>筛选状态为「已完成」(CarWaybillV1Enum.COMPLETED) 的运单；
     *       startTime/endTime 均非空时按运单 update_time 过滤，否则统计全部已完成运单</li>
     *   <li>汇总运单子任务净重：chargeType=1 取 load_amount（装货净重），chargeType=2 取 unload_amount（卸货净重）</li>
     * </ol>
     * 典型场景：贸易订单完结服务费结算、看板今日/本月运单完成量统计。
     *
     * @param tradeOrderId 贸易订单ID
     * @param chargeType   计费方式：1-装货净重，2-卸货净重
     * @param startTime    开始时间（可为 null，须与 endTime 同时传入才生效）
     * @param endTime      结束时间（可为 null，须与 startTime 同时传入才生效）
     * @return 运输净重量合计，无数据时返回 0
     */
    @Override
    public BigDecimal sumCompletedWaybillVolumeByTimeRange(Long tradeOrderId, Integer chargeType,
                                                           LocalDateTime startTime, LocalDateTime endTime) {
        log.info("汇总贸易订单已完成运单运输净重量开始，贸易订单ID:{}, 计费方式:{}, 开始时间:{}, 结束时间:{}",
                tradeOrderId, chargeType, startTime, endTime);

        if (Objects.isNull(tradeOrderId)) {
            log.warn("汇总运输净重量失败，贸易订单ID为空");
            throw new BusinessException("贸易订单ID不能为空");
        }
        if (Objects.isNull(chargeType)) {
            log.warn("汇总运输净重量失败，计费方式为空，贸易订单ID:{}", tradeOrderId);
            throw new BusinessException("计费方式不能为空");
        }
        if (!Objects.equals(chargeType, NumberConstant.ONE) && !Objects.equals(chargeType, NumberConstant.TWO)) {
            log.warn("汇总运输净重量跳过，计费方式不支持，贸易订单ID:{}, 计费方式:{}", tradeOrderId, chargeType);
            return BigDecimal.ZERO;
        }

        // 第一步：查询贸易订单关联的有效物流订单
        List<Long> logisticsOrderIds = listLogisticsOrderIdsByTradeOrderId(tradeOrderId);
        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
            log.info("汇总运输净重量结束，未找到关联物流订单，贸易订单ID:{}, 合计净重量:0", tradeOrderId);
            return BigDecimal.ZERO;
        }
        log.info("查询到关联物流订单，贸易订单ID:{}, 物流订单数量:{}", tradeOrderId, logisticsOrderIds.size());

        // 第二步：筛选已完成运单，可选按完成时间过滤
        QueryWrapper<KwtWaybillOrder> waybillWrapper = new QueryWrapper<KwtWaybillOrder>()
                .select("id")
                .eq("del_flag", Global.NO)
                .in("l_order_id", logisticsOrderIds)
                .eq("status", CarWaybillV1Enum.COMPLETED.getCode());
        if (Objects.nonNull(startTime) && Objects.nonNull(endTime)) {
            waybillWrapper.ge("update_time", toDate(startTime))
                    .lt("update_time", toDate(endTime));
            log.info("运单按时间范围过滤，贸易订单ID:{}, 开始时间:{}, 结束时间:{}", tradeOrderId, startTime, endTime);
        } else {
            log.info("运单未限制时间范围，统计全部已完成运单，贸易订单ID:{}", tradeOrderId);
        }

        List<Long> waybillOrderIds = Optional.ofNullable(waybillOrderMapper.selectList(waybillWrapper))
                .orElse(Collections.emptyList())
                .stream()
                .map(KwtWaybillOrder::getId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(waybillOrderIds)) {
            log.info("汇总运输净重量结束，未找到已完成运单，贸易订单ID:{}, 计费方式:{}, 合计净重量:0",
                    tradeOrderId, chargeType);
            return BigDecimal.ZERO;
        }
        log.info("查询到已完成运单，贸易订单ID:{}, 已完成运单数量:{}", tradeOrderId, waybillOrderIds.size());

        // 第三步：汇总运单子任务装/卸货净重
        QueryWrapper<KwtWaybillOrderSubtask> subtaskWrapper = new QueryWrapper<KwtWaybillOrderSubtask>()
                .eq("del_flag", Global.NO)
                .in("w_order_id", waybillOrderIds);
        if (Objects.equals(chargeType, NumberConstant.ONE)) {
            subtaskWrapper.select("load_amount")
                    .isNotNull("load_amount");
        } else {
            subtaskWrapper.select("unload_amount")
                    .isNotNull("unload_amount");
        }

        BigDecimal totalVolume = Optional.ofNullable(waybillOrderSubtaskMapper.selectList(subtaskWrapper))
                .orElse(Collections.emptyList())
                .stream()
                .map(item -> Objects.equals(chargeType, NumberConstant.ONE) ? item.getLoadAmount() : item.getUnloadAmount())
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        String volumeType = Objects.equals(chargeType, NumberConstant.ONE) ? "装货净重" : "卸货净重";
        log.info("汇总贸易订单已完成运单运输净重量完成，贸易订单ID:{}, 计费方式:{}, 净重类型:{}, 合计净重量:{}",
                tradeOrderId, chargeType, volumeType, totalVolume);
        return totalVolume;
    }

    /**
     * 根据贸易订单ID查询有效物流订单ID列表，统一复用 MyBatis-Plus 查询条件，避免手写SQL。
     *
     * @param tradeOrderId 贸易订单ID
     * @return 有效物流订单ID列表
     */
    private List<Long> listLogisticsOrderIdsByTradeOrderId(Long tradeOrderId) {
        return Optional.ofNullable(logisticsOrderMapper.selectList(new QueryWrapper<KwtLogisticsOrder>()
                        .select("id")
                        .eq("del_flag", Global.NO)
                        .eq("t_order_id", tradeOrderId)))
                .orElse(Collections.emptyList())
                .stream()
                .map(KwtLogisticsOrder::getId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
    }

    /**
     * LocalDateTime 转 Date，保持与数据库时间字段类型一致。
     *
     * @param dateTime 本地日期时间
     * @return Date时间
     */
    private Date toDate(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }


    @Override
    public BigDecimal sumCompletedWaybillVolumeByTimeRange(Long tradeOrderId, Integer chargeType) {
        log.info("汇总贸易订单已完成运单运输净重量开始，贸易订单ID:{}, 计费方式:{}",
                tradeOrderId, chargeType);

        if (Objects.isNull(tradeOrderId)) {
            log.warn("汇总运输净重量失败，贸易订单ID为空");
            throw new BusinessException("贸易订单ID不能为空");
        }
        if (Objects.isNull(chargeType)) {
            log.warn("汇总运输净重量失败，计费方式为空，贸易订单ID:{}", tradeOrderId);
            throw new BusinessException("计费方式不能为空");
        }
        if (!Objects.equals(chargeType, NumberConstant.ONE) && !Objects.equals(chargeType, NumberConstant.TWO)) {
            log.warn("汇总运输净重量跳过，计费方式不支持，贸易订单ID:{}, 计费方式:{}", tradeOrderId, chargeType);
            return BigDecimal.ZERO;
        }

        // 第一步：查询贸易订单关联的有效物流订单
        List<Long> logisticsOrderIds = listLogisticsOrderIdsByTradeOrderId(tradeOrderId);
        if (CollectionUtils.isEmpty(logisticsOrderIds)) {
            log.info("汇总运输净重量结束，未找到关联物流订单，贸易订单ID:{}, 合计净重量:0", tradeOrderId);
            return BigDecimal.ZERO;
        }
        log.info("查询到关联物流订单，贸易订单ID:{}, 物流订单数量:{}", tradeOrderId, logisticsOrderIds.size());

        // 第二步：筛选已完成运单，可选按完成时间过滤
        QueryWrapper<KwtWaybillOrder> waybillWrapper = new QueryWrapper<KwtWaybillOrder>()
                .select("id")
                .eq("del_flag", Global.NO)
                .in("l_order_id", logisticsOrderIds)
                .eq("status", CarWaybillV1Enum.COMPLETED.getCode());

        List<Long> waybillOrderIds = Optional.ofNullable(waybillOrderMapper.selectList(waybillWrapper))
                .orElse(Collections.emptyList())
                .stream()
                .map(KwtWaybillOrder::getId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(waybillOrderIds)) {
            log.info("汇总运输净重量结束，未找到已完成运单，贸易订单ID:{}, 计费方式:{}, 合计净重量:0",
                    tradeOrderId, chargeType);
            return BigDecimal.ZERO;
        }
        log.info("查询到已完成运单，贸易订单ID:{}, 已完成运单数量:{}", tradeOrderId, waybillOrderIds.size());

        // 第三步：汇总运单子任务装/卸货净重
        QueryWrapper<KwtWaybillOrderSubtask> subtaskWrapper = new QueryWrapper<KwtWaybillOrderSubtask>()
                .eq("del_flag", Global.NO)
                .in("w_order_id", waybillOrderIds);
        if (Objects.equals(chargeType, NumberConstant.ONE)) {
            subtaskWrapper.select("load_amount")
                    .isNotNull("load_amount");
        } else {
            subtaskWrapper.select("unload_amount")
                    .isNotNull("unload_amount");
        }

        BigDecimal totalVolume = Optional.ofNullable(waybillOrderSubtaskMapper.selectList(subtaskWrapper))
                .orElse(Collections.emptyList())
                .stream()
                .map(item -> Objects.equals(chargeType, NumberConstant.ONE) ? item.getLoadAmount() : item.getUnloadAmount())
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        String volumeType = Objects.equals(chargeType, NumberConstant.ONE) ? "装货净重" : "卸货净重";
        log.info("汇总贸易订单已完成运单运输净重量完成，贸易订单ID:{}, 计费方式:{}, 净重类型:{}, 合计净重量:{}",
                tradeOrderId, chargeType, volumeType, totalVolume);
        return totalVolume;
    }
}
