package com.yiqi.core.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yiqi.app.domain.AppUserBillMstr;
import com.yiqi.app.service.IAppUserBillMstrService;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.common.utils.CurrencyUtil;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.core.domain.SettlementManageFactory;
import com.yiqi.core.domain.SettlementManageStore;
import com.yiqi.core.domain.dto.SettlementBillAddDTO;
import com.yiqi.core.mapper.SettlementManageStoreMapper;
import com.yiqi.core.service.ISettlementManageFactoryService;
import com.yiqi.core.service.ISettlementManageStoreService;
import com.yiqi.order.domain.*;
import com.yiqi.order.service.*;
import com.yiqi.recharge.domain.RechargePasswordCard;
import com.yiqi.recharge.service.IRechargePasswordCardService;
import com.yiqi.settlement.domain.SettlementFactoryRate;
import com.yiqi.settlement.domain.SettlementStoreRate;
import com.yiqi.settlement.domain.dto.OrderStatisticsVO;
import com.yiqi.settlement.domain.dto.PaymentStatisticsVO;
import com.yiqi.settlement.domain.dto.StoreBillStatistics;
import com.yiqi.settlement.domain.dto.StoreSettlementData;
import com.yiqi.settlement.service.ISettlementFactoryRateService;
import com.yiqi.settlement.service.ISettlementStoreRateService;
import com.yiqi.system.domain.ManageFactory;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.IManageFactoryService;
import com.yiqi.system.service.ISysStoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import com.yiqi.core.mapper.SettlementManageBillMapper;
import com.yiqi.core.domain.SettlementManageBill;
import com.yiqi.core.service.ISettlementManageBillService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

/**
 * 结算管理Service业务层处理
 *
 * @author ruoyi
 * @date 2024-02-15
 */
@Service
@Slf4j
public class SettlementManageBillServiceImpl extends ServiceImpl<SettlementManageBillMapper, SettlementManageBill> implements ISettlementManageBillService {
    @Autowired
    private ISettlementManageFactoryService settlementManageFactoryService;
    @Autowired
    private ISettlementManageStoreService settlementManageStoreService;
    @Autowired
    private SettlementManageStoreMapper settlementManageStoreMapper;
    @Autowired
    private IOrderClothItemService orderClothItemService;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private ISettlementStoreRateService settlementStoreRateService;
    @Autowired
    private IManageFactoryService factoryService;
    @Autowired
    private ISysStoreService storeService;
    @Autowired
    private IRechargePasswordCardService rechargePasswordCardService;
    @Autowired
    private IAppUserBillMstrService appUserBillMstrService;
    @Autowired
    private IOrderPayInfoService orderPayInfoService;
    @Autowired
    private IOrderRefundInfoService orderRefundInfoService;
    @Autowired
    private IOrderClothService orderClothService;
    @Autowired
    private IOrderClothRefundService orderClothRefundService;
    @Autowired
    private IOrderGoodsService orderGoodsService;
    @Autowired
    private IOrderPurchaseGoodsService orderPurchaseGoodsService;
    @Autowired
    private IOrderGoodsRefundService orderGoodsRefundService;
    @Autowired
    private ISettlementFactoryRateService settlementFactoryRateService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertSettlementManageBill(SettlementBillAddDTO settlementBillAddDTO) {
        SettlementManageBill settlementManageBill = this.buildSettlementManageBill(settlementBillAddDTO);
        // 门店结算
        this.handleCountStoreSettlement(settlementManageBill);
        // 工厂结算
        this.handleCountFactorySettlement(settlementManageBill);
        //更新结算单
        SettlementManageStore settlementManageStore = settlementManageStoreMapper.statisticsByBillId(settlementManageBill.getId());
        settlementManageBill.setStoreNum(settlementManageStore.getStoreNum());
        settlementManageBill.setMaterialImprestAmount(settlementManageStore.getMaterialImprestAmount());
        settlementManageBill.setSettlementAmount(settlementManageStore.getSettlementAmount());
        settlementManageBill.setSystemMaintenanceAmount(settlementManageStore.getSystemMaintenanceAmount());
        settlementManageBill.setWashClothAmount(settlementManageStore.getWashClothAmount());
        this.updateById(settlementManageBill);
    }

    private SettlementManageBill buildSettlementManageBill(SettlementBillAddDTO settlementBillAddDTO) {
        Date beginTime = DateUtils.strToDate(settlementBillAddDTO.getMonth() + "-01");
        Date endTime = DateUtils.addDays(DateUtils.addMonths(beginTime, 1), -1);
        //如果存在结算单，则不在生成
        if (this.count(new QueryWrapper<SettlementManageBill>().lambda()
                .eq(SettlementManageBill::getBeginTime, beginTime)
                .eq(SettlementManageBill::getEndTime, endTime)
                .eq(SettlementManageBill::getDelFlag, StatusType.OK.getCode())) > 0) {
            throw new ServiceException("已存在该月份的结算单");
        }
        SettlementManageBill settlementManageBill = new SettlementManageBill();
        settlementManageBill.setBeginTime(beginTime);
        settlementManageBill.setEndTime(endTime);
        settlementManageBill.setTitle(settlementBillAddDTO.getTitle());
        settlementManageBill.buildCreateData();
        settlementManageBill.setStatus(SettlementBillStatusType.WAITING.getCode());
        settlementManageBill.setDelFlag(StatusType.OK.getCode());
        this.save(settlementManageBill);
        return settlementManageBill;
    }

    /**
     * 工厂结算
     *
     * @param settlementManageBill
     * @return
     */
    private void handleCountFactorySettlement(SettlementManageBill settlementManageBill) {
        List<ManageFactory> factoryList = factoryService.list(new QueryWrapper<ManageFactory>().lambda()
                .eq(ManageFactory::getStatus, StatusType.OK.getCode())
                .eq(ManageFactory::getDelFlag, StatusType.OK.getCode()));
        if (CollUtil.isEmpty(factoryList)) {
            return;
        }

        for (ManageFactory factory : factoryList) {
            this.buildFactorySettlement(settlementManageBill, factory);
        }
    }

    @Override
    public StoreBillStatistics storeChargeSettlement(Long storeId, Date startTime, Date endTime) {

        return null;
    }

    /**
     * 门店交易数据汇总
     */
    @Override
    public StoreBillStatistics storeBillSettlement(Long storeId, Date startTime, Date endTime) {
        // 1. 查询洗衣订单
        List<String> orderStatuss = CollUtil.newArrayList(
                ClothOrderStatusType.WAIT_FACTORY.getCode(),
                ClothOrderStatusType.WASHING.getCode(),
                ClothOrderStatusType.HAS_WASH.getCode(),
                ClothOrderStatusType.WAITING_FOR_COMMENT.getCode(),
                ClothOrderStatusType.WAITING_TO_SEND.getCode(),
                ClothOrderStatusType.WAITING_FOR_HANG.getCode(),
                ClothOrderStatusType.SENDING.getCode(),
                ClothOrderStatusType.FINISH.getCode(),
                ClothOrderStatusType.REFUND_SUCCESS.getCode()
        );
        List<OrderCloth> orderClothList = orderClothService.list(new QueryWrapper<OrderCloth>().lambda()
                .in(OrderCloth::getOrderStatus, orderStatuss)
                .eq(OrderCloth::getSourceType, SourceType.STORE.getCode())
                .eq(OrderCloth::getOrgId, storeId)
                .between(OrderCloth::getCreateTime, startTime, endTime));

        // 2. 查询商品订单
        List<OrderGoods> orderGoodsList = orderGoodsService.list(new QueryWrapper<OrderGoods>().lambda()
                .ne(OrderGoods::getOrderStatus, OrderGoodsStatusType.CANCEL_ORDER.getCode())
                .eq(OrderGoods::getSourceType, SourceType.STORE.getCode())
                .eq(OrderGoods::getOrgId, storeId)
                .between(OrderGoods::getCreateTime, startTime, endTime));

        // 3. 查询衣服退款记录
        List<OrderClothRefund> clothRefundList = orderClothRefundService.list(new QueryWrapper<OrderClothRefund>().lambda()
                .eq(OrderClothRefund::getSourceType, SourceType.STORE.getCode())
                .eq(OrderClothRefund::getOrgId, storeId)
                .eq(OrderClothRefund::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                .between(OrderClothRefund::getRefundTime, startTime, endTime));

        // 4. 查询商品退款记录
        List<OrderGoodsRefund> goodsRefundList = orderGoodsRefundService.list(new QueryWrapper<OrderGoodsRefund>().lambda()
                .eq(OrderGoodsRefund::getOrgId, storeId)
                .eq(OrderGoodsRefund::getSourceType, SourceType.STORE.getCode())
                .eq(OrderGoodsRefund::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                .between(OrderGoodsRefund::getRefundTime, startTime, endTime));

        // 5. 统计洗衣订单数据
        OrderStatisticsVO clothStats = calculateClothOrderStats(orderClothList, clothRefundList);

        // 6. 统计商品订单数据
        OrderStatisticsVO goodsStats = calculateGoodsOrderStats(orderGoodsList, goodsRefundList);

        // 7. 汇总支付方式统计
        PaymentStatisticsVO paymentStats = calculatePaymentStats(clothStats, goodsStats);

        // 8. 保存统计结果
        return saveStatisticsResult(storeId, startTime, endTime, clothStats, goodsStats, paymentStats);
    }

    @Override
    public StoreBillStatistics platformBillSettlement(Date startTime, Date endTime) {
        // 1. 查询洗衣订单
        List<OrderCloth> orderClothList = new ArrayList<>();

        // 2. 查询商品订单
        List<OrderGoods> orderGoodsList = orderGoodsService.list(new QueryWrapper<OrderGoods>().lambda()
                .ne(OrderGoods::getOrderStatus, OrderGoodsStatusType.CANCEL_ORDER.getCode())
                .eq(OrderGoods::getSourceType, SourceType.MANAGER.getCode())
                .isNull(OrderGoods::getOrgId)
                .between(OrderGoods::getCreateTime, startTime, endTime));

        // 3. 查询衣服退款记录
        List<OrderClothRefund> clothRefundList = new ArrayList<>();

        // 4. 查询商品退款记录
        List<OrderGoodsRefund> goodsRefundList = orderGoodsRefundService.list(new QueryWrapper<OrderGoodsRefund>().lambda()
                .isNull(OrderGoodsRefund::getOrgId)
                .eq(OrderGoodsRefund::getSourceType, SourceType.MANAGER.getCode())
                .eq(OrderGoodsRefund::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                .between(OrderGoodsRefund::getRefundTime, startTime, endTime));

        // 5. 统计洗衣订单数据
        OrderStatisticsVO clothStats = calculateClothOrderStats(orderClothList, clothRefundList);

        // 6. 统计商品订单数据
        OrderStatisticsVO goodsStats = calculateGoodsOrderStats(orderGoodsList, goodsRefundList);

        // 7. 汇总支付方式统计
        PaymentStatisticsVO paymentStats = calculatePaymentStats(clothStats, goodsStats);

        // 8. 保存统计结果
        return saveStatisticsResult(0L, startTime, endTime, clothStats, goodsStats, paymentStats);
    }


    /**
     * 计算洗衣订单统计数据
     */
    private OrderStatisticsVO calculateClothOrderStats(List<OrderCloth> orderList, List<OrderClothRefund> refundList) {
        OrderStatisticsVO stats = new OrderStatisticsVO();
        stats.setTransactionAmount(BigDecimal.ZERO);
        stats.setTransactionRefundAmount(BigDecimal.ZERO);
        // 1. 订单数量统计
        stats.setOrderCount(orderList.size());
        stats.setGoodsCount(
                orderList.stream()
                        .map(OrderCloth::getOrderClothCount)
                        .filter(Objects::nonNull)
                        .reduce(0, Integer::sum)
        );
        // 2. 交易订单数量统计
        stats.setTransactionCount(orderList.stream()
                .filter(order -> PayStatus.HAS_PAY.getCode().equals(order.getOrderStatus()))
                .count());

        // 2. 订单金额统计
        BigDecimal totalAmount = orderList.stream()
                .map(OrderCloth::getPayAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        stats.setTotalAmount(totalAmount);

        // 3. 支付方式统计
        calculateClothPayTypeAmounts(orderList, stats);
        // 4. 退款方式统计
        calculateClothRefundTypeAmounts(refundList, stats);

        // 5. 退款统计
        Map<String, BigDecimal> refundAmounts = calculateClothRefundAmounts(refundList);
        stats.setRefundCount(refundAmounts.get("count").intValue());
        stats.setRefundAmount(refundAmounts.get("amount"));

        return stats;
    }

    /**
     * 计算商品订单统计数据
     */
    private OrderStatisticsVO calculateGoodsOrderStats(List<OrderGoods> orderList, List<OrderGoodsRefund> refundList) {
        OrderStatisticsVO stats = new OrderStatisticsVO();
        stats.setTransactionAmount(BigDecimal.ZERO);
        stats.setTransactionRefundAmount(BigDecimal.ZERO);

        // 1. 订单数量统计
        stats.setOrderCount(orderList.size());
        stats.setTransactionCount(orderList.stream()
                .filter(order -> PayStatus.HAS_PAY.getCode().equals(order.getPayStatus()))
                .count());
        stats.setGoodsCount(
                orderList.stream()
                        .filter(order -> PayStatus.HAS_PAY.getCode().equals(order.getPayStatus()))
                        .map(OrderGoods::getGoodsCount)
                        .filter(Objects::nonNull)
                        .reduce(0, Integer::sum)
        );

        // 2. 订单金额统计
        BigDecimal totalAmount = orderList.stream()
                .map(OrderGoods::getPayAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        stats.setTotalAmount(totalAmount);

        // 3. 支付方式统计
        calculateGoodsPayTypeAmounts(orderList, stats);

        // 4. 退款方式统计
        calculateGoodsRefundTypeAmounts(refundList, stats);

        // 5. 退款统计
        Map<String, BigDecimal> refundAmounts = calculateGoodsRefundAmounts(refundList);
        stats.setRefundCount(refundAmounts.get("count").intValue());
        stats.setRefundAmount(refundAmounts.get("amount"));

        return stats;
    }

    /**
     * 计算洗衣订单支付方式金额
     */
    private void calculateClothPayTypeAmounts(List<OrderCloth> orderList, OrderStatisticsVO stats) {
        BigDecimal wxPayAmount = BigDecimal.ZERO;
        BigDecimal alipayAmount = BigDecimal.ZERO;
        BigDecimal cashAmount = BigDecimal.ZERO;
        BigDecimal memberAmount = BigDecimal.ZERO;
        BigDecimal unionAmount = BigDecimal.ZERO;
        BigDecimal transactionAmount = BigDecimal.ZERO;
        for (OrderCloth order : orderList) {
            if (PayStatus.HAS_PAY.getCode().equals(order.getPayStatus())) {
                wxPayAmount = CurrencyUtil.add(wxPayAmount, order.getWxPayAmount());
                alipayAmount = CurrencyUtil.add(alipayAmount, order.getAliPayAmount());
                cashAmount = CurrencyUtil.add(cashAmount, order.getCashPayAmount());
                memberAmount = CurrencyUtil.add(memberAmount, order.getMemberPayAmount());
                transactionAmount = CurrencyUtil.add(transactionAmount, order.getPayAmount());
            }
        }

        stats.setWechatAmount(wxPayAmount); // 微信
        stats.setAlipayAmount(alipayAmount); // 支付宝
        stats.setCashAmount(cashAmount); // 现金
        stats.setMemberAmount(memberAmount); // 余额
        stats.setUnionAmount(unionAmount); // 银联
        stats.setTransactionAmount(transactionAmount);
    }

    /**
     * 计算商品订单支付方式金额
     */
    private void calculateGoodsPayTypeAmounts(List<OrderGoods> orderList, OrderStatisticsVO stats) {
        BigDecimal wxPayAmount = BigDecimal.ZERO;
        BigDecimal alipayAmount = BigDecimal.ZERO;
        BigDecimal cashAmount = BigDecimal.ZERO;
        BigDecimal memberAmount = BigDecimal.ZERO;
        BigDecimal unionAmount = BigDecimal.ZERO;
        BigDecimal transactionAmount = BigDecimal.ZERO;
        for (OrderGoods order : orderList) {
            if (PayStatus.HAS_PAY.getCode().equals(order.getPayStatus())) {
                wxPayAmount = CurrencyUtil.add(wxPayAmount, order.getWxPayAmount());
                alipayAmount = CurrencyUtil.add(alipayAmount, order.getAliPayAmount());
                cashAmount = CurrencyUtil.add(cashAmount, order.getCashPayAmount());
                memberAmount = CurrencyUtil.add(memberAmount, order.getMemberPayAmount());
                transactionAmount = CurrencyUtil.add(transactionAmount, order.getPayAmount());
            }
        }

        stats.setWechatAmount(wxPayAmount); // 微信
        stats.setAlipayAmount(alipayAmount); // 支付宝
        stats.setCashAmount(cashAmount); // 现金
        stats.setMemberAmount(memberAmount); // 余额
        stats.setUnionAmount(unionAmount); // 银联
        stats.setTransactionAmount(transactionAmount);
    }


    /**
     * 计算洗衣订单支付方式金额
     */
    private void calculateClothRefundTypeAmounts(List<OrderClothRefund> orderList, OrderStatisticsVO stats) {

        BigDecimal wxPayAmount = BigDecimal.ZERO;
        BigDecimal alipayAmount = BigDecimal.ZERO;
        BigDecimal cashAmount = BigDecimal.ZERO;
        BigDecimal memberAmount = BigDecimal.ZERO;
        BigDecimal unionAmount = BigDecimal.ZERO;
        BigDecimal transactionAmount = BigDecimal.ZERO;
        for (OrderClothRefund order : orderList) {
            if (OrderRefundStatus.REFUND_SUCCESS.getCode().equals(order.getRefundStatus())) {
                wxPayAmount = CurrencyUtil.add(wxPayAmount, order.getWxRefundAmount());
                alipayAmount = CurrencyUtil.add(alipayAmount, order.getAliRefundAmount());
                cashAmount = CurrencyUtil.add(cashAmount, order.getCashRefundAmount());
                memberAmount = CurrencyUtil.add(memberAmount, order.getMemberRefundAmount());
                transactionAmount = CurrencyUtil.add(transactionAmount, order.getRefundAmount());
            }
        }

        stats.setWechatRefundAmount(wxPayAmount); // 微信
        stats.setAlipayRefundAmount(alipayAmount); // 支付宝
        stats.setCashRefundAmount(cashAmount); // 现金
        stats.setMemberRefundAmount(memberAmount); // 余额
        stats.setUnionRefundAmount(unionAmount); // 银联
        stats.setTransactionRefundAmount(transactionAmount);

    }

    /**
     * 计算商品订单支付方式金额
     */
    private void calculateGoodsRefundTypeAmounts(List<OrderGoodsRefund> orderList, OrderStatisticsVO stats) {
        BigDecimal wxPayAmount = BigDecimal.ZERO;
        BigDecimal alipayAmount = BigDecimal.ZERO;
        BigDecimal cashAmount = BigDecimal.ZERO;
        BigDecimal memberAmount = BigDecimal.ZERO;
        BigDecimal unionAmount = BigDecimal.ZERO;
        BigDecimal transactionAmount = BigDecimal.ZERO;
        for (OrderGoodsRefund order : orderList) {
            if (OrderRefundStatus.REFUND_SUCCESS.getCode().equals(order.getRefundStatus())) {
                wxPayAmount = CurrencyUtil.add(wxPayAmount, order.getWxRefundAmount());
                alipayAmount = CurrencyUtil.add(alipayAmount, order.getAliRefundAmount());
                cashAmount = CurrencyUtil.add(cashAmount, order.getCashRefundAmount());
                memberAmount = CurrencyUtil.add(memberAmount, order.getMemberRefundAmount());
                transactionAmount = CurrencyUtil.add(transactionAmount, order.getRefundAmount());
            }
        }

        stats.setWechatRefundAmount(wxPayAmount); // 微信
        stats.setAlipayRefundAmount(alipayAmount); // 支付宝
        stats.setCashRefundAmount(cashAmount); // 现金
        stats.setMemberRefundAmount(memberAmount); // 余额
        stats.setUnionRefundAmount(unionAmount); // 银联
        stats.setTransactionRefundAmount(transactionAmount);
    }


    /**
     * 计算支付方式统计
     */
    private PaymentStatisticsVO calculatePaymentStats(OrderStatisticsVO clothStats,
                                                      OrderStatisticsVO goodsStats) {
        PaymentStatisticsVO stats = new PaymentStatisticsVO();
        stats.setWechatPayAmount(clothStats.getWechatAmount().add(goodsStats.getWechatAmount()));
        stats.setAlipayPayAmount(clothStats.getAlipayAmount().add(goodsStats.getAlipayAmount()));
        stats.setCashPayAmount(clothStats.getCashAmount().add(goodsStats.getCashAmount()));
        stats.setMemberPayAmount(clothStats.getMemberAmount().add(goodsStats.getMemberAmount()));
        stats.setUnionPayAmount(clothStats.getUnionAmount().add(goodsStats.getUnionAmount()));
        stats.setWechatRefundAmount(clothStats.getWechatRefundAmount().add(goodsStats.getWechatRefundAmount()));
        stats.setAlipayRefundAmount(clothStats.getAlipayRefundAmount().add(goodsStats.getAlipayRefundAmount()));
        stats.setCashRefundAmount(clothStats.getCashRefundAmount().add(goodsStats.getCashRefundAmount()));
        stats.setMemberRefundAmount(clothStats.getMemberRefundAmount().add(goodsStats.getMemberRefundAmount()));
        stats.setUnionRefundAmount(clothStats.getUnionRefundAmount().add(goodsStats.getUnionRefundAmount()));
        stats.setTransactionAmount(clothStats.getTransactionAmount().add(goodsStats.getTransactionAmount()));
        stats.setTransactionRefundAmount(clothStats.getTransactionRefundAmount().add(goodsStats.getTransactionRefundAmount()));
        return stats;
    }

    /**
     * 门店结算
     *
     * @param settlementManageBill
     */
    private Integer handleCountStoreSettlement(SettlementManageBill settlementManageBill) {
        List<SysStore> storeList = storeService.list(new QueryWrapper<SysStore>().lambda()
                .gt(SysStore::getId, 0)
                .eq(SysStore::getStatus, StatusType.OK.getCode())
                .eq(SysStore::getDelFlag, DeleteStatus.OK.getCode()));
        if (CollUtil.isEmpty(storeList)) {
            return 0;
        }
        for (SysStore store : storeList) {
            this.buildStoreSettlement(settlementManageBill, store);
        }
        return storeList.size();
    }


    /**
     * 加载门店结算所需的所有基础数据
     */
    private StoreSettlementData loadSettlementData(Long storeId, Date startTime, Date endTime) {
        StoreSettlementData data = new StoreSettlementData();

        //获取费率
        SettlementStoreRate settlementRate = settlementStoreRateService.getByStoreId(storeId, startTime);
        data.setSettlementRate(settlementRate);

        // 并行加载数据以提高性能
        CompletableFuture.allOf(
                // 加载订单数据
                CompletableFuture.runAsync(() -> {
                    data.setClothOrders(orderClothService.list(new QueryWrapper<OrderCloth>()
                            .eq("org_id", storeId)
                            .eq("pay_status", PayStatus.HAS_PAY.getCode())
                            .between("pay_time", startTime, endTime)));
                    //大于0的数据
                    data.setClothItems(orderClothItemService.list(new QueryWrapper<OrderClothItem>()
                            .eq("org_id", storeId)
                            .gt("flow_status", ClothOrderFlowStatus.waitingForWash.getCode())
                            .between("create_time", startTime, endTime)));

                    data.setGoodsOrders(orderGoodsService.list(new QueryWrapper<OrderGoods>()
                            .eq("org_id", storeId)
                            .eq("source_type", SourceType.STORE.getCode())
                            .eq("pay_status", PayStatus.HAS_PAY.getCode())
                            .between("pay_time", startTime, endTime)));
                    //加载采购订单
                    data.setOrderPurchaseGoods(orderPurchaseGoodsService.list(new QueryWrapper<OrderPurchaseGoods>()
                            .eq("org_id", storeId)
                            .eq("source_type", SourceType.STORE.getCode())
                            .gt("order_status", purchaseGoodsStatusType.CONFIRM_PAY.getCode())
                            .between("pay_time", startTime, endTime)));
                }),
                //加载退款数据
                CompletableFuture.runAsync(() -> {

                    // 3. 查询衣服退款记录
                    List<OrderClothRefund> clothRefundList = orderClothRefundService.list(new QueryWrapper<OrderClothRefund>().lambda()
                            .eq(OrderClothRefund::getSourceType, SourceType.STORE.getCode())
                            .eq(OrderClothRefund::getOrgId, storeId)
                            .eq(OrderClothRefund::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                            .between(OrderClothRefund::getRefundTime, startTime, endTime));

                    // 4. 查询商品退款记录
                    List<OrderGoodsRefund> goodsRefundList = orderGoodsRefundService.list(new QueryWrapper<OrderGoodsRefund>().lambda()
                            .eq(OrderGoodsRefund::getOrgId, storeId)
                            .eq(OrderGoodsRefund::getSourceType, SourceType.STORE.getCode())
                            .eq(OrderGoodsRefund::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                            .between(OrderGoodsRefund::getRefundTime, startTime, endTime));

                    data.setClothRefunds(clothRefundList);
                    data.setGoodsRefunds(goodsRefundList);
                }),

                // 加载支付数据
                CompletableFuture.runAsync(() -> {
                    data.setPayInfos(orderPayInfoService.list(new QueryWrapper<OrderPayInfo>()
                            .eq("store_id", storeId)
                            .eq("pay_status", PayStatus.HAS_PAY.getCode())
                            .between("create_time", startTime, endTime)));

                    data.setRefundInfos(orderRefundInfoService.list(new QueryWrapper<OrderRefundInfo>()
                            .eq("store_id", storeId)
                            .eq("refund_status", PayStatus.HAS_PAY.getCode())
                            .between("create_time", startTime, endTime)));
                }),

                // 加载会员卡数据
                CompletableFuture.runAsync(() -> {
                    data.setMemberCards(rechargePasswordCardService.list(new QueryWrapper<RechargePasswordCard>()
                            .eq("recharge_store_id", storeId)));
                }),

                // 加载跨店结算数据
                CompletableFuture.runAsync(() -> {
                    data.setCrossStoreBills(appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>()
                            .eq("org_id", storeId)
                            .ne("order_type", '4')
                            .or().eq("card_store_id", storeId)
                            .between("create_time", startTime, endTime)));
                }),

                // 加载上期结算数据
                CompletableFuture.runAsync(() -> {
                    Date lastMonthStart = DateUtils.addMonths(startTime, -1);
                    data.setLastSettlement(settlementManageStoreService.getOne(new QueryWrapper<SettlementManageStore>()
                            .eq("org_id", storeId)
                            .eq("begin_time", lastMonthStart)));
                })

        ).join();

        return data;
    }

    /**
     * 主结算方法
     */
    private void buildStoreSettlement(SettlementManageBill settlementManageBill, SysStore store) {
        // 1. 加载所有基础数据
        StoreSettlementData data = loadSettlementData(store.getId(),
                settlementManageBill.getBeginTime(),
                settlementManageBill.getEndTime());

        // 2. 创建结算记录
        SettlementManageStore settlement = new SettlementManageStore();
        buildStoreSettlementInfo(settlement, settlementManageBill, store);
        if (data.getSettlementRate() == null) {
            // 7. 设置备注信息
            settlement.setRemark("当期无可用的门店结算费率");
            settlement.setStatus(SettlementStatusType.NO.getCode());
            settlementManageStoreService.save(settlement);
            return;
        }
        // 3. 计算会员相关金额
        calculateMembershipAmounts(settlement, data);

        // 4. 计算支付相关金额
        calculatePaymentAmounts(settlement, data);

        //计算洗衣和商品订单统计，采购订单
        calculateClothAndGoodsOrderStats(settlement, data);

        // 5. 计算运营相关金额
        calculateOperationalAmounts(settlement, data);

        //计算跨店结算金
        calculateCrossStoreAmount(settlement, data);

        //计算快递费
        calculateExpressAmount(settlement, data);

        // 6. 计算最终结算金额
        calculateFinalSettlement(settlement);

        // 7. 保存结算记录
        settlement.setStatus(SettlementStatusType.NO.getCode());
        settlementManageStoreService.save(settlement);
    }

    private void calculateExpressAmount(SettlementManageStore settlement, StoreSettlementData data) {
        // 1. 统计快递订单数据
        settlement.setExpressAmount(BigDecimal.ZERO);
        settlement.setExpressCount(0);
    }

    private void calculateClothAndGoodsOrderStats(SettlementManageStore settlement, StoreSettlementData data) {
        // 1. 统计洗衣订单数据
        OrderStatisticsVO clothStats = calculateClothOrderStats(data.getClothOrders(), data.getClothRefunds());

        settlement.setOrderClothAmount(CurrencyUtil.sub(clothStats.getTransactionAmount(), clothStats.getTransactionRefundAmount()));

        // 2. 统计商品订单数据
        OrderStatisticsVO goodsStats = calculateGoodsOrderStats(data.getGoodsOrders(), data.getGoodsRefunds());
        log.info("洗衣订单统计结果：{}", JSONUtil.toJsonStr(clothStats));
        log.info("商品订单统计结果：{}", JSONUtil.toJsonStr(goodsStats));
        settlement.setOrderGoodsAmount(CurrencyUtil.sub(goodsStats.getTransactionAmount(), goodsStats.getTransactionRefundAmount()));
        settlement.setOrderAmount(CurrencyUtil.add(settlement.getOrderClothAmount(), settlement.getOrderGoodsAmount()));

        //3. 统计采购订单金额
        BigDecimal orderPurchaseAmount = data.getOrderPurchaseGoods().stream()
                .map(goods -> goods.getCostTotalPrice()
                )
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        settlement.setOrderPurchaseAmount(orderPurchaseAmount);
    }

    /**
     * 计算会员相关金额
     */
    private void calculateMembershipAmounts(SettlementManageStore settlement, StoreSettlementData data) {
        // 1. 计算会员剩余金额，如果赠送时间没有过期也统计进来
        BigDecimal memberBalance = data.getMemberCards().stream()
                .filter(card -> {
                    return RechargeStatusType.HAS_USE.getCode().equals(card.getRechargeStatus()) && (
                            card.getGiveExpiredTime() == null || card.getGiveExpiredTime().after(new Date())
                    );
                })
                .map(card -> card.getRechargeBalance()
                        .add(card.getGiveBalance())
                )
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        settlement.setMemberBalance(memberBalance);

        // 2. 计算福利金额
        BigDecimal welfareAmount = data.getMemberCards().stream()
                .filter(card -> RechargeStatusType.HAS_USE.getCode().equals(card.getRechargeStatus()))
                .map(RechargePasswordCard::getWelfareBalance)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        settlement.setWelfareAmount(welfareAmount);

        // 3. 计算未开卡金额
        BigDecimal unopenedAmount = data.getMemberCards().stream()
                .filter(card -> RechargeStatusType.NOT_UES.getCode().equals(card.getRechargeStatus()))
                .map(RechargePasswordCard::getRechargeBalance)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        settlement.setUnopenedCardPasswordAmount(unopenedAmount);

        // 4. 计算各类押金
        SettlementStoreRate settlementRate = data.getSettlementRate();
        settlement.setPayableDeposit(memberBalance.multiply(settlementRate.getCardDepositRate()));
        settlement.setWelfareDeposit(welfareAmount.multiply(settlementRate.getWelfareDepositRate()));
        settlement.setCardPasswordDeposit(unopenedAmount.multiply(settlementRate.getPasswordDepositRate()));

        // 5. 设置上期押金数据
        if (data.getLastSettlement() != null) {
            settlement.setPaidDeposit(data.getLastSettlement().getPayableDeposit());
            settlement.setPaidWelfareDeposit(data.getLastSettlement().getWelfareDeposit());
            settlement.setPaidCardPasswordDeposit(data.getLastSettlement().getCardPasswordDeposit());
        }
    }

    /**
     * 计算支付相关金额
     */
    private void calculatePaymentAmounts(SettlementManageStore settlement, StoreSettlementData data) {
        SettlementStoreRate settlementRate = data.getSettlementRate();
        // 1. 计算支付宝收支
        Map<String, BigDecimal> alipayStats = calculatePaymentSettlementStats(data, PayType.ALIPAY.getCode());
        settlement.setAlipayAmount(alipayStats.get("netAmount"));
        settlement.setAlipayArriveAmount(CurrencyUtil.mul(settlement.getAlipayAmount(), new BigDecimal(1).subtract(settlementRate.getAliPayRate())));

        // 2. 计算微信收支
        Map<String, BigDecimal> wechatStats = calculatePaymentSettlementStats(data, PayType.WECHAT.getCode());
        settlement.setWechatAmount(wechatStats.get("netAmount"));
        settlement.setWechatArriveAmount(CurrencyUtil.mul(settlement.getWechatAmount(), new BigDecimal(1).subtract(settlementRate.getWxPayRate())));
    }

    /**
     * 计算运营相关金额
     */
    private void calculateOperationalAmounts(SettlementManageStore settlement, StoreSettlementData data) {
        // 1. 计算原材料备用金,原材料备用金=（洗衣订单+商品订单-本期内已撤订单）*原材料费率
        BigDecimal materialAmount = CurrencyUtil.mul(settlement.getOrderAmount(), data.getSettlementRate().getMaterialRate());
        settlement.setMaterialImprestAmount(materialAmount);
        //1.1 原材料备用金余额=上期末原材料备用金余额+本期新增原材料备用金可用额度-本期原辅材料采购订单金额之和
        if (data.getLastSettlement() != null) {
            settlement.setMaterialImprestRemainAmount(CurrencyUtil.sub(CurrencyUtil.add(data.getLastSettlement().getMaterialImprestRemainAmount(), settlement.getMaterialImprestAmount()), settlement.getOrderPurchaseAmount()));
        } else {
            settlement.setMaterialImprestRemainAmount(CurrencyUtil.sub(settlement.getMaterialImprestAmount(), settlement.getOrderPurchaseAmount()));
        }

        // 2. 计算系统维护费
        BigDecimal systemMaintenanceAmount = CurrencyUtil.mul(settlement.getOrderAmount(), data.getSettlementRate().getManagementRate());
        settlement.setSystemMaintenanceAmount(systemMaintenanceAmount);

        // 3. 计算洗衣费 (已入厂)
        BigDecimal washAmount = data.getClothItems().stream()
                .filter(item -> Integer.parseInt(item.getFlowStatus()) > 0)
                .map(OrderClothItem::getPayPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        settlement.setWashClothAmount(washAmount);
    }

    /**
     * 计算跨店结算金额
     * *
     * 1. 洗衣：线下门店，会员用余额支付的洗衣订单
     * 2. 零售：线下门店，会员用余额支付的零售商品订单
     * 3. app：线上app，会员用余额支付的零售商品订单（app洗衣订单不存在跨店结算）
     * 4. 第三方：线下门店，会员用微信/支付宝等第三方支付渠道支付的所有订单（含洗衣和零售，实际情况下比较少）
     * 5. 运费：暂时为0（目前平台和门店自有运费账户走预充值模式，字段保留）
     * 根据会员余额所消费的门店费率计算分成，分成规则为：
     * *      * 本店卡洗衣所得为本店卡在异店消费分给消费门店的费用，异店卡洗衣为异店卡在本店消费分给本店的费用**
     */
    private void calculateCrossStoreAmount(SettlementManageStore settlement, StoreSettlementData data) {
        // 4. 计算跨店结算金额（会员卡）
        // 跨店结算金=(本店卡:洗衣*费率-异店卡:洗衣*费率)+
        // (本店卡:零售*费率-异店卡:零售*费率)+(本店卡:app*费率-异店卡:app*费率)+
        // (本店卡:第三方*费率-异店卡:第三方*费率)+(本店卡:运费*费率-异店卡:运费*费率)
        //消费的订单金额  洗衣 零售 app 第三方 运费
        BigDecimal washAmount = BigDecimal.ZERO;
        BigDecimal washOtherAmount = BigDecimal.ZERO; //洗衣异店
        BigDecimal goodsAmount = BigDecimal.ZERO;
        BigDecimal goodsOtherAmount = BigDecimal.ZERO;
        BigDecimal appAmount = BigDecimal.ZERO;
        BigDecimal appOtherAmount = BigDecimal.ZERO;
        BigDecimal thirdAmount = BigDecimal.ZERO;
        BigDecimal thirdOtherAmount = BigDecimal.ZERO;
        BigDecimal freightAmount = BigDecimal.ZERO;

        Long currentStoreId = settlement.getOrgId();

        for (AppUserBillMstr appUserBillMstr : data.getCrossStoreBills()) {
            if (appUserBillMstr.getSourceType() == null) {
                continue;
            }
            if (appUserBillMstr.getIsRefund().equals(SysBoolType.NO.getCode())) {

                if (appUserBillMstr.getSourceType().equals(SourceType.MANAGER.getCode())) {
                    //线上三方使用门店卡支付的金额
                    if (OrderType.goods.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.life.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.car.getCode().equals(appUserBillMstr.getOrderType())) {
                        if (currentStoreId.equals(appUserBillMstr.getCardStoreId())) {
                            appAmount = CurrencyUtil.add(appAmount, appUserBillMstr.getPayTotalAmount());
                        }
                    }
                    continue;
                }


                if (OrderType.cloth.getCode().equals(appUserBillMstr.getOrderType())) {
                    //本店的卡在其他店的消费
                    if (currentStoreId.equals(appUserBillMstr.getCardStoreId()) && !currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        washAmount = CurrencyUtil.add(washAmount, appUserBillMstr.getPayTotalAmount());
                    }
                    //异店的卡在本店的消费
                    if (!currentStoreId.equals(appUserBillMstr.getCardStoreId()) && currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        washOtherAmount = CurrencyUtil.add(washOtherAmount, appUserBillMstr.getPayTotalAmount());
                    }
                } else if (OrderType.goods.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.life.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.car.getCode().equals(appUserBillMstr.getOrderType())) {
                    if (currentStoreId.equals(appUserBillMstr.getCardStoreId()) && !currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        goodsAmount = CurrencyUtil.add(goodsAmount, appUserBillMstr.getPayTotalAmount());
                    }
                    if (!currentStoreId.equals(appUserBillMstr.getCardStoreId()) && currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        goodsOtherAmount = CurrencyUtil.add(goodsOtherAmount, appUserBillMstr.getPayTotalAmount());
                    }
                }

            } else {
                //退款
                if (appUserBillMstr.getSourceType().equals(SourceType.MANAGER.getCode())) {
                    //线上三方使用门店卡支付的金额
                    if (OrderType.goods.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.life.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.car.getCode().equals(appUserBillMstr.getOrderType())) {
                        if (currentStoreId.equals(appUserBillMstr.getCardStoreId())) {
                            appAmount = CurrencyUtil.sub(appAmount, appUserBillMstr.getPayTotalAmount());
                        }
                    }
                    continue;
                }


                if (OrderType.cloth.getCode().equals(appUserBillMstr.getOrderType())) {
                    //本店的卡在其他店的消费
                    if (currentStoreId.equals(appUserBillMstr.getCardStoreId()) && !currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        washAmount = CurrencyUtil.sub(washAmount, appUserBillMstr.getPayTotalAmount());
                    }
                    //异店的卡在本店的消费
                    if (!currentStoreId.equals(appUserBillMstr.getCardStoreId()) && currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        washOtherAmount = CurrencyUtil.sub(washOtherAmount, appUserBillMstr.getPayTotalAmount());
                    }
                } else if (OrderType.goods.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.life.getCode().equals(appUserBillMstr.getOrderType()) || OrderType.car.getCode().equals(appUserBillMstr.getOrderType())) {
                    if (currentStoreId.equals(appUserBillMstr.getCardStoreId()) && !currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        goodsAmount = CurrencyUtil.sub(goodsAmount, appUserBillMstr.getPayTotalAmount());
                    }
                    if (!currentStoreId.equals(appUserBillMstr.getCardStoreId()) && currentStoreId.equals(appUserBillMstr.getOrgId())) {
                        goodsOtherAmount = CurrencyUtil.sub(goodsOtherAmount, appUserBillMstr.getPayTotalAmount());
                    }
                }

            }
        }
        SettlementStoreRate settlementRate = data.getSettlementRate();
        BigDecimal allPayAmount = CurrencyUtil.add(washAmount, goodsAmount, appAmount, thirdAmount, freightAmount);
        BigDecimal otherPayAmount = CurrencyUtil.add(washOtherAmount, goodsOtherAmount, appOtherAmount, thirdOtherAmount);
        BigDecimal crossStoreAmount = CurrencyUtil.mul(CurrencyUtil.sub(allPayAmount, otherPayAmount), settlementRate.getOtherConsumeRate());
        settlement.setOtherStoreAmount(allPayAmount);
        settlement.setOtherCardAmount(otherPayAmount);
        settlement.setRetailOtherStoreAmount(goodsAmount);
        settlement.setRetailOtherCardAmount(goodsOtherAmount);
        settlement.setAppOtherStoreAmount(appAmount);
        settlement.setAppOtherCardAmount(appOtherAmount);
        settlement.setThirdOtherStoreAmount(thirdAmount);
        settlement.setThirdOtherCardAmount(thirdOtherAmount);


        settlement.setCrossStoreSettlementAmount(crossStoreAmount);
    }

    /**
     * 计算最终结算金额
     */
    private void calculateFinalSettlement(SettlementManageStore settlement) {

        /**
         * 门店结算金额=（支付宝+微信实收金额）-(应付押金-已付押金)-(应付福利押金+卡密押金-已付福利押金-已付卡密押金)
         *  -原材料备用金-系统维护费-洗衣费-跨店结算金*
         */
        BigDecimal finalAmount = settlement.getAlipayAmount()
                .add(settlement.getWechatAmount())
                .subtract(settlement.getPayableDeposit().subtract(settlement.getPaidDeposit()))
                .subtract(settlement.getWelfareDeposit().subtract(settlement.getPaidWelfareDeposit()))
                .subtract(settlement.getCardPasswordDeposit().subtract(settlement.getPaidCardPasswordDeposit()))
                .subtract(settlement.getMaterialImprestAmount())
                .subtract(settlement.getSystemMaintenanceAmount())
                .subtract(settlement.getWashClothAmount())
                .subtract(settlement.getCrossStoreSettlementAmount());

        settlement.setSettlementAmount(finalAmount);
    }

    private void buildStoreSettlementInfo(SettlementManageStore settlementManageStore, SettlementManageBill settlementManageBill, SysStore store) {
        settlementManageStore.setBillId(settlementManageBill.getId());
        settlementManageStore.setSourceType(SourceType.STORE.getCode());
        settlementManageStore.setOrgId(store.getId());
        settlementManageStore.setBeginTime(settlementManageBill.getBeginTime());
        settlementManageStore.setEndTime(settlementManageBill.getEndTime());
        settlementManageStore.setTitle(settlementManageBill.getTitle());
        settlementManageStore.setStatus(SettlementStatusType.NO.getCode());

        this.build0ClothStore(settlementManageStore);
    }

    /**
     * 门店本月没有交易时，初始化结算数据为0
     *
     * @param settlementManageStore 门店结算对象
     */
    private void build0ClothStore(SettlementManageStore settlementManageStore) {
        // 1. 会员相关金额初始化
        settlementManageStore.setMemberBalance(BigDecimal.ZERO);          // 会员剩余金额
        settlementManageStore.setPayableDeposit(BigDecimal.ZERO);        // 会员卡应付押金
        settlementManageStore.setPaidDeposit(BigDecimal.ZERO);           // 会员卡已付押金
        settlementManageStore.setWelfareAmount(BigDecimal.ZERO);         // 福利金额
        settlementManageStore.setWelfareDeposit(BigDecimal.ZERO);        // 应付福利押金
        settlementManageStore.setPaidWelfareDeposit(BigDecimal.ZERO);    // 已付福利押金

        // 2. 卡密相关金额初始化
        settlementManageStore.setUnopenedCardPasswordAmount(BigDecimal.ZERO);  // 未开卡卡密金额
        settlementManageStore.setCardPasswordDeposit(BigDecimal.ZERO);         // 应付未开卡卡密押金
        settlementManageStore.setPaidCardPasswordDeposit(BigDecimal.ZERO);     // 已付卡密押金

        // 3. 支付相关金额初始化
        settlementManageStore.setAlipayAmount(BigDecimal.ZERO);          // 支付宝实收总金额
        settlementManageStore.setWechatAmount(BigDecimal.ZERO);          // 微信支付实收总金额

        // 4. 运营相关金额初始化
        settlementManageStore.setMaterialImprestAmount(BigDecimal.ZERO); // 原材料备用金
        settlementManageStore.setSystemMaintenanceAmount(BigDecimal.ZERO); // 系统维护费
        settlementManageStore.setWashClothAmount(BigDecimal.ZERO);       // 洗衣费
        settlementManageStore.setCrossStoreSettlementAmount(BigDecimal.ZERO); // 跨店结算金额

        // 5. 订单统计数据初始化
//        settlementManageStore.setTotalTransactionNum(0);                 // 总交易笔数
//        settlementManageStore.setTotalTransactionAmount(BigDecimal.ZERO); // 总交易金额
//        settlementManageStore.setRealIncomeAmount(BigDecimal.ZERO);      // 实际收入金额

        // 6. 最终结算金额初始化
        settlementManageStore.setSettlementAmount(BigDecimal.ZERO);      // 结算金额

        // 7. 设置备注信息
    }

    /**
     * 工厂结算处理
     *
     * @param settlementManageBill
     * @return
     */
    private void buildFactorySettlement(SettlementManageBill settlementManageBill, ManageFactory factory) {
        if (settlementManageBill.getStatus().equals(SettlementBillStatusType.FINISH.getCode())) {
            throw new ServiceException("该账单已结算完成，请勿重复操作");
        }
        //删除工厂结算数据，重新结算
        settlementManageFactoryService.remove(new QueryWrapper<SettlementManageFactory>().lambda().eq(SettlementManageFactory::getOrgId, factory.getId()).eq(SettlementManageFactory::getBillId, settlementManageBill.getId()));
        SettlementFactoryRate settlementFactoryRate = settlementFactoryRateService.getByFactoryId(factory.getId(), settlementManageBill.getBeginTime());
        SettlementManageFactory settlementManageFactory = new SettlementManageFactory();
        this.buildFactorySettlementInfo(settlementManageFactory, settlementManageBill, factory);
        if (settlementFactoryRate == null) {
            this.build0ClothFactory(settlementManageFactory);
            settlementManageFactory.setRemark("工厂暂无可用费率");
            settlementManageFactoryService.save(settlementManageFactory);
            return;
        }
        //查询衣服订单，入场时间在上个月的，切没有撤销或者推单的衣服
        List<OrderClothItem> orderClothItemList = orderClothItemService.list(new QueryWrapper<OrderClothItem>().lambda()
                .isNull(OrderClothItem::getRefundId)
                .eq(OrderClothItem::getFactoryId, factory.getId())
                .ge(OrderClothItem::getCreateTime, settlementManageBill.getBeginTime())
                .ge(OrderClothItem::getInFactoryTime, settlementManageBill.getBeginTime())
                .lt(OrderClothItem::getInFactoryTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        if (CollUtil.isEmpty(orderClothItemList)) {
            this.build0ClothFactory(settlementManageFactory);
            settlementManageFactory.setRemark("无入厂洗衣订单");
            settlementManageFactoryService.save(settlementManageFactory);
            return;
        }
        settlementManageFactory.setTotalTransactionNum(orderClothItemList.size());
        //计算衣服总价格
        BigDecimal orderClothItemTotalPrice = orderClothItemList.stream().map(OrderClothItem::getTotalPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 总交易金额
        settlementManageFactory.setTotalTransactionAmount(orderClothItemTotalPrice);
        //按照门店进行统计，计算每个门店的总金额
        Map<Long, BigDecimal> storeTotalPriceMap = orderClothItemList.stream().collect(Collectors.groupingBy(OrderClothItem::getOrgId, Collectors.mapping(OrderClothItem::getTotalPrice, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
        AtomicReference<BigDecimal> factorySettlementAmount = new AtomicReference<>(BigDecimal.ZERO);
        storeTotalPriceMap.forEach((k, v) -> {
            //获取门店的费率
            SettlementStoreRate settlementStoreRate = settlementStoreRateService.getByStoreId(k, settlementManageBill.getBeginTime());
            if (settlementStoreRate == null || settlementStoreRate.getFactoryRate() == null) {
                settlementManageFactory.setRemark("工厂结算部分门店费率暂未设置");
                settlementManageFactoryService.save(settlementManageFactory);
                return;
            }
            BigDecimal amount = CurrencyUtil.mul(v, settlementStoreRate.getFactoryRate());
            factorySettlementAmount.set(CurrencyUtil.add(factorySettlementAmount.get(), amount));
        });
        //（所有门店入厂洗衣件数对应的订单总金额-入厂后未洗退单总金额）*对应门店工厂结算费率
        settlementManageFactory.setFactorySettlementAmount(factorySettlementAmount.get());
        //材料结算金额总和
        BigDecimal materialAmount = CurrencyUtil.mul(settlementFactoryRate.getMaterialRate(), orderClothItemTotalPrice);
        settlementManageFactory.setMaterialAmount(materialAmount);
        //管理费
        BigDecimal managetAmount = CurrencyUtil.mul(settlementFactoryRate.getManagementRate(), orderClothItemTotalPrice);
        settlementManageFactory.setManageAmount(managetAmount);
        // 工厂消费 = 材料费+ 管理费
        BigDecimal payMoney = settlementManageFactory.getManageAmount().add(settlementManageFactory.getMaterialAmount());
        // 工厂实际收入 = 工厂结算金额总和 - 工厂消费
        settlementManageFactory.setRealIncomeAmount(settlementManageFactory.getFactorySettlementAmount().subtract(payMoney));
        settlementManageFactoryService.save(settlementManageFactory);
    }

    /**
     * 本月订单全部为空时，默认所有工厂都是设置为0
     *
     * @param settlementManageBill
     * @param factoryList
     */
    private void handle0ClothAllFactorySettlement(SettlementManageBill settlementManageBill, List<ManageFactory> factoryList) {
        if (CollUtil.isEmpty(factoryList)) {
            return;
        }
        for (ManageFactory factory : factoryList) {
            SettlementManageFactory settlementManageFactory = new SettlementManageFactory();
            this.buildFactorySettlementInfo(settlementManageFactory, settlementManageBill, factory);
            this.build0ClothFactory(settlementManageFactory);
            settlementManageFactoryService.save(settlementManageFactory);
        }
    }

    /**
     * 工厂本月没有衣服时，设置默认为0
     *
     * @param settlementManageFactory
     */
    private void build0ClothFactory(SettlementManageFactory settlementManageFactory) {
        // 工厂结算金额总和
        settlementManageFactory.setFactorySettlementAmount(BigDecimal.ZERO);
        // 材料结算金额总和
        settlementManageFactory.setMaterialAmount(BigDecimal.ZERO);
        // 管理结算金额总和
        settlementManageFactory.setManageAmount(BigDecimal.ZERO);
        // 总交易金额
        settlementManageFactory.setTotalTransactionAmount(BigDecimal.ZERO);
        // 总交易件数
        settlementManageFactory.setTotalTransactionNum(0);
        // 工厂实际收入
        settlementManageFactory.setRealIncomeAmount(BigDecimal.ZERO);
    }

    /**
     * 工厂本月有衣服时，计算数量
     *
     * @param settlementManageFactory
     */
    private void buildHasClothFactory(SettlementManageFactory settlementManageFactory, List<OrderClothItem> orderClothItemList) {
        // 工厂结算金额总和
        // 材料结算金额总和
        // 管理结算金额总和
        // 总交易金额
        settlementManageFactory.setTotalTransactionAmount(
                orderClothItemList.stream().map(OrderClothItem::getTotalPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 总交易件数
        settlementManageFactory.setTotalTransactionNum(orderClothItemList.size());

        // 工厂消费 = 材料费+ 管理费
        BigDecimal payMoney = settlementManageFactory.getManageAmount().add(settlementManageFactory.getMaterialAmount());
        // 工厂实际收入 = 工厂结算金额总和 - 工厂消费
        settlementManageFactory.setRealIncomeAmount(settlementManageFactory.getFactorySettlementAmount().subtract(payMoney));

    }

    /**
     * 构建工厂账单基础数据
     *
     * @param settlementManageFactory
     * @param settlementManageBill
     * @param factory
     */
    private void buildFactorySettlementInfo(SettlementManageFactory settlementManageFactory, SettlementManageBill settlementManageBill, ManageFactory factory) {
        settlementManageFactory.setBillId(settlementManageBill.getId());
        settlementManageFactory.setSourceType(SourceType.FACTORY.getCode());
        settlementManageFactory.setOrgId(factory.getId());
        settlementManageFactory.setBeginTime(settlementManageBill.getBeginTime());
        settlementManageFactory.setEndTime(settlementManageBill.getEndTime());
        settlementManageFactory.setTitle(settlementManageBill.getTitle());
        settlementManageFactory.setStatus(SettlementStatusType.NO.getCode());
    }

    /**
     * 计算衣服退款金额
     */
    private Map<String, BigDecimal> calculateClothRefundAmounts(List<OrderClothRefund> refundList) {
        Map<String, BigDecimal> result = new HashMap<>();
        if (refundList == null || refundList.size() == 0) {
            result.put("count", BigDecimal.ZERO);
            result.put("amount", BigDecimal.ZERO);
            return result;
        }
        // 统计退款笔数
        result.put("count", BigDecimal.valueOf(refundList.size()));

        // 统计退款金额
        BigDecimal refundAmount = refundList.stream()
                .map(OrderClothRefund::getRefundAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        result.put("amount", refundAmount);

        return result;
    }

    /**
     * 计算商品退款金额
     */
    private Map<String, BigDecimal> calculateGoodsRefundAmounts(List<OrderGoodsRefund> refundList) {
        Map<String, BigDecimal> result = new HashMap<>();
        if (refundList == null || refundList.size() == 0) {
            result.put("count", BigDecimal.ZERO);
            result.put("amount", BigDecimal.ZERO);
            return result;
        }

        // 统计退款笔数
        result.put("count", BigDecimal.valueOf(refundList.size()));

        // 统计退款金额
        BigDecimal refundAmount = refundList.stream()
                .map(OrderGoodsRefund::getRefundAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        result.put("amount", refundAmount);

        return result;
    }

    /**
     * 保存统计结果
     */
    private StoreBillStatistics saveStatisticsResult(Long storeId, Date startTime, Date endTime,
                                                     OrderStatisticsVO clothStats, OrderStatisticsVO goodsStats,
                                                     PaymentStatisticsVO paymentStats) {
        StoreBillStatistics statistics = new StoreBillStatistics();
        statistics.setStoreId(storeId);
        statistics.setStartTime(startTime);
        statistics.setEndTime(endTime);
        statistics.setClothOrderStats(clothStats);
        statistics.setGoodsOrderStats(goodsStats);
        statistics.setPaymentStats(paymentStats);

        return statistics;
    }

    /**
     * 计算支付方式的收支统计
     *
     * @param data    结算基础数据
     * @param payType 支付类型代码
     * @return 包含收款、退款和净额的统计结果
     */
    private Map<String, BigDecimal> calculatePaymentSettlementStats(StoreSettlementData data, String payType) {
        Map<String, BigDecimal> stats = new HashMap<>();

        // 1. 计算收款总额（从支付信息表获取）
        BigDecimal payAmount = data.getPayInfos().stream()
                .filter(payInfo -> payType.equals(payInfo.getPayType())
                        && PayStatus.HAS_PAY.getCode().equals(payInfo.getPayStatus()))
                .map(OrderPayInfo::getPayAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        stats.put("payAmount", payAmount);

        // 2. 计算退款总额（从退款信息表获取）
        BigDecimal refundAmount = data.getRefundInfos().stream()
                .filter(refund -> payType.equals(refund.getPayType())
                        && PayStatus.HAS_PAY.getCode().equals(refund.getRefundStatus()))
                .map(OrderRefundInfo::getRefundAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        stats.put("refundAmount", refundAmount);

        // 3. 计算实收金额（收款总额 - 退款总额）
        BigDecimal netAmount = payAmount.subtract(refundAmount);
        stats.put("netAmount", netAmount);

        // 4. 计算交易笔数
        long transactionCount = data.getPayInfos().stream()
                .filter(payInfo -> payType.equals(payInfo.getPayType())
                        && PayStatus.HAS_PAY.getCode().equals(payInfo.getPayStatus()))
                .count();
        stats.put("transactionCount", new BigDecimal(transactionCount));

        // 5. 计算退款笔数
        long refundCount = data.getRefundInfos().stream()
                .filter(refund -> payType.equals(refund.getPayType())
                        && PayStatus.HAS_PAY.getCode().equals(refund.getRefundStatus()))
                .count();
        stats.put("refundCount", new BigDecimal(refundCount));

        return stats;
    }

}



