package com.ghy.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.AdapayErrorCode;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.adapay.model.DivMember;
import com.ghy.common.adapay.model.PaymentDTO;
import com.ghy.common.constant.UserConstants;
import com.ghy.common.core.text.Convert;
import com.ghy.common.enums.*;
import com.ghy.common.exception.base.BaseException;
import com.ghy.common.utils.*;
import com.ghy.customer.domain.Customer;
import com.ghy.customer.service.CustomerService;
import com.ghy.goods.domain.DeptGoodsCategory;
import com.ghy.goods.domain.GoodsCategory;
import com.ghy.goods.domain.GoodsStandard;
import com.ghy.goods.service.DeptGoodsCategoryService;
import com.ghy.goods.service.GoodsCategoryService;
import com.ghy.goods.service.GoodsStandardService;
import com.ghy.order.domain.*;
import com.ghy.order.mapper.OrderAddSubtractMapper;
import com.ghy.order.mapper.OrderDetailMapper;
import com.ghy.order.mapper.OrderMasterMapper;
import com.ghy.order.pojo.dto.OrderDetailStatisticsDTO;
import com.ghy.order.service.*;
import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.service.WorkerService;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static java.time.temporal.ChronoField.*;

@Service
public class OrderDetailServiceImpl implements OrderDetailService {

    private static final Logger logger = LoggerFactory.getLogger(OrderDetailServiceImpl.class);

    private static final AtomicLong INDEX = new AtomicLong(1L);

    public static final DateTimeFormatter MINI_FORMATTER = new DateTimeFormatterBuilder()
            .appendValue(YEAR, 4).appendValue(MONTH_OF_YEAR, 2)
            .appendValue(DAY_OF_MONTH, 2).appendValue(HOUR_OF_DAY, 2)
            .appendValue(MINUTE_OF_HOUR, 2).appendValue(SECOND_OF_MINUTE, 2).toFormatter();

    private static final Integer ZERO = 0;

    @Resource
    private ThreadPoolTaskExecutor executor;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private OrderMasterMapper orderMasterMapper;
    @Resource
    private AdapayService adapayService;
    @Resource
    private OrderMasterService orderMasterService;
    @Resource
    private FinancialMasterService financialMasterService;
    @Resource
    private FinancialDetailService financialDetailService;
    @Resource
    private FinancialChangeRecordService financialChangeRecordService;
    @Resource
    private OrderGoodsService orderGoodsService;
    @Resource
    private OrderFineRecordMapper orderFineRecordMapper;
    @Resource
    private OrderAddSubtractMapper orderAddSubtractMapper;
    @Resource
    private WorkerService workerService;
    @Resource
    private GoodsStandardService goodsStandardService;
    @Resource
    private DeptGoodsCategoryService deptGoodsCategoryService;

    @Resource
    private CustomerService customerService;

    @Resource
    private IAfterServiceRecordService afterServiceRecordService;

    @Resource
    private IOrderAttachmentRecordService orderAttachmentRecordService;

    @Resource
    private IOrderCallRecordService orderCallRecordService;

    // Adapay 手续费率 默认0.008
    @Value("${adapay.fee_rate:0.008}")
    private String feeRate;

    private final OrderDetailStatisticsDTO statisticsDTO = new OrderDetailStatisticsDTO();
    private final OrderDetailStatisticsDTO statisticsDTOByNow = new OrderDetailStatisticsDTO();

    @Override
    public int insertOrderDetail(OrderDetail orderDetail) {
        return orderDetailMapper.insertOrderDetail(orderDetail);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateOrderDetail(OrderDetail orderDetail) {
        if (orderDetail.getOrderStatus() == null) {
            // 修改预约时间的时候需要清除超时状态
            if (orderDetail.getExpectTimeStart() != null && orderDetail.getExpectTimeStart().compareTo(new Date()) > 0) {
                orderDetail.setTimeout(0);
            }
            return orderDetailMapper.updateOrderDetail(orderDetail);
        }
        int orderStatus = orderDetail.getOrderStatus();
        boolean flag = Boolean.TRUE;
        // 查子单信息
        OrderDetail originOrderDetail = this.orderDetailMapper.selectById(orderDetail.getId());
        if (!Objects.equals(originOrderDetail.getOrderStatus(), orderDetail.getOrderStatus())) {
            // 修改状态的时候需要清除超时状态
            orderDetail.setTimeout(0);
        }
        
        // 判断是否为立即发货订单
        if (orderDetail.getIsQuicklyDelivery() != null && orderDetail.getIsQuicklyDelivery() == 1) {
            // 查询主单信息获取发货类型
        
            
            orderDetail.setOrderStatus(OrderStatus.SERVER.code());
            
            // 立即发货时，计算确认截止时间并设置到confirmStartTime字段
            Date now = new Date();
            long waitTimeMillis;
            String logType;
            
            // 根据发货类型判断等待时间
            if (orderDetail.getDeliveryType() != null) {
                if (orderDetail.getDeliveryType() == 2 || orderDetail.getDeliveryType() == 3) {
                    // 送货上门或自提：8小时
                    waitTimeMillis = 8 * 60 * 60 * 1000L; // 8小时的毫秒数
                    logType = orderDetail.getDeliveryType() == 2 ? "送货上门" : "自提";
                } else if (orderDetail.getDeliveryType() == 1) {
                    // 发快递/物流：4天
                    waitTimeMillis = 4 * 24 * 60 * 60 * 1000L; // 4天的毫秒数
                    logType = "发快递/物流";
                } else {
                    // 未知发货类型，默认8小时
                    waitTimeMillis = 8 * 60 * 60 * 1000L;
                    logType = "未知类型(默认8小时)";
                    logger.warn("订单[{}]发货类型未知[{}]，使用默认8小时", orderDetail.getCode(), orderDetail.getDeliveryType());
                }
                
                // 计算确认截止时间
                Date confirmDeadlineTime = new Date(now.getTime() + waitTimeMillis);
                orderDetail.setConfirmStartTime(confirmDeadlineTime);
                
                logger.info("立即发货订单[{}]发货类型[{}]，确认截止时间：{}",
                        orderDetail.getCode(), logType,
                        com.ghy.common.utils.DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", confirmDeadlineTime));
            } else {
                logger.warn("订单[{}]发货类型为null，未设置确认截止时间", orderDetail.getCode());
            }
        }
        
        int result = orderDetailMapper.updateOrderDetail(orderDetail);
        // 查询主单关联商品
        List<OrderGoods> masterOrderGoodsList = orderGoodsService.selectByOrderMasterId(originOrderDetail.getOrderMasterId());
        Map<Long, OrderGoods> masterGoodsMap = masterOrderGoodsList.stream().collect(Collectors.toMap(OrderGoods::getGoodsStandardId, obj -> obj));
        // 子单修改从服务中到确认中需要修改已服务商品数量，从确认中到服务中需要重置已服务商品数量
        if (OrderStatus.FINISH_CHECK.code() == orderDetail.getOrderStatus() && originOrderDetail.getOrderStatus() < OrderStatus.FINISH_CHECK.code()) {
            List<OrderGoods> orderGoodsList = orderGoodsService.selectByOrderDetailId(orderDetail.getId());
            if (CollectionUtils.isNotEmpty(orderGoodsList)) {
                orderGoodsList.stream().filter(Objects::nonNull).forEach(orderGoods -> {
                    if (orderGoods.getGoodsStandardId() != null) {
                        // 检查goodsNum是否为null，提供默认值0
                        Integer goodsNum = orderGoods.getGoodsNum() != null ? orderGoods.getGoodsNum() : 0;
                        orderGoods.setServerGoodsNum(goodsNum);
                        orderGoodsService.updateOrderGoods(orderGoods);
                        // 主单关联商品相应修改已服务数量
                        OrderGoods masterGoods = masterGoodsMap.get(orderGoods.getGoodsStandardId());
                        if (masterGoods != null && masterGoods.getServerGoodsNum() != null) {
                            Integer masterServerGoodsNum = masterGoods.getServerGoodsNum();
                            masterGoods.setServerGoodsNum(masterServerGoodsNum + goodsNum);
                        }
                    }
                });
            }
        } else if (OrderStatus.FINISH_CHECK.code() == originOrderDetail.getOrderStatus() && orderDetail.getOrderStatus() < OrderStatus.FINISH_CHECK.code()) {
            List<OrderGoods> orderGoodsList = orderGoodsService.selectByOrderDetailId(orderDetail.getId());
            if (CollectionUtils.isNotEmpty(orderGoodsList)) {
                orderGoodsList.stream().filter(Objects::nonNull).forEach(orderGoods -> {
                    if (orderGoods.getGoodsStandardId() != null) {
                        orderGoods.setServerGoodsNum(0);
                        orderGoodsService.updateOrderGoods(orderGoods);
                        // 主单关联商品相应修改已服务数量
                        OrderGoods masterGoods = masterGoodsMap.get(orderGoods.getGoodsStandardId());
                        if (masterGoods != null && masterGoods.getServerGoodsNum() != null && orderGoods.getGoodsNum() != null) {
                            Integer masterServerGoodsNum = masterGoods.getServerGoodsNum();
                            masterGoods.setServerGoodsNum(masterServerGoodsNum - orderGoods.getGoodsNum());
                        }
                    }
                });
            }
        }
        // 更新主单关联商品
        masterOrderGoodsList.stream().forEach(masterOrderGoods -> {
            orderGoodsService.updateOrderGoods(masterOrderGoods);
        });

        OrderDetail detailInfo = this.orderDetailMapper.selectById(orderDetail.getId());
        // 判断是否需要更新主单状态.即是否有
        // 1.更新大于当前  detail 1/2/3
        for (OrderDetail detail : orderDetailMapper.selectByOrderMasterId(detailInfo.getOrderMasterId())) {
            if (detail.getOrderStatus() < orderStatus) {
                flag = false;
                break;
            }
        }
        // 判断主单是否全部派单
        boolean allAssign = orderMasterService.isAllAssign(detailInfo.getOrderMasterId());
        if (flag && allAssign) {
            OrderMaster orderMaster = orderMasterMapper.selectById(detailInfo.getOrderMasterId());
            if (!Objects.equals(orderMaster.getOrderStatus(), orderStatus)) {
                // 修改状态的时候需要清除超时状态
                orderMaster.setTimeout(0);
            }
            if (ObjectUtils.isEmpty(orderDetail.getExpectTimeStart())) {
                orderMaster.setOrderStatus(orderStatus);
                orderMasterMapper.updateOrderMaster(orderMaster);
            }
        }
        return result;
    }

    @Override
    public List<OrderDetail> selectOrderDetailList(OrderDetail orderDetail) {
        List<OrderDetail> result = new ArrayList<>();
        List<OrderDetail> orderDetails = orderDetailMapper.selectOrderDetailList(orderDetail);
        orderDetails.forEach(model -> {
            if (StringUtils.isNotEmpty(orderDetail.getIsCall())) {
                OrderCallRecord param = new OrderCallRecord();
                param.setOrderType("02");
                param.setOrderId(model.getOrderMasterId());
                List<OrderCallRecord> list = orderCallRecordService.selectOrderCallRecordList(param);
                // 用于判断是约 还是 排的问题
                if ("01".equals(orderDetail.getIsCall()) && CollectionUtils.isEmpty(list)) {
                    result.add(model);
                }
                if ("02".equals(orderDetail.getIsCall()) && CollectionUtils.isNotEmpty(list)) {
                    result.add(model);
                }
            } else {
                result.add(model);
            }
        });
        return result;
    }

    @Override
    public OrderDetail selectById(Long orderDetailId) {
        return orderDetailMapper.selectById(orderDetailId);
    }

    @Override
    public List<OrderDetail> selectByOrderMasterId(Long orderMasterId) {
        return orderDetailMapper.selectByOrderMasterId(orderMasterId);
    }

    @Override
    public List<OrderDetail> selectByOrderMasterIds(List<Long> orderMasterIds) {
        if (CollectionUtils.isEmpty(orderMasterIds)) {
            return Collections.emptyList();
        }
        return orderDetailMapper.selectByOrderMasterIds(orderMasterIds);
    }

    @Override
    public int deleteOrderDetailByIds(String ids) {
        Long[] orderDetailIds = Convert.toLongArray(ids);
        return orderDetailMapper.deleteOrderDetailByIds(orderDetailIds);
    }

    @Override
    public String checkOrderDetailCodeUnique(OrderDetail orderDetail) {
        long orderDetailId = orderDetail.getId() == null ? -1L : orderDetail.getId();
        OrderDetail info = orderDetailMapper.checkOrderDetailCodeUnique(orderDetail.getCode());
        if (info != null && info.getId() != orderDetailId) {
            return UserConstants.ORDER_CODE_NOT_UNIQUE;
        }
        return UserConstants.ORDER_CODE_UNIQUE;
    }

    @Override
    public synchronized String createCode(String orderMasterCode) {
        OrderDetail param = new OrderDetail();
        param.setOrderMasterCode(orderMasterCode);
        List<OrderDetail> details = orderDetailMapper.selectOrderDetailList(param);
        int count = 0;
        if (CollectionUtils.isNotEmpty(details)) {
            count = details.size();
        }
        return orderMasterCode + "-" + (count + 1);
    }

    @Override
    public Map<Long, List<OrderDetail>> byOrderIdInMap(List<Long> orderIdList) {
        Map<Long, List<OrderDetail>> longByOrderDetailListMap = new HashMap<>();
        if (orderIdList != null && orderIdList.size() > 0) {
            List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderIdList(orderIdList);
            if (orderDetailList != null && orderDetailList.size() > 0) {
                for (OrderDetail orderDetail : orderDetailList) {
                    List<OrderDetail> orderDetailListByMapCrw = longByOrderDetailListMap.get(orderDetail.getOrderMasterId());
                    if (orderDetailListByMapCrw != null && orderDetailListByMapCrw.size() > 0) {
                        List<OrderDetail> orderDetailListByMapNew = new ArrayList<>();
                        orderDetailListByMapNew.add(orderDetail);
                        longByOrderDetailListMap.put(orderDetail.getOrderMasterId(), orderDetailListByMapNew);
                    } else {
                        List<OrderDetail> orderDetailListByMapNew = new ArrayList<>();
                        orderDetailListByMapNew.add(orderDetail);
                        longByOrderDetailListMap.put(orderDetail.getOrderMasterId(), orderDetailListByMapNew);
                    }
                }
            }
        }
        return longByOrderDetailListMap;
    }

    @Override
    public void applyForCancel(Long orderDetailId) throws BaseAdaPayException {
        OrderDetail orderDetail = selectById(orderDetailId);
        Assert.notNull(orderDetail, "找不到对应的子订单");

        switch (orderDetail.getOrderStatus()) {
            case 0:
            case 1: // 待接单和待排期状态可直接取消
                cancel(orderDetailId);
                break;
            case 2: // 待上门状态需要师傅同意才能取消
                orderDetailMapper.updateStatus(orderDetailId, OrderStatus.GOING_CANCEL.code());
                logger.info("Set OrderDetail[{}].orderStatus = {}", orderDetailId, OrderStatus.GOING_CANCEL.code());
                break;
            case 3: // 服务中状态需要师傅同意才能取消
                orderDetailMapper.updateStatus(orderDetailId, OrderStatus.SERVER_CANCEL.code());
                logger.info("Set OrderDetail[{}].orderStatus = {}", orderDetailId, OrderStatus.SERVER_CANCEL.code());
                break;
            case 4: // 待确认状态需要师傅同意才能取消
                orderDetailMapper.updateStatus(orderDetailId, OrderStatus.FINISH_CHECK_CANCEL.code());
                logger.info("Set OrderDetail[{}].orderStatus = {}", orderDetailId, OrderStatus.FINISH_CHECK_CANCEL.code());
                break;
            default: // 其他状态不可取消
                throw new IllegalArgumentException("这个子订单不能取消了");
        }
    }

    /**
     * 子订单取消
     *
     * @param orderDetailId 子订单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancel(long orderDetailId) throws BaseAdaPayException {
        logger.info("子订单取消 orderDetailId = {}", orderDetailId);
        OrderDetail orderDetail = selectById(orderDetailId);
        Assert.notNull(orderDetail, "找不到对应的子订单");
        if (OrderStatus.FINISH.code() == orderDetail.getOrderStatus() || OrderStatus.CANCEL.code() == orderDetail.getOrderStatus()) {
            logger.info("子订单[id={}]状态不正确，orderStatus={}", orderDetailId, orderDetail.getOrderStatus());
            return;
        }
        // 更新子订单状态
        orderDetailMapper.updateStatus(orderDetailId, OrderStatus.CANCEL.code());
        logger.info("Set OrderDetail[{}].orderStatus = {}", orderDetailId, OrderStatus.CANCEL.code());
        
        // 清除超时状态
        OrderDetail updateOrderDetail = new OrderDetail();
        updateOrderDetail.setId(orderDetailId);
        updateOrderDetail.setTimeout(0);
        orderDetailMapper.updateOrderDetail(updateOrderDetail);
        // 查询出所有的子订单  就走主订单取消流程
        List<OrderDetail> orderDetails = orderDetailMapper.selectByOrderMasterId(orderDetail.getOrderMasterId());
        // 判断是否是已付款的订单,未付款不需要退款
        FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId());
        Assert.notNull(financialMaster, "找不到对应的财务单");
        // 发起退款
        refund(orderDetail);
        // 如果除了这个子订单以外 没有其它未取消的订单
        boolean allCancel = true;
        for (OrderDetail od : orderDetails) {
            if (!od.getOrderStatus().equals(OrderStatus.CANCEL.code())) {
                allCancel = false;
                break;
            }
        }
        // 判断主单是否全部派单
        boolean allAssign = orderMasterService.isAllAssign(orderDetail.getOrderMasterId());
        // 如果主单已经全部派单 并且 所有单都已经取消
        if (allAssign && allCancel) {
            logger.info("主订单[id={}]下所有的子订单都被取消 直接进入主订单取消流程", orderDetail.getOrderMasterId());
            orderMasterService.cancelAgree(orderDetail.getOrderMasterId(), 1);
        }
    }

    /**
     * 子单全额退款
     *
     * @param orderDetail
     * @throws BaseAdaPayException
     */
    public void refund(OrderDetail orderDetail) throws BaseAdaPayException {
        Long orderDetailId = orderDetail.getId();
        OrderMaster orderMaster = orderMasterMapper.selectById(orderDetail.getOrderMasterId());
        Assert.notNull(orderMaster, "OrderMaster is null !");
        FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId());
        Assert.notNull(financialMaster, "FinancialMaster is null !");
        FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(orderDetailId);
        Assert.notNull(financialMaster, "找不到支付记录");
        boolean paid = PayStatus.PAID.getCode().equals(financialMaster.getPayStatus()) ||
                PayStatus.PAYED_ADD.getCode().equals(financialMaster.getPayStatus());

        // 主财务单金额
        BigDecimal masterMoney = financialMaster.getPayMoney();
        // 子财务单金额
        BigDecimal detailMoney = financialDetail.getPayMoney();

        List<FinancialChangeRecord> fcrList = financialChangeRecordService.selectByDetailIds(orderDetailId.toString());
        // 先把这个子单的加价单全退了
        for (FinancialChangeRecord fcr : fcrList) {
            if (PayStatus.PAID.getCode().equals(fcr.getPayStatus()) || PayStatus.PAYED_ADD.getCode().equals(fcr.getPayStatus())) {
                executor.execute(() -> financialChangeRecordService.refund(orderMaster.getDeptId(), fcr.getId()));
                // 主/子财务单里也加上了加价单的金额 所以这里减掉
                masterMoney = masterMoney.subtract(fcr.getChangeMoney());
                detailMoney = detailMoney.subtract(fcr.getChangeMoney());
            }
        }

        // detailMoney ≤ 0 不需要退款
        if (BigDecimal.ZERO.compareTo(detailMoney) > -1) {
            logger.info("子订单[{}]不需要退款 payMoney={}元", orderDetail.getId(), detailMoney);
            // 更新子财务单金额和状态
            financialDetail.setPayStatus(paid ? PayStatus.REFUND.getCode() : PayStatus.CANCEL.getCode());
            financialDetail.setPayMoney(detailMoney);
            financialDetailService.updateFinancialDetail(financialDetail);

            // 更新主财务单金额
            financialMaster.setPayMoney(masterMoney);
            financialMasterService.updateFinancialMaster(financialMaster);
            return;
        }

        // 更新子财务单金额和状态 如果是已支付改退款中 如果是未支付改为取消
        financialDetail.setPayMoney(detailMoney);
        financialDetail.setPayStatus(paid ? PayStatus.REVERSING.getCode() : PayStatus.CANCEL.getCode());
        financialDetailService.updateFinancialDetail(financialDetail);

        // 更新主财务单金额
        financialMaster.setPayMoney(masterMoney.subtract(detailMoney));
        financialMasterService.updateFinancialMaster(financialMaster);

        if (!paid) {
            logger.info("子订单[id={}]未支付 不需要退款", orderDetailId);
            return;
        }
        Assert.hasText(financialMaster.getPaymentId(), "找不到订单的支付记录，请联系管理员");
        // 发起退款
        String refundAmt = AdapayUtils.bigDecimalToString(detailMoney);
        logger.info("子订单[id={}]发起退款: refundAmt={}元", orderDetailId, refundAmt);
        JSONObject response = adapayService.payReverse(orderMaster.getDeptId(), financialMaster.getPaymentId(), refundAmt, RefundType.ROD);
        boolean status = AdapayStatusEnum.pending.code.equals(response.getString("status")) ||
                AdapayStatusEnum.succeeded.code.equals(response.getString("status"));
        // 如果退款失败 这里携带失败原因抛出异常 回滚订单状态
        Assert.isTrue(status, response.getString("error_msg"));
        logger.info("子订单[id={}]退款成功", orderDetailId);
        executor.execute(() -> {
            String reverseId = response.getString("id");
            FinancialDetail fd2update = new FinancialDetail();
            fd2update.setId(financialDetail.getId());
            fd2update.setReverseId(reverseId);
            financialDetailService.updateFinancialDetail(fd2update);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelAgree(Long orderDetailId, Integer agree) throws BaseAdaPayException {
        OrderDetail orderDetail = selectById(orderDetailId);
        Assert.notNull(orderDetail, "找不到对应的子订单");
        if (Integer.valueOf(1).equals(agree)) {
            // 师傅同意取消订单
            cancel(orderDetailId);
        } else {
            // 师傅不同意取消订单
            Integer orderStatus = orderDetail.getOrderStatus();
            // 修改主订单状态为原来的状态
            orderDetailMapper.updateStatus(orderDetailId, Math.abs(orderStatus));
        }
    }

    @Override
    public void updateByOrderMasterId(OrderDetail orderDetail) {
        orderDetailMapper.updateByOrderMasterId(orderDetail);
    }

    @Override
    public List<OrderDetail> selectByStatus(List<Integer> status) {
        if (CollectionUtils.isEmpty(status)) {
            return Collections.emptyList();
        }
        return orderDetailMapper.selectByStatus(status);
    }

    /**
     * 子订单确认完成 暂时先用 synchronized 来避免重复提交
     * 1.修改子订单状态为 OrderStatus.FINISH.code
     * 2.将子订单对应的子财务单确认分账
     * 3.提现至银行卡
     *
     * @param orderDetailId 子订单ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void finish(Long orderDetailId) throws BaseAdaPayException {
        logger.debug("子订单[{}]finish......", orderDetailId);
        // 校验订单
        OrderDetail orderDetail = selectById(orderDetailId);
        if (orderDetail == null) {
            throw new BaseException("找不到对应的子订单");
        }
        OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
        String odCode = orderDetail.getCode();
        Assert.isTrue(!orderDetail.getOrderStatus().equals(OrderStatus.FINISH.code()), "订单已经是完成状态");
        FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId());
        if (financialMaster == null) {
            throw new BaseException("找不到主财务单");
        }

        // 大师傅
        Worker workerMaster = workerService.selectById(orderMaster.getWorkerId());
        // 小师傅
        Worker workerSub = workerService.selectById(orderDetail.getWorkerId());
        // 订单的支付信息
        PaymentDTO orderPayment = financialMasterService.selectPaymentById(financialMaster.getPaymentId());
        if (orderPayment == null) {
            throw new BaseException("找不到支付记录");
        }
        // 子订单对应的子财务单只有一条 直接取出
        FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(orderDetailId);
        if (financialDetail == null) {
            throw new BaseException("FinancialDetail is null!!!");
        }
        if (financialDetail.getPayStatus() != 1) {
            throw new BaseException("订单不是已支付状态");
        }
        final Long deptId = orderMaster.getDeptId();
        Long financialMasterId = financialDetail.getFinancialMasterId();
        // 找到 type=平台抽成 的子财务单 用来承担手续费
        List<FinancialDetail> details = financialDetailService.selectByFinancialMasterIdAndType(financialMasterId, FinancialDetailType.PLATFORM_FEE.getCode());
        if (CollectionUtils.isEmpty(details)) {
            logger.error("找不到平台抽成的子财务单 orderDetailId={}", orderDetailId);
            return;
        }
        logger.info("财务子单{}", financialDetail);
        logger.info("财务明细{}", details);
        List<OrderGoods> orderGoods = orderGoodsService.selectByOrderDetailId(orderDetailId);
        if (CollectionUtils.isEmpty(orderGoods)) {
            throw new BaseException("找不到子订单对应的商品");
        }

        Long goodsStandardId = orderGoods.get(0).getGoodsStandardId();
        GoodsStandard goodsStandard = goodsStandardService.selectById(goodsStandardId);
        // 第四级规格
        DeptGoodsCategory childCategory = deptGoodsCategoryService.get(goodsStandard.getDeptGoodsCategoryId());
        // 需要找第三级规格
        DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(childCategory.getParentCategoryId());



        // 平台抽成的子财务单
        FinancialDetail platformFeeFD = details.get(0);
        BigDecimal payMoney = platformFeeFD.getPayMoney();
        logger.info("平台的抽成{}子单的实际金额{}", payMoney, financialDetail.getPayMoney());
        FinancialDetail fdUpdate = new FinancialDetail();
        fdUpdate.setId(platformFeeFD.getId());

        logger.debug("子订单[{}]的完单流程开始", orderDetailId);

        // 子单收款人的memberId
        String memberId = AdapayUtils.getWorkerMemberId(financialDetail.getPayeeId(), deptId);
        String masterMemberId = AdapayUtils.getWorkerMemberId(workerMaster.getWorkerId(), deptId);
        String placeId = null;
        String parentPlaceId = null;


        // 一级分销追加扣点
        BigDecimal saleRateOne = new BigDecimal(deptGoodsCategory.getOneRate());
        saleRateOne = MoneyUtil.lt0(saleRateOne) ? BigDecimal.ZERO : saleRateOne;
        logger.info("一级分销扣点{}", saleRateOne);
        // 二级分销追加扣点
        BigDecimal saleRateTwo = new BigDecimal(deptGoodsCategory.getTwoRate());
        saleRateTwo = MoneyUtil.lt0(saleRateTwo) ? BigDecimal.ZERO : saleRateTwo;
        logger.info("二级分销扣点{}", saleRateTwo);
        // 三级分销追加扣点
        BigDecimal saleRateThree = new BigDecimal(deptGoodsCategory.getThreeRate());
        saleRateThree = MoneyUtil.lt0(saleRateThree) ? BigDecimal.ZERO : saleRateThree;
        logger.info("三级分销扣点{}", saleRateThree);
        Customer customer = customerService.selectByCustomerId(orderMaster.getCustomerId());
        // 一级分销售
        if (customer.getCustomerPlace() != null && customer.getParentCustomerPlace() == null) {
            placeId = AdapayUtils.getCustomerMemberId(customer.getCustomerPlace(), deptId);
            saleRateThree = saleRateThree.add(saleRateTwo).add(saleRateOne);
            saleRateTwo = BigDecimal.ZERO;
        } else if (customer.getCustomerPlace() != null && customer.getParentCustomerPlace() != null) {
            placeId = AdapayUtils.getCustomerMemberId(customer.getCustomerPlace(), deptId);
            parentPlaceId = AdapayUtils.getCustomerMemberId(customer.getParentCustomerPlace(), deptId);
            saleRateTwo = saleRateTwo.add(saleRateOne);
        }

        // 大师傅提成
        BigDecimal teamRete = new BigDecimal(workerMaster.getLeaderTeamRate());
        teamRete = MoneyUtil.lt0(teamRete) ? BigDecimal.ZERO : teamRete;
        BigDecimal teamMoney = new BigDecimal(workerSub.getLeaderTeamMoney());
        teamMoney = MoneyUtil.lt0(teamMoney) ? BigDecimal.ZERO : teamMoney;

        // 平台加价抽成
        BigDecimal deptRate = new BigDecimal(deptGoodsCategory.getDeptRate());
        deptRate = MoneyUtil.lt0(deptRate) ? BigDecimal.ZERO : deptRate;
        BigDecimal deptMoney = MoneyUtil.lt0(deptGoodsCategory.getDeptMoney()) ? BigDecimal.ZERO : deptGoodsCategory.getDeptMoney();
        logger.info("平台加价抽成{},费率{}", deptMoney, deptRate);
        // 平台追加抽成
        BigDecimal pcDeptRate = new BigDecimal(deptGoodsCategory.getPcDeptRate());
        pcDeptRate = MoneyUtil.lt0(pcDeptRate) ? BigDecimal.ZERO : pcDeptRate;
        BigDecimal pcDeptMoney = MoneyUtil.lt0(deptGoodsCategory.getPcDeptMoney()) ? BigDecimal.ZERO : deptGoodsCategory.getPcDeptMoney();
        logger.info("平台追加抽成{},费率{}", pcDeptMoney, pcDeptRate);
        BigDecimal retainRate = new BigDecimal(deptGoodsCategory.getRetainRate());
        retainRate = MoneyUtil.lt0(retainRate) ? BigDecimal.ZERO : retainRate;
        BigDecimal retainMoney = MoneyUtil.lt0(deptGoodsCategory.getRetainMoney()) ? BigDecimal.ZERO : deptGoodsCategory.getPcDeptMoney();



        BigDecimal dtx = BigDecimal.ZERO;

        // 追加金额分账
        BigDecimal dtx1 = this.addPaymentConfirm(orderDetailId, deptId, memberId, masterMemberId, teamRete, teamMoney, pcDeptRate, pcDeptMoney, saleRateOne, placeId, saleRateTwo, parentPlaceId);
        dtx = dtx.add(dtx1);
        logger.info("追加金额分账{}", dtx);
        // 改价单分账
        BigDecimal changeMoney = BigDecimal.ZERO;
        // 查询子订单的加价记录
        List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectByDetailIds(String.valueOf(orderDetailId));
        logger.info("子订单加价记录{}", dtx);
        if (CollectionUtils.isNotEmpty(financialChangeRecords)) {
            // 改价记录只会有一条 直接取出
            FinancialChangeRecord fcRecord = financialChangeRecords.get(0);
            boolean paid = PayStatus.PAID.getCode().equals(fcRecord.getPayStatus());
            boolean payedAdd = PayStatus.PAYED_ADD.getCode().equals(fcRecord.getPayStatus());
            if (paid || payedAdd) {
                changeMoney = fcRecord.getChangeMoney();
                logger.info("子订单加价金额{}", changeMoney);
                BigDecimal dtx2 = changePaymentConfirm(fcRecord, orderDetailId, orderDetail.getWorkerId(), deptId, memberId,
                        masterMemberId, teamRete, teamMoney, deptRate, deptMoney, saleRateThree, placeId, saleRateTwo, parentPlaceId,retainRate);
//                dtx = dtx.add(dtx2);
                logger.info("子订单加价记录{}加价完毕{}", dtx2, dtx);
            }
        }

        // 附件费分账
        OrderAttachmentRecord param = new OrderAttachmentRecord();
        param.setOrderDetailId(orderDetailId);
        List<OrderAttachmentRecord> orderAttachmentRecordList = orderAttachmentRecordService.selectOrderAttachmentRecordList(param);
        logger.info("附件费分账金额{}", orderAttachmentRecordList);
        if (CollectionUtils.isNotEmpty(orderAttachmentRecordList)) {
            // 附件费分账.
            attachPaymentConfirm(orderAttachmentRecordList.get(0), orderDetailId, orderDetail.getWorkerId(), deptId, memberId);
        }
        // --------------------- 子财务单分账部分 start ---------------------
        // 子单的实际金额
        BigDecimal odMoney = financialDetail.getPayMoney();
        logger.info("子单的实际金额{}", odMoney);

        BigDecimal commissionAmount=BigDecimal.ZERO;
        if (MoneyUtil.lte0(odMoney)) {
           logger.info("子财务单[{}] 应支付金额={} 不需要分账", financialDetail.getId(), odMoney);
        } else {
            // 查询师傅的超时扣款记录
            List<OrderTimeoutRecord> fineRecords = orderFineRecordMapper.selectUnFine(orderDetail.getWorkerId(), orderMaster.getDeptId());
            // 超时罚金
            BigDecimal fineMoney = BigDecimal.ZERO;
            ArrayList<Long> fineIds = new ArrayList<>();
            for (OrderTimeoutRecord fineRecord : fineRecords) {
                // 抵扣超时罚金 这里的罚金是按创建时间升序排列的 优先抵扣最早的罚金
                if (MoneyUtil.lt(fineMoney.add(fineRecord.getPayMoney()), odMoney)) {
                    // 加价单金额不足以抵扣罚金
                    break;
                } else {
                    // 抵扣罚金
                    logger.info("子订单[{}]的派单金额[{}]抵扣罚金{}元", orderDetailId, odMoney, fineRecord.getPayMoney());
                    fineMoney = fineMoney.add(fineRecord.getPayMoney());
                    // 被抵扣的罚金记录ID先存下来，分账成功后修改状态
                    fineIds.add(fineRecord.getId());
                }
            }

            // 分账账户信息
            ArrayList<DivMember> divMembers = new ArrayList<>();
            // 是否有罚金
            boolean haveFine = MoneyUtil.gt0(fineMoney);
            logger.info("子单的罚金{},是否有罚金{}", fineMoney, haveFine);
            if (haveFine) { // 有罚金 从罚金里扣除手续费
                // 平台的分账信息 用来承担罚金
                divMembers.add(new DivMember("0", MoneyUtil.toS(fineMoney), true));
                BigDecimal workerMoney = odMoney.subtract(fineMoney);
                if (MoneyUtil.gt0(workerMoney)) {
                    divMembers.add(new DivMember(memberId, MoneyUtil.toS(workerMoney), false));
                    dtx = dtx.add(workerMoney);
                }
            } else {
                // 没有罚金 自己承担手续费
            divMembers.add(new DivMember(memberId, MoneyUtil.toS(odMoney), false));
                // 平台金额部分抽出来部分承担手续费
                BigDecimal payCommissionRate = new BigDecimal("0.01");

                 commissionAmount = odMoney.multiply(payCommissionRate)
                        .setScale(2, RoundingMode.UP);  // 第一次精度控制
                if (commissionAmount.compareTo(payMoney) > 0){
                    for (FinancialDetail financialDetail1:details){
                        payMoney=financialDetail1.getPayMoney();
                        if (payMoney.compareTo(commissionAmount)>0){
                            fdUpdate.setId(financialDetail1.getId());
                            break;
                        }
                    }
                }
                payMoney = payMoney.subtract(commissionAmount);
                fdUpdate.setPayMoney(payMoney);
                divMembers.add(new DivMember("0", MoneyUtil.toS(commissionAmount), true));

               int financialDetailUpdate= financialDetailService.updateFinancialDetail(fdUpdate);
                odMoney = odMoney.add(commissionAmount);
                // 增加手续费财务子单
                FinancialDetail financialDetail1 = new FinancialDetail();
                financialDetail1.setOrderDetailId(orderDetailId);
                financialDetail1.setFinancialDetailType(6);
                financialDetail1.setPayMoney(commissionAmount);
                financialDetail1.setPayTime(new Date());
                financialDetail1.setFinancialMasterId(financialMasterId);
               int financialDetailInsert= financialDetailService.insertFinancialDetail(financialDetail1);
                    logger.info("平台的抽成减去承担手续费后的金额{}，平台手续费{},子单金额{},是否更新成功{},是否增加成功{}", payMoney, commissionAmount,odMoney,financialDetailUpdate,financialDetailInsert);

            }
            logger.info("子单的罚金处理后的总额{}", dtx);
            String orderNo = "OD_" + orderDetailId + "_" + System.currentTimeMillis();
            logger.info("子订单[{}]发起分账: {} 分账人员{}", orderDetailId, JSON.toJSONString(divMembers), orderDetail.getWorkerName());
            JSONObject response = adapayService.paymentConfirm(deptId, orderPayment.getId(), orderNo, MoneyUtil.toS(odMoney), divMembers, null, null);
            logger.info("子订单[{}]的分账结果: {}", orderDetailId, response.toString());
            boolean status = AdapayStatusEnum.succeeded.code.equals(response.getString("status"));
            // 如果确认支付失败 这里抛出异常 回滚订单状态
            Assert.isTrue(status, response.toString());
            // 分账成功 把罚金状态改为已扣除
            fineIds.forEach(fineRecordId -> orderFineRecordMapper.updateFineStatus(fineRecordId, 1));
            logger.info("子单的实际金额{}", odMoney);
            if (commissionAmount.compareTo(BigDecimal.ZERO)>0){
                odMoney=odMoney.subtract(commissionAmount);
            }
            if (!haveFine) {
                String feeAmt = response.getString("fee_amt");
                dtx = dtx.add(odMoney).subtract(new BigDecimal(feeAmt));
            }
            logger.info("子单的没有罚金的实际金额{}", dtx);
        }
        // --------------------- 子财务单分账部分 end ---------------------

        // --------------------- 自动提现流程 start ---------------------
        // 走到这里确认分账成功了 进入自动提现流程
        logger.info("子订单[code={}]开始自动提现", odCode);
        if (MoneyUtil.lte0(dtx)) {
            logger.info("子订单[code={}] 待提现金额={} 无需提现", odCode, dtx);
                  updateStatus(orderDetailId, OrderStatus.FINISH.code());
        } else {
            // 待提现金额
            String cashAmt = AdapayUtils.bigDecimalToString(dtx);
            executor.execute(() -> drawCash(orderDetailId, financialDetail.getDeptId(), memberId, cashAmt));
            // 修改子订单状态为完成
            updateStatus(orderDetailId, OrderStatus.FINISH.code());
        }
        // --------------------- 自动提现流程 end ---------------------
    }

    /**
     * 订单改价分账
     *
     * @param orderDetailId  子订单ID
     * @param workerId       子师傅ID
     * @param deptId         企业ID
     * @param memberId       子师傅ID
     * @param masterMemberId 主师傅ID
     * @param teamRete       团队抽成比例
     * @param teamMoney      团队抽成金额
     * @param deptRate       平台抽成比例
     * @param deptMoney      平台抽成金额
     * @return 改价金额
     * @throws BaseAdaPayException AdaPay分账接口可能抛出的异常
     */
    private BigDecimal changePaymentConfirm(FinancialChangeRecord fcRecord, Long orderDetailId, Long workerId, Long deptId,
                                            String memberId, String masterMemberId, BigDecimal teamRete, BigDecimal teamMoney,
                                            BigDecimal deptRate, BigDecimal deptMoney,
                                            BigDecimal oneRate, String placeOne, BigDecimal twoRate, String placeTwo,BigDecimal retainRate) throws BaseAdaPayException {
        BigDecimal changeMoney = fcRecord.getChangeMoney();
        // 分销金额
        BigDecimal placeOneMoney = BigDecimal.ZERO;
        BigDecimal placeTwoMoney = BigDecimal.ZERO;
        // 平台抽成
        BigDecimal platformFee = changeMoney.multiply(deptRate).add(deptMoney).setScale(2, RoundingMode.DOWN);
        // 大师傅抽成
        BigDecimal masterFee = changeMoney.multiply(teamRete).add(teamMoney).setScale(2, RoundingMode.DOWN);
        BigDecimal retainRateMoney=BigDecimal.ZERO;

        // 如果提成>追加金额 则去掉固定提成 只计算比例提成
        if (MoneyUtil.lt(masterFee.add(platformFee), changeMoney)) {
            platformFee = changeMoney.multiply(deptRate).setScale(2, RoundingMode.DOWN);
        }
        // 分销抽成
        // 1级分销
        if (MoneyUtil.lt(oneRate, changeMoney)) {
            placeOneMoney = changeMoney.multiply(oneRate).setScale(2, RoundingMode.DOWN);
        }
        // 2级分销
        if (MoneyUtil.lt(twoRate, changeMoney)) {
            placeTwoMoney = changeMoney.multiply(twoRate).setScale(2, RoundingMode.DOWN);
        }
        if (MoneyUtil.lt(retainRate, changeMoney)) {
            retainRateMoney = changeMoney.multiply(retainRate).setScale(2, RoundingMode.DOWN);
        }

        logger.info("子订单改价分账1级{}2级{}", placeOneMoney, placeTwoMoney);
        // 上门师傅的报酬
        BigDecimal workerFee = changeMoney;
        BigDecimal fineMoney = BigDecimal.ZERO;
        // 查询师傅的超时扣款记录
        List<OrderTimeoutRecord> fineRecords = orderFineRecordMapper.selectUnFine(workerId, deptId);
        ArrayList<Long> fineIds = new ArrayList<>();
        for (OrderTimeoutRecord fineRecord : fineRecords) {
            // 抵扣超时罚金 这里的罚金是按创建时间升序排列的 优先抵扣最早的罚金
            if (MoneyUtil.lt(fineMoney.add(fineRecord.getPayMoney()), workerFee)) {
                // 加价单金额不足以抵扣罚金
                logger.info("子订单[{}]的加价单[{}]不足以抵扣罚金{}元", orderDetailId, fcRecord.getId(), fineRecord.getPayMoney());
                break;
            } else {
                // 抵扣罚金
                logger.info("子订单[{}]的加价单[{}]抵扣罚金{}元", orderDetailId, fcRecord.getId(), fineRecord.getPayMoney());
                fineMoney = fineMoney.add(fineRecord.getPayMoney());
                // 被抵扣的罚金记录ID先存下来，分账成功后修改状态
                fineIds.add(fineRecord.getId());
            }
        }
        // 扣除罚金后的上门师傅报酬
//        workerFee = workerFee.subtract(fineMoney);
        // 平台抽成 + 超时罚金
//        platformFee = platformFee.add(fineMoney);
        ArrayList<DivMember> divMembers = new ArrayList<>();
        // 承担手续费的标志 如果平台抽成为0则大师傅承担手续费 如果大师傅抽成也为0 则由上门师傅自己承担手续费
        boolean feeFlag = false;
        if (MoneyUtil.gt0(platformFee)&&MoneyUtil.gt0(retainRate)){
            divMembers.add(new DivMember("0", MoneyUtil.toS(platformFee.add(retainRateMoney)), true));
            workerFee = workerFee.subtract(platformFee).subtract(retainRateMoney);
            feeFlag = true;
        }else{
            if (MoneyUtil.gt0(platformFee)) {
                divMembers.add(new DivMember("0", MoneyUtil.toS(platformFee), true));
                workerFee = workerFee.subtract(platformFee);
                feeFlag = true;
            }
            //截留扣点
            if (MoneyUtil.gt0(retainRate)) {
                divMembers.add(new DivMember("0", MoneyUtil.toS(retainRateMoney), false));
                workerFee = workerFee.subtract(retainRateMoney);
                feeFlag = true;
            }
        }

        if (MoneyUtil.gt0(placeOneMoney) && StringUtils.isNotEmpty(placeOne)) {
            divMembers.add(new DivMember(placeOne, MoneyUtil.toS(placeOneMoney), !feeFlag));
            workerFee = workerFee.subtract(placeOneMoney);
        }
        if (MoneyUtil.gt0(placeTwoMoney) && StringUtils.isNotEmpty(placeTwo)) {
            divMembers.add(new DivMember(placeTwo, MoneyUtil.toS(placeTwoMoney), !feeFlag));
            workerFee = workerFee.subtract(placeTwoMoney);
        }
        //子师傅的费用计算
        BigDecimal detailFee = BigDecimal.ZERO;

        logger.info("大师傅初始金额{}平台费用{}团队抽成金额{}", masterFee, platformFee, teamMoney);
        // 如果是大师傅自己接单,则不需要抽成
        if (AdapayUtils.getWorkerMemberId(workerId, deptId).equals(masterMemberId)) {
            masterFee = BigDecimal.ZERO;
        } else {
            if (MoneyUtil.gt0(workerFee)) {
                detailFee = workerFee.multiply(BigDecimal.ONE.subtract(teamRete)).setScale(2, RoundingMode.DOWN);
                divMembers.add(new DivMember(memberId, MoneyUtil.toS(detailFee), !feeFlag));
            }
            masterFee = workerFee.subtract(detailFee);
            if (MoneyUtil.gt0(masterFee)) {
                divMembers.add(new DivMember(masterMemberId, MoneyUtil.toS(masterFee), !feeFlag));
            }
        }
        logger.info("子师傅的费用{}子师傅抽成比例{}", detailFee, BigDecimal.ONE.subtract(teamRete));
        String orderNo = "FCR_" + fcRecord.getId() + "_" + System.currentTimeMillis();
        //调用分账
        logger.info("子订单[{}]的[改价单]发起分账", orderDetailId);
        JSONObject response = adapayService.paymentConfirm(deptId, fcRecord.getPaymentId(), orderNo, MoneyUtil.toS(fcRecord.getChangeMoney()), divMembers, null, null);
        logger.info("子订单[{}]的[改价单]分账结果: {}", orderDetailId, response.toString());
        if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) { // 分账成功
            logger.info("子订单[{}]的[改价单]分账成功", orderDetailId);
            // 分账成功 把罚金状态改为已扣除
            fineIds.forEach(fineRecordId -> orderFineRecordMapper.updateFineStatus(fineRecordId, 1));
            //获取当前订单的 一级 二级分销
            drawCash(orderDetailId, deptId, placeOne, AdapayUtils.bigDecimalToString(placeOneMoney));
            drawCash(orderDetailId, deptId, placeTwo, AdapayUtils.bigDecimalToString(placeTwoMoney));
            drawCash(orderDetailId, deptId, memberId, AdapayUtils.bigDecimalToString(detailFee));
            drawCash(orderDetailId, deptId, masterMemberId, AdapayUtils.bigDecimalToString(masterFee));
        } else { // 分账失败
            if (AdapayErrorCode.CONFIRM_AMT_OVER_LIMIT.equals(response.getString("error_code"))) {
                // 当前确认金额 > 支付金额 - 已支付确认金额 - 已支付撤销金额
                // 这里有两种可能 1.可能是之前算错了手续费的旧订单
                // 2.可能是之前执行过完单流程 改价单分账成功了 但是子财务单分账失败了
                // 所以直接跳过
                logger.info("子订单[{}] 跳过[改价单]分账 : CONFIRM_AMT_OVER_LIMIT", orderDetailId);
            } else {
                logger.error("子订单[{}]的[改价单 paymentId={}]分账失败: {}", orderDetailId, fcRecord.getRemark(), response.toJSONString());
                // 其它错误抛异常
                throw new IllegalArgumentException(response.getString("error_msg"));
            }
        }
        return detailFee;
    }

    private void attachPaymentConfirm(OrderAttachmentRecord orderAttachmentRecord, Long orderDetailId, Long workerId, Long deptId, String customerId) throws BaseAdaPayException {
        BigDecimal attachMoney = orderAttachmentRecord.getAttachMoney();
        // 扣除罚金后的上门师傅报酬
//        workerFee = workerFee.subtract(fineMoney);
        // 平台抽成 + 超时罚金
//        platformFee = platformFee.add(fineMoney);
        ArrayList<DivMember> divMembers = new ArrayList<>();
        // 承担手续费的标志 如果平台抽成为0则大师傅承担手续费 如果大师傅抽成也为0 则由上门师傅自己承担手续费

        boolean feeFlag = false;
        BigDecimal one = null;
        if (MoneyUtil.gt0(attachMoney)) {
            BigDecimal rate = BigDecimal.valueOf(0.99);
            one = attachMoney.multiply(rate).setScale(2, RoundingMode.DOWN);
            divMembers.add(new DivMember(customerId, MoneyUtil.toS(one), false));
            divMembers.add(new DivMember("0", MoneyUtil.toS(attachMoney.subtract(one)), true));
            logger.info("子订单[{}]的[附件费]提现金额", one);
            feeFlag = true;
        }
        String orderNo = "FCR_" + orderAttachmentRecord.getId() + "_" + System.currentTimeMillis();
        //调用分账
        logger.info("子订单[{}]的[附件费]发起分账", orderDetailId);
        JSONObject response = adapayService.paymentConfirm(deptId, orderAttachmentRecord.getPaymentId(), orderNo, MoneyUtil.toS(attachMoney), divMembers, null, null);
        logger.info("子订单[{}]的[附件费]分账结果: {}", orderDetailId, response.toString());
        if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) { // 分账成功
            logger.info("子订单[{}]的[附件费]分账成功", orderDetailId);
            logger.info("子订单[{}]的[附件费]提现金额", one);
            if (feeFlag) {
                drawCash(orderDetailId, deptId, customerId, AdapayUtils.bigDecimalToString(one));
            }
        } else { // 分账失败
            if (AdapayErrorCode.CONFIRM_AMT_OVER_LIMIT.equals(response.getString("error_code"))) {
                // 当前确认金额 > 支付金额 - 已支付确认金额 - 已支付撤销金额
                // 这里有两种可能 1.可能是之前算错了手续费的旧订单
                // 2.可能是之前执行过完单流程 改价单分账成功了 但是子财务单分账失败了
                // 所以直接跳过
                logger.info("子订单[{}] 跳过[附件费]分账 : CONFIRM_AMT_OVER_LIMIT", orderDetailId);
            } else {
                logger.error("子订单[{}]的[附件费 paymentId={}]分账失败: {}", orderDetailId, orderAttachmentRecord.getPaymentId(), response.toJSONString());
                // 其它错误抛异常
                throw new IllegalArgumentException(response.getString("error_msg"));
            }
        }
    }

    /**
     * 订单追加分账
     *
     * @param orderDetailId  子订单ID
     * @param deptId         企业ID
     * @param memberId       子师傅ID
     * @param masterMemberId 主师傅ID
     * @param teamRete       团队抽成比例
     * @param teamMoney      团队抽成金额
     * @param pcDeptRate     平台抽成比例
     * @param pcDeptMoney    平台抽成金额
     * @throws BaseAdaPayException AdaPay分账接口可能抛出的异常
     */
    private BigDecimal addPaymentConfirm(Long orderDetailId, Long deptId, String memberId, String masterMemberId,
                                         BigDecimal teamRete, BigDecimal teamMoney, BigDecimal pcDeptRate, BigDecimal pcDeptMoney,
                                         BigDecimal oneRate, String placeOne, BigDecimal twoRate, String placeTwo) throws BaseAdaPayException {
        BigDecimal dtx = BigDecimal.ZERO;
        List<OrderAddSubtract> oasList = orderAddSubtractMapper.select(new OrderAddSubtract()
                .setOrderDetailId(orderDetailId).setPayStatus(PayStatus.PAID.getCode()));
        List<OrderAddSubtract> adds = oasList.stream().filter(oas -> MoneyUtil.gt0(oas.getMoney())).collect(Collectors.toList());
        for (OrderAddSubtract oas : adds) {
            BigDecimal placeOneMoney = BigDecimal.ZERO;
            BigDecimal placeTwoMoney = BigDecimal.ZERO;

            BigDecimal oasMoney = oas.getMoney();
            // 平台抽成
            BigDecimal platformFee = oasMoney.multiply(pcDeptRate).add(pcDeptMoney).setScale(2, RoundingMode.DOWN);
            logger.info("平台抽成{}", platformFee);
            // 大师傅抽成
            BigDecimal masterFee = oasMoney.multiply(teamRete).add(teamMoney).setScale(2, RoundingMode.DOWN);
            // 如果提成>追加金额 则去掉固定提成 只计算比例提成
            if (MoneyUtil.lt(masterFee.add(platformFee), oasMoney)) {
                platformFee = oasMoney.multiply(pcDeptRate).setScale(2, RoundingMode.DOWN);
                masterFee = oasMoney.multiply(teamRete).setScale(2, RoundingMode.DOWN);
            }
            // 分销抽成
            // 1级分销
            if (MoneyUtil.lt(oneRate, oasMoney)) {
                placeOneMoney = oasMoney.multiply(oneRate).setScale(2, RoundingMode.DOWN);
            }
            logger.info("1级分销{}", placeOneMoney);
            // 2级分销
            if (MoneyUtil.lt(twoRate, oasMoney)) {
                placeTwoMoney = oasMoney.multiply(twoRate).setScale(2, RoundingMode.DOWN);
            }
            logger.info("2级分销{}", placeTwoMoney);
            // 如果是大师傅自己接单,则不需要抽成
            if (memberId.equals(masterMemberId)) {
                masterFee = BigDecimal.ZERO;
            }
            // 上门师傅的报酬
            BigDecimal workerFee = oasMoney.subtract(platformFee).subtract(masterFee);
            // 分账信息
            ArrayList<DivMember> divMembers = new ArrayList<>();
            // 承担手续费的标志 如果平台抽成为0则大师傅承担手续费 如果大师傅抽成也为0 则由上门师傅自己承担手续费
            boolean feeFlag = false;
            if (MoneyUtil.gt0(platformFee)) {
                divMembers.add(new DivMember("0", MoneyUtil.toS(platformFee), true));
                feeFlag = true;
            }
            logger.info("平台抽成后{}", divMembers);
            if (MoneyUtil.gt0(masterFee)) {
                divMembers.add(new DivMember(masterMemberId, MoneyUtil.toS(masterFee), !feeFlag));
                feeFlag = true;
            }
            logger.info("大师傅抽成后{}", divMembers);
            if (MoneyUtil.gt0(workerFee)) {
                divMembers.add(new DivMember(memberId, MoneyUtil.toS(workerFee), !feeFlag));
                dtx = dtx.add(workerFee);
            }
            logger.info("工费抽成后{}，dtx{}", divMembers, dtx);
            if (StringUtils.isNotEmpty(placeOne)) {
                divMembers.add(new DivMember(placeOne, MoneyUtil.toS(placeOneMoney), !feeFlag));
                dtx = dtx.add(placeOneMoney);
            }
            logger.info("第一次分成{}，dtx{}", divMembers, dtx);
            if (StringUtils.isNotEmpty(placeTwo)) {
                divMembers.add(new DivMember(placeTwo, MoneyUtil.toS(placeTwoMoney), !feeFlag));
                dtx = dtx.add(placeTwoMoney);
            }
            logger.info("第二次分成{}，dtx{}", divMembers, dtx);
            String orderNo = "OAS_" + oas.getId() + "_" + System.currentTimeMillis();
            //调用分账
            logger.info("子订单[{}]的追加单[{}]发起分账: {}", orderDetailId, oas.getId(), JSON.toJSONString(divMembers));
            JSONObject response = adapayService.paymentConfirm(deptId, oas.getPaymentId(),
                    orderNo, MoneyUtil.toS(oasMoney), divMembers, null, null);
            logger.info("子订单[{}]的追加单[{}]分账结果: {}", orderDetailId, oas.getId(), response.toString());
        }
        return dtx;
    }

    /**
     * 子订单分账后提现
     *
     * @param orderDetailId 子订单ID
     * @param deptId        企业ID
     * @param memberId      Adapay用户ID
     * @param cashAmt       提现金额
     */
    private void drawCash(Long orderDetailId, Long deptId, String memberId, String cashAmt) {
        String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
        JSONObject drawCashResponse;
        try {
            drawCashResponse = adapayService.drawCash(deptId, orderNo, "T1",
                    cashAmt, memberId, "订单结算", null);
        } catch (BaseAdaPayException e) {
            logger.error("自动发起提现失败: 子订单id={}, deptId={}", orderDetailId, cashAmt);
            return;
        }
        boolean drawCashStatus = AdapayStatusEnum.pending.code.equals(drawCashResponse.getString("status")) ||
                AdapayStatusEnum.succeeded.code.equals(drawCashResponse.getString("status"));
        if (drawCashStatus) {
            // 提现成功
            logger.info("子订单[id={}]自动提现成功", orderDetailId);
            // 修改订单状态
            OrderDetail odUpdate = new OrderDetail();
            odUpdate.setId(orderDetailId);
            odUpdate.setDrawCashTime(new Date());
            odUpdate.setDrawCashStatus(1);
            // 保存提现ID 用于同步Adapay提现状态
            odUpdate.setDrawCashId(drawCashResponse.getString("id"));
            orderDetailMapper.updateOrderDetail(odUpdate);
        } else {
            // 提现失败 把信息记录到error日志里
            logger.error("自动发起提现失败: 子订单id={}, deptId={} 失败信息: {}", orderDetailId, cashAmt, drawCashResponse.toJSONString());
        }
    }

    @Override
    public Long countOrderDetailList(OrderDetail orderDetail) {
        return orderDetailMapper.countOrderDetailList(orderDetail);
    }

    @Override
    public Long selectOrderDetailCount(OrderDetail orderDetail) {
        return orderDetailMapper.selectOrderDetailCount(orderDetail);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int changePrice(Long orderDetailId, BigDecimal changeMoney, Integer type, String remark,String urls ,String fileNames,String reason) throws
            Exception {
        OrderDetail orderDetail = orderDetailMapper.selectById(orderDetailId);
        if (orderDetail == null) {
            throw new BaseException("子单不存在!");
        }
        // 主单
        OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
        // 主师傅
        Worker workerMaster = workerService.selectById(orderMaster.getWorkerId());
        // 三级类目
        List<OrderGoods> orderGoods = orderGoodsService.selectByOrderDetailId(orderDetailId);
        if (CollectionUtils.isEmpty(orderGoods)) {
            throw new BaseException("找不到子订单对应的商品");
        }

        Long goodsStandardId = orderGoods.get(0).getGoodsStandardId();
        GoodsStandard goodsStandard = goodsStandardService.selectById(goodsStandardId);
        // 第四级规格
        DeptGoodsCategory childCategory = deptGoodsCategoryService.get(goodsStandard.getDeptGoodsCategoryId());
        // 需要找第三级规格
        DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(childCategory.getParentCategoryId());

        FinancialChangeRecord param = new FinancialChangeRecord();
        param.setPayStatus(0);
        param.setOrderDetailId(orderDetailId);
        List<FinancialChangeRecord> list = financialChangeRecordService.selectFinancialChangeRecordList(param);
        FinancialChangeRecord financialChangeRecord;
        int affectedRows = 0;
        if (changeMoney.compareTo(BigDecimal.ZERO) == 0) {
            // 入参中的加价金额为空则直接删除未支付的加价记录
            if (list.size() > 0) {
                financialChangeRecord = list.get(0);
                affectedRows = financialChangeRecordService.deleteFinancialChangeRecordById(financialChangeRecord.getId());
            }
        } else if (list.size() > 0) {
            // 修改现有
            financialChangeRecord = list.get(0);
            financialChangeRecord.setChangeMoney(changeMoney);
            financialChangeRecord.setType(type);
            financialChangeRecord.setRemark(remark);
            financialChangeRecord.setUrls(urls);
            financialChangeRecord.setFileNames(fileNames);
            financialChangeRecord.setReason(reason);
            this.buildSettle(financialChangeRecord, deptGoodsCategory, workerMaster);
            affectedRows = financialChangeRecordService.update(financialChangeRecord);
        } else {
            // 创建改单记录
            financialChangeRecord = new FinancialChangeRecord();
            financialChangeRecord.setOrderDetailId(orderDetailId);
            financialChangeRecord.setOrderMasterId(orderDetail.getOrderMasterId());
            financialChangeRecord.setChangeMoney(changeMoney);
            financialChangeRecord.setStatus(0);
            financialChangeRecord.setPayStatus(0);
            financialChangeRecord.setType(type);
            financialChangeRecord.setRemark(remark);
            financialChangeRecord.setUrls(urls);
            financialChangeRecord.setFileNames(fileNames);
            financialChangeRecord.setReason(reason);
            this.buildSettle(financialChangeRecord, deptGoodsCategory, workerMaster);
            affectedRows = financialChangeRecordService.insert(financialChangeRecord);
        }
        if (changeMoney.compareTo(BigDecimal.ZERO) != 0 && affectedRows != 1) {
            throw new Exception("加价记录新增或者修改失败");
        }

        return affectedRows;
    }

    /**
     * <p>构建各分销所得金额</p>
     *
     * @param deptGoodsCategory     三级类目，用来计算扣点
     * @param financialChangeRecord 加价记录
     */
    private void buildSettle(FinancialChangeRecord financialChangeRecord, DeptGoodsCategory deptGoodsCategory, Worker workerMaster) {
        // 一级分销追加扣点
        BigDecimal saleRateOne = new BigDecimal(deptGoodsCategory.getOneRate());
        saleRateOne = MoneyUtil.lt0(saleRateOne) ? BigDecimal.ZERO : saleRateOne;
        BigDecimal saleOneMoney = financialChangeRecord.getChangeMoney().multiply(saleRateOne);
        financialChangeRecord.setOneMoney(saleOneMoney);

        // 二级分销追加扣点
        BigDecimal saleRateTwo = new BigDecimal(deptGoodsCategory.getTwoRate());
        saleRateTwo = MoneyUtil.lt0(saleRateTwo) ? BigDecimal.ZERO : saleRateTwo;
        BigDecimal saleTwoMoney = financialChangeRecord.getChangeMoney().multiply(saleRateTwo);
        financialChangeRecord.setTwoMoney(saleTwoMoney);

        // 三级分销追加扣点
        BigDecimal saleRateThree = new BigDecimal(deptGoodsCategory.getThreeRate());
        saleRateThree = MoneyUtil.lt0(saleRateThree) ? BigDecimal.ZERO : saleRateThree;
        BigDecimal saleThreeMoney = financialChangeRecord.getChangeMoney().multiply(saleRateThree);
        financialChangeRecord.setThreeMoney(saleThreeMoney);


        // 平台加价抽成
        BigDecimal deptRate = new BigDecimal(deptGoodsCategory.getDeptRate());
        deptRate = MoneyUtil.lt0(deptRate) ? BigDecimal.ZERO : deptRate;
        BigDecimal deptMoney = MoneyUtil.lt0(deptGoodsCategory.getDeptMoney()) ? BigDecimal.ZERO : deptGoodsCategory.getDeptMoney();
        BigDecimal deptChangeMoney = deptMoney.add(financialChangeRecord.getChangeMoney().multiply(deptRate));
        financialChangeRecord.setDeptMoney(deptChangeMoney);

        // 大师傅提成
        BigDecimal teamRete = new BigDecimal(workerMaster.getLeaderTeamRate());
        teamRete = MoneyUtil.lt0(teamRete) ? BigDecimal.ZERO : teamRete;
        BigDecimal teamMoney = new BigDecimal(workerMaster.getLeaderTeamMoney());
        teamMoney = MoneyUtil.lt0(teamMoney) ? BigDecimal.ZERO : teamMoney;

        //截留扣点
        BigDecimal retainRate = new BigDecimal(deptGoodsCategory.getRetainRate());
        retainRate = MoneyUtil.lt0(retainRate) ? BigDecimal.ZERO : retainRate;
        BigDecimal retainMoney = financialChangeRecord.getChangeMoney().multiply(retainRate).setScale(2, RoundingMode.DOWN);


        BigDecimal  endMoney=financialChangeRecord.getChangeMoney().subtract(saleOneMoney)
                .subtract(saleTwoMoney).subtract(saleThreeMoney).subtract(deptChangeMoney).subtract(retainMoney);
        BigDecimal workerMoney=endMoney.multiply(BigDecimal.ONE.subtract(teamRete)).setScale(2, RoundingMode.DOWN);
        BigDecimal leaderMoney = endMoney.subtract(workerMoney).add(teamMoney);
        logger.info("截留扣点{}截留扣点金额{}减去所有返点的金额{}大师傅的金额{}子师傅的金额{}子师傅的费率{}",retainRate,retainMoney,endMoney,leaderMoney,workerMoney,BigDecimal.ONE.subtract(teamRete));

        financialChangeRecord.setLeaderMoney(leaderMoney);

        // 截留扣点 暂不需要
        BigDecimal pcDeptRate = new BigDecimal(deptGoodsCategory.getPcDeptRate());
        pcDeptRate = MoneyUtil.lt0(pcDeptRate) ? BigDecimal.ZERO : pcDeptRate;
        BigDecimal pcDeptMoney = MoneyUtil.lt0(deptGoodsCategory.getPcDeptMoney()) ? BigDecimal.ZERO : deptGoodsCategory.getPcDeptMoney();
        BigDecimal deptAddMoney = financialChangeRecord.getChangeMoney().multiply(pcDeptRate).add(pcDeptMoney);
        financialChangeRecord.setDeptAddMoney(deptAddMoney);

        // 师傅剩余服务金额
        financialChangeRecord.setWorkerMoney(workerMoney);

    }

    @Override
    public int sureChange(Long financialChangeRecordId) {
        return 0;
    }

    @Override
    public FinancialChangeRecord getChangedPriceRecord(Long orderDetailId) {
        FinancialChangeRecord param = new FinancialChangeRecord();
        param.setOrderDetailId(orderDetailId);
        List<FinancialChangeRecord> list = financialChangeRecordService.selectFinancialChangeRecordList(param);
        if (!CollectionUtils.isEmpty(list)) {
            FinancialChangeRecord financialChangeRecord=list.get(0);
            OrderAttachmentRecord orderAttachmentRecord = new OrderAttachmentRecord();
            orderAttachmentRecord.setFinancialChangeRecordId(financialChangeRecord.getId());
            List<OrderAttachmentRecord> orderAttachmentRecordList = orderAttachmentRecordService.selectOrderAttachmentRecordList(orderAttachmentRecord);
            if (CollectionUtils.isNotEmpty(orderAttachmentRecordList)) {
                financialChangeRecord.setAttachmentMoney(orderAttachmentRecordList.get(0).getAttachMoney());
            }
            logger.info("加价的配件费订单{}加价id{}",orderAttachmentRecordList,financialChangeRecord.getId());
            return financialChangeRecord;
        }
        return null;
    }

    @Override
    public List<OrderStatusCount> statusCount() {
        return orderDetailMapper.statusCount();
    }

    @Override
    public int updateDrawCashStatus(String drawCashId, int drawCashStatus, Date drawCashTime, Date arrivalTime) {
        return orderDetailMapper.updateDrawCashStatus(drawCashId, drawCashStatus, drawCashTime, arrivalTime);
    }

    @Override
    public void refundSucceeded(String reverseId) {
        financialDetailService.refundSucceeded(reverseId);
    }

    @Override
    public int updateStatus(Long id, int status) {
        for (OrderStatus os : OrderStatus.values()) {
            if (status == os.code()) {
                return orderDetailMapper.updateStatus(id, status);
            }
        }
        throw new IllegalArgumentException("Unknown OrderStatus: " + status);
    }

    @Override
    public int updateTimeout(Long id, int timeout, int timeoutFineTimes) {
        return orderDetailMapper.updateTimeout(id, timeout, timeoutFineTimes);
    }

    @Override
    public int updateAfterTimeout(Long id, int timeout, int timeoutFineTimes) {
        return orderDetailMapper.updateAfterTimeout(id, timeout, timeoutFineTimes);
    }

    @Override
    public int deleteByMaster(Long masterId) {
        return orderDetailMapper.deleteByMaster(masterId);
    }

    @Override
    public int insertOrderAddSubtract(OrderAddSubtract body) {
        Assert.notNull(body.getOrderDetailId(), "订单id不能为空");
        OrderDetail orderDetail = orderDetailMapper.selectById(body.getOrderDetailId());
        Assert.notNull(orderDetail, "订单不存在");

        boolean unFinish = ZERO.equals(orderDetail.getDrawCashStatus()) &&
                OrderStatus.FINISH_CHECK.code() != orderDetail.getOrderStatus() &&
                OrderStatus.FINISH.code() != orderDetail.getOrderStatus();
        Assert.isTrue(unFinish, "订单已经完成，不能再做追加扣减操作");

        boolean unCancel = OrderStatus.CANCEL.code() != orderDetail.getOrderStatus();
        Assert.isTrue(unCancel, "订单已经取消，不能再做追加扣减操作");

        Assert.isTrue(BigDecimal.ZERO.compareTo(body.getMoney()) != 0, "金额不能为0");

        FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(orderDetail.getId());
        Assert.notNull(financialDetail, "找不到财务单");

        // 可用派单金额 = 财务单金额 - 已支付的加价记录 - 已支付的追加记录
        BigDecimal paiDanMoney = financialDetail.getPayMoney();

        // 已支付的加价记录
        List<FinancialChangeRecord> paidChangeRecords = financialChangeRecordService.selectByDetailIds(orderDetail.getId().toString())
                .stream().filter(x -> x.getPayStatus() == 1).collect(Collectors.toList());
        for (FinancialChangeRecord record : paidChangeRecords) {
            paiDanMoney = paiDanMoney.subtract(record.getChangeMoney());
        }

        // 已支付的追加记录
        List<OrderAddSubtract> orderAdds = orderAddSubtractMapper.select(new OrderAddSubtract()
                .setOrderDetailId(orderDetail.getId()).setPayStatus(PayStatus.PAID.getCode()));
        for (OrderAddSubtract oas : orderAdds) {
            if (MoneyUtil.gt0(oas.getMoney())) {
                paiDanMoney = paiDanMoney.subtract(oas.getMoney());
            }
        }

        // 如果这是扣减操作
        if (MoneyUtil.lt0(body.getMoney())) {
            // 扣减金额不能超过派单金额
            Assert.isTrue(MoneyUtil.gte0(paiDanMoney.add(body.getMoney())), "扣减金额不能超过派单金额");
        }

        // 保存扣减记录
        OrderAddSubtract insert = new OrderAddSubtract();
        insert.setOrderMasterId(orderDetail.getOrderMasterId());
        insert.setOrderDetailId(orderDetail.getId());
        insert.setMoney(body.getMoney());
        insert.setRemark(body.getRemark());
        insert.setCreateBy(body.getCreateBy());
        insert.setPayType(body.getPayType());
        return orderAddSubtractMapper.insert(insert);
    }

    @Override
    public OrderDetailCount differentStatusOrderCount(OrderDetail orderDetail) {
        return orderDetailMapper.differentStatusOrderCount(orderDetail);
    }

    @Override
    public Long afterDetailOrderCount(OrderDetail orderDetail) {
        AfterServiceRecord afterServiceRecord = new AfterServiceRecord();
        afterServiceRecord.setExcludeAfterServiceFinished(Boolean.TRUE);
        List<AfterServiceRecord> afterServiceRecordList = afterServiceRecordService.selectAfterServiceRecordList(afterServiceRecord);
        // 踢重后的子单ids
        List<Long> detailIds = afterServiceRecordList.stream().map(AfterServiceRecord::getOrderDetailId).distinct().collect(Collectors.toList());
        String ids = StringUtils.join(detailIds, ",");
        if (StringUtils.isNotEmpty(ids)) {
            orderDetail.setOrderDetailIds(ids);
        } else {
            orderDetail.setOrderDetailIds("0");
        }
        return this.countOrderDetailList(orderDetail);
    }

    @Override
    public OrderDetailStatisticsDTO orderStatisticsReturn() {
        return statisticsDTO;
    }

    @Override
    public OrderDetailStatisticsDTO orderStatisticsDispose() {
        // 拿到当前时间
        Long time = System.currentTimeMillis();
        // 根据时间返回查询
        List<OrderDetail> orderDetails = orderDetailMapper.searchByOrderStartTime(DateUtils.getDayStartTime(time), DateUtils.getDayEndTime(time));
        // 订单数据统计
        if (orderDetails != null && !orderDetails.isEmpty()) {
            // 根据map数据进行数据分类处理 根据订单状态类型进行数据分类处理。
            Map<Integer, List<OrderDetail>> masterOrderMap = orderDetails.stream().collect(Collectors.groupingBy(OrderDetail::getOrderStatus));
            // 循环订单状态类型进行状态类型   switch进行归类处理。
            for (Integer orderStateKey : masterOrderMap.keySet()) {
                /**
                 * 0.待接单 1.待排期 2.待上门 3.服务中 4.已完成 5.已取消
                 */
                switch (orderStateKey) {
                    case 0:
                        statisticsDTO.setPendingOrderNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 1:
                        statisticsDTO.setWaitingDateNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 2:
                        statisticsDTO.setWaitSeeNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 3:
                        statisticsDTO.setInServiceNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 4:
                        statisticsDTO.setCompletedNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 5:
                        statisticsDTO.setCanceledNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    default:
                        break;
                }
            }
            // 总数
            statisticsDTO.setTotalOrderNumber(orderDetails.size());
        }
        return statisticsDTO;
    }

    @Override
    public OrderDetailStatisticsDTO orderStatisticsReturnByNow() {
        return statisticsDTOByNow;
    }

    @Override
    public OrderDetailStatisticsDTO orderStatisticsDisposeByNow() {
        // 拿到当前时间
        Long time = System.currentTimeMillis();
        // 根据时间返回查询
        List<OrderDetail> orderDetails = orderDetailMapper.searchByOrderStartTime(DateUtils.getDayStartTime(time), DateUtils.getDayEndTime(time));
        // 订单数据统计
        if (orderDetails != null && !orderDetails.isEmpty()) {
            // 根据map数据进行数据分类处理 根据订单状态类型进行数据分类处理。
            Map<Integer, List<OrderDetail>> masterOrderMap = orderDetails.stream().collect(Collectors.groupingBy(OrderDetail::getOrderStatus));
            // 循环订单状态类型进行状态类型   switch进行归类处理。
            for (Integer orderStateKey : masterOrderMap.keySet()) {
                /**
                 * 0.待接单 1.待排期 2.待上门 3.服务中 4.已完成 5.已取消
                 */
                switch (orderStateKey) {
                    case 0:
                        statisticsDTOByNow.setPendingOrderNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 1:
                        statisticsDTOByNow.setWaitingDateNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 2:
                        statisticsDTOByNow.setWaitSeeNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 3:
                        statisticsDTOByNow.setInServiceNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 4:
                        statisticsDTOByNow.setCompletedNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    case 5:
                        statisticsDTOByNow.setCanceledNumber(masterOrderMap.get(orderStateKey).size());
                        break;
                    default:
                        break;
                }
            }
            // 总数
            statisticsDTOByNow.setTotalOrderNumber(orderDetails.size());
        }
        return statisticsDTOByNow;
    }
    @Override
    public int delayOrder(Long orderMasterId) {

        List<OrderDetail> orderDetailList=orderDetailMapper.selectByOrderMasterId(orderMasterId);
        int num=0;
        for (OrderDetail orderDetail:orderDetailList){
            // 查询订单信息
            if (orderDetail == null) {
                throw new BaseException("订单不存在");
            }

            // 检查延期次数
            Integer delayCount = orderDetail.getDelayCount();
            if (delayCount == null) {
                delayCount = 0;
            }
            if (delayCount >= 2) {
                throw new BaseException("延期次数已达上限，最多只能延期2次");
            }

            // 检查订单状态是否允许延期
            if (orderDetail.getOrderStatus() == null) {
                throw new BaseException("订单状态异常");
            }

            // 更新延期次数
            orderDetail.setDelayCount(delayCount + 1);

            // 处理confirm_start_time，增加3天
            Date confirmStartTime = orderDetail.getConfirmStartTime();
            if (confirmStartTime == null) {
                confirmStartTime = new Date();
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(confirmStartTime);
            calendar.add(Calendar.DAY_OF_MONTH, 3);
            orderDetail.setConfirmStartTime(calendar.getTime());

            // 如果是待确认状态，则变为服务中
            if (OrderStatus.FINISH_CHECK.code()==orderDetail.getOrderStatus()) {
                orderDetail.setOrderStatus(OrderStatus.SERVER.code());
            }

            // 更新订单
            num= orderDetailMapper.updateOrderDetail(orderDetail);
        }
        return  num;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int returnOrder(Long orderDetailId) {
        // 查询订单信息
        OrderDetail orderDetail = orderDetailMapper.selectById(orderDetailId);
        OrderMaster orderMaster=orderMasterMapper.selectById(orderDetail.getOrderMasterId());

        if (orderDetail == null) {
            throw new BaseException("订单不存在");
        }

        // 检查订单状态是否允许退回
        if (orderDetail.getOrderStatus() == null) {
            throw new BaseException("订单状态异常");
        }

        // 根据订单类型决定退回状态
        Integer orderType = orderDetail.getOrderType();
        if (orderType == null) {
            throw new BaseException("订单类型异常");
        }

        // 根据订单类型设置退回状态
        if (orderType == 0) {
            // 服务订单：退回到服务中状态
            orderDetail.setOrderStatus(OrderStatus.SERVER.code());
        } else if (orderType == 1) {
            // 商品订单：退回到待排期状态
            orderDetail.setOrderStatus(OrderStatus.PLAIN.code());
        } else {
            throw new BaseException("不支持的订单类型");
        }

        // 清除超时状态
        orderDetail.setTimeout(0);
        int num= orderDetailMapper.updateOrderDetail(orderDetail);
        List<OrderDetail> orderDetailList=orderDetailMapper.selectByOrderMasterId(orderDetail.getOrderMasterId());
        if (orderMaster.getOrderType()==0){
            Boolean bo= orderDetailList.stream()
                    .allMatch(subOrder ->
                            // 子单状态不为 null 且等于 1
                            Objects.nonNull(subOrder.getOrderStatus()) && subOrder.getOrderStatus() == 3
                    );
            if (bo){
                num= orderMasterMapper.updateStatus(orderMaster.getId(),3);
            }
        }else{
            Boolean bo= orderDetailList.stream()
                    .allMatch(subOrder ->
                            // 子单状态不为 null 且等于 1
                            Objects.nonNull(subOrder.getOrderStatus()) && subOrder.getOrderStatus() == 1
                    );
            if (bo){
                List<Long> idList = new ArrayList<>();
                idList.add(orderDetailId);
                Long[] ids = idList.toArray(new Long[0]);
                OrderMaster orderMaster1=new OrderMaster();
                orderMaster1.setHasDispatchedAll(0);
                orderMaster1.setId(orderMaster.getId());
                orderMaster1.setOrderStatus(1);
                num= orderMasterMapper.updateOrderMaster(orderMaster1);
                orderDetailMapper.deleteOrderDetailByIds(ids);
            }
        }

        return num;
    }

    @Override
    public int saveDetailWorkerRemark(Long orderDetailId, String workerRemark) {
        logger.info("保存子单师傅备注，子单ID：{}，师傅备注：{}", orderDetailId, workerRemark);
        
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setId(orderDetailId);
        orderDetail.setWorkerRemark(workerRemark);
        
        int result = orderDetailMapper.updateOrderDetail(orderDetail);
        logger.info("更新子单师傅备注，子单ID：{}，结果：{}", orderDetailId, result);
        
        return result;
    }

    @Override
    public int updateOrderDetailAddressById(OrderDetail orderDetail) {
        logger.info("更新子单地址信息，子单ID：{}", orderDetail.getId());
        return orderDetailMapper.updateOrderDetail(orderDetail);
    }
}
