package com.yiqi.core.service.impl;

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

import cn.hutool.core.collection.CollUtil;
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.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.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.service.ISettlementFactoryRateService;
import com.yiqi.settlement.service.ISettlementStoreRateService;
import com.yiqi.system.domain.ManageFactory;
import com.yiqi.system.domain.SysSettlementRate;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.IManageFactoryService;
import com.yiqi.system.service.ISysConfigService;
import com.yiqi.system.service.ISysSettlementRateService;
import com.yiqi.system.service.ISysStoreService;
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;

/**
 * 结算管理Service业务层处理
 *
 * @author ruoyi
 * @date 2024-02-15
 */
@Service
public class SettlementManageBillServiceImpl extends ServiceImpl<SettlementManageBillMapper, SettlementManageBill> implements ISettlementManageBillService {
    @Autowired
    private ISettlementManageFactoryService settlementManageFactoryService;
    @Autowired
    private ISettlementManageStoreService settlementManageStoreService;
    @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 ISysSettlementRateService sysSettlementRateService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private IOrderClothService orderClothService;
    @Autowired
    private IOrderGoodsService orderGoodsService;
    @Autowired
    private ISettlementFactoryRateService settlementFactoryRateService;

    @Override
    public void insertSettlementManageBill(SettlementBillAddDTO settlementBillAddDTO) {
        SettlementManageBill settlementManageBill = this.buildSettlementManageBill(settlementBillAddDTO);
        // 工厂结算
        this.handleCountFactorySettlement(settlementManageBill);

        // 门店结算
        this.handleCountStoreSettlement(settlementManageBill);
    }

    private SettlementManageBill buildSettlementManageBill(SettlementBillAddDTO settlementBillAddDTO) {
        Date beginTime = DateUtils.strToDate(settlementBillAddDTO.getMonth() + "-01");
        Date endTime = DateUtils.addDays(DateUtils.addMonths(beginTime, 1), -1);
        SettlementManageBill settlementManageBill = new SettlementManageBill();
        settlementManageBill.setBeginTime(beginTime);
        settlementManageBill.setEndTime(endTime);
        settlementManageBill.setTitle(settlementBillAddDTO.getTitle());
        settlementManageBill.buildCreateData();
        settlementManageBill.setStatus(SettlementBillStatusType.COUNT.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) {
            //查询衣服订单，入场时间在上个月的，切没有撤销的衣服
            List<OrderClothItem> orderClothItemList = orderClothItemService.list(new QueryWrapper<OrderClothItem>().lambda()
                    .ne(OrderClothItem::getFlowStatus, ClothOrderFlowStatus.refund.getCode())
                    .eq(OrderClothItem::getFactoryId, factory.getId())
                    .ge(OrderClothItem::getCreateTime, settlementManageBill.getBeginTime())
                    .ge(OrderClothItem::getInFactoryTime, settlementManageBill.getBeginTime())
                    .lt(OrderClothItem::getInFactoryTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
            this.buildFactorySettlement(settlementManageBill, factory, orderClothItemList);
        }
    }

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


        // 计算门店结算明细
//        threadPoolTaskExecutor.execute(() -> this.buildStoreSettlement(settlementManageBill, storeList));
    }

    /**
     * 门店结算处理
     *
     * @param settlementManageBill
     * @return
     */
    private void buildStoreSettlement(SettlementManageBill settlementManageBill, SysStore sysStore) {
        //查询全部门店费率
        List<SysSettlementRate> storeRateList = sysSettlementRateService.list(new QueryWrapper<SysSettlementRate>().lambda());
        Map<Long, List<SysSettlementRate>> storeRateMap = storeRateList.stream().collect(Collectors.groupingBy(SysSettlementRate::getOrgId));
        List<SettlementManageStore> settlementManageStoreList = new ArrayList<>();

        SettlementStoreRate settlementStoreRate = settlementStoreRateService.getByStoreId(sysStore.getId(), settlementManageBill.getBeginTime());
        if (settlementStoreRate == null) {
            SettlementManageStore settlementManageStore = new SettlementManageStore();
            this.buildStoreSettlementInfo(settlementManageStore, settlementManageBill, sysStore);
            settlementManageStore.setStatus(SettlementStatusType.FAIL.getCode());
            settlementManageStore.setRemark("结算费率无效，结算失败");
            settlementManageStoreService.save(settlementManageStore);
        }

        SettlementManageStore settlementManageStore = new SettlementManageStore();
        this.buildStoreSettlementInfo(settlementManageStore, settlementManageBill, sysStore);
        // 查询门店有效充值会员卡
        List<RechargePasswordCard> rechargePasswordCardList = rechargePasswordCardService.list(new QueryWrapper<RechargePasswordCard>().lambda()
                .eq(RechargePasswordCard::getUseBindStoreId, sysStore.getId())
                .eq(RechargePasswordCard::getRechargeStatus, RechargeStatusType.HAS_USE.getCode()));

        // 查询门店未开卡
        List<RechargePasswordCard> noOpenCardList = rechargePasswordCardService.list(new QueryWrapper<RechargePasswordCard>().lambda()
                .eq(RechargePasswordCard::getRechargeStatus, RechargeStatusType.NOT_UES.getCode())
                .eq(RechargePasswordCard::getRechargeStoreId, sysStore.getId()));

        // 查询门店微信消费记录
        List<OrderPayInfo> payInfoList = orderPayInfoService.list(new QueryWrapper<OrderPayInfo>().lambda()
                .eq(OrderPayInfo::getStoreId, sysStore.getId())
                .eq(OrderPayInfo::getPayStatus, PayStatus.HAS_PAY.getCode())
                .ge(OrderPayInfo::getCreateTime, settlementManageBill.getBeginTime())
                .lt(OrderPayInfo::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 查询门店微信消费记录
        List<OrderRefundInfo> refundInfoList = orderRefundInfoService.list(new QueryWrapper<OrderRefundInfo>().lambda()
                .eq(OrderRefundInfo::getStoreId, sysStore.getId())
                .eq(OrderRefundInfo::getRefundStatus, PayStatus.HAS_PAY.getCode())
                .ge(OrderRefundInfo::getCreateTime, settlementManageBill.getBeginTime())
                .lt(OrderRefundInfo::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 查询衣服单项订单
        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ClothOrderFlowStatus.inFactory.getCode());
        statusList.add(ClothOrderFlowStatus.checkCloth.getCode());
        statusList.add(ClothOrderFlowStatus.outFactory.getCode());
        statusList.add(ClothOrderFlowStatus.hangering.getCode());
        statusList.add(ClothOrderFlowStatus.hasTake.getCode());
        statusList.add(ClothOrderFlowStatus.reWash.getCode());

        List<OrderClothItem> orderClothItemList = orderClothItemService.list(new QueryWrapper<OrderClothItem>().lambda()
                .in(OrderClothItem::getFlowStatus, statusList)
                .eq(OrderClothItem::getSourceType, SourceType.STORE.getCode())
                .eq(OrderClothItem::getOrgId, sysStore.getId())
                .ge(OrderClothItem::getCreateTime, settlementManageBill.getBeginTime())
                .lt(OrderClothItem::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 查询衣服订单
        List<OrderCloth> orderClothList = orderClothService.list(new QueryWrapper<OrderCloth>().lambda()
                .ne(OrderCloth::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                .eq(OrderCloth::getSourceType, SourceType.STORE.getCode())
                .eq(OrderCloth::getOrgId, sysStore.getId())
                .ge(OrderCloth::getCreateTime, settlementManageBill.getBeginTime())
                .lt(OrderCloth::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 查询商品订单
        List<OrderGoods> orderGoodsList = orderGoodsService.list(new QueryWrapper<OrderGoods>().lambda()
                .ne(OrderGoods::getRefundStatus, OrderRefundStatus.REFUND_SUCCESS.getCode())
                .eq(OrderGoods::getSourceType, SourceType.STORE.getCode())
                .eq(OrderGoods::getOrgId, sysStore.getId())
                .ge(OrderGoods::getCreateTime, settlementManageBill.getBeginTime())
                .lt(OrderGoods::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));

        // 查询门店跨店结算  收记录
        List<AppUserBillMstr> crossReceiveBillMstrList = appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getSourceType, SourceType.STORE.getCode())
                .eq(AppUserBillMstr::getOrgId, sysStore.getId())
                .eq(AppUserBillMstr::getIsOtherStore, SysBoolType.YES.getCode())
                .eq(AppUserBillMstr::getPayType, PayType.BALANCE.getCode())
                .ge(AppUserBillMstr::getCreateTime, settlementManageBill.getBeginTime())
                .lt(AppUserBillMstr::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 查询门店跨店结算  分红 （给出去）记录
        List<AppUserBillMstr> crossSendBillMstrList = appUserBillMstrService.list(new QueryWrapper<AppUserBillMstr>().lambda()
                .eq(AppUserBillMstr::getSourceType, SourceType.STORE.getCode())
                .eq(AppUserBillMstr::getOtherStoreOrgId, sysStore.getId())
                .eq(AppUserBillMstr::getIsOtherStore, SysBoolType.YES.getCode())
                .eq(AppUserBillMstr::getPayType, PayType.BALANCE.getCode())
                .ge(AppUserBillMstr::getCreateTime, settlementManageBill.getBeginTime())
                .lt(AppUserBillMstr::getCreateTime, DateUtils.addDays(settlementManageBill.getEndTime(), 1)));
        // 充值余额总和
        BigDecimal totalRechargeBalance = rechargePasswordCardList.stream().map(RechargePasswordCard::getRechargeBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 福利金余额总和
        BigDecimal totalWelfareBalance = rechargePasswordCardList.stream().map(RechargePasswordCard::getWelfareBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 赠送余额总和
        BigDecimal totalGiveBalance = rechargePasswordCardList.stream().map(RechargePasswordCard::getGiveBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 未开卡卡密金额总和
        BigDecimal totalUnopenedCard = noOpenCardList.stream().map(RechargePasswordCard::getRechargeBalance).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 微信消费总和
        BigDecimal totalWechat = payInfoList.stream().filter(o -> o.getPayType().equals(PayType.WECHAT.getCode())).map(OrderPayInfo::getPayAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 支付宝消费总和
        BigDecimal totalAlipay = payInfoList.stream().filter(o -> o.getPayType().equals(PayType.ALIPAY.getCode())).map(OrderPayInfo::getPayAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 微信退款总和
        BigDecimal totalWechatRefund = refundInfoList.stream().filter(o -> o.getPayType().equals(PayType.WECHAT.getCode())).map(OrderRefundInfo::getRefundAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 支付宝退款总和
        BigDecimal totalAlipayRefund = refundInfoList.stream().filter(o -> o.getPayType().equals(PayType.ALIPAY.getCode())).map(OrderRefundInfo::getRefundAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);

        // 材料金额
        BigDecimal totalMaterialAmount = orderClothList.stream().map(OrderCloth::getPayAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 系统维护金额
        BigDecimal totalSystemAmount = orderGoodsList.stream().map(OrderGoods::getPayAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 洗衣费
        BigDecimal totalWashAmount = orderClothItemList.stream().map(OrderClothItem::getTotalPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 跨店结算金 -收
        BigDecimal totalCrossReceive = crossReceiveBillMstrList.stream().map(AppUserBillMstr::getOtherStoreAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 跨店结算金 -支付
        BigDecimal totalCrossSend = crossSendBillMstrList.stream().map(AppUserBillMstr::getOtherStoreAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);


        // 设置 会员剩余金额 = 充值余额总和+福利金余额总和+赠送余额总和
        BigDecimal addMemberBalance = totalRechargeBalance.add(totalWelfareBalance).add(totalGiveBalance);
        settlementManageStore.setMemberBalance(addMemberBalance);
        //`welfare_amount` '福利金额',
        settlementManageStore.setWelfareAmount(totalWelfareBalance);
        //   `unopened_card_password_amount` '未开卡卡密金额',
        settlementManageStore.setUnopenedCardPasswordAmount(totalUnopenedCard);

        List<SysSettlementRate> sysSettlementRates = storeRateMap.get(sysStore.getId());
        // 应付押金
        BigDecimal payableDeposit = BigDecimal.ZERO;
        // 应付福利押金
        BigDecimal welfareDeposit = BigDecimal.ZERO;
        // 应付卡密押金
        BigDecimal cardPasswordDeposit = BigDecimal.ZERO;
        // 微信金额
        BigDecimal wechatAmount = BigDecimal.ZERO;
        // 支付宝金额
        BigDecimal alipayAmount = BigDecimal.ZERO;
        // 材料金额
        BigDecimal materialAmount = BigDecimal.ZERO;
        // 系统维护金额
        BigDecimal systemMaintenanceAmount = BigDecimal.ZERO;
        // 洗衣费金额
        BigDecimal washClothAmount = BigDecimal.ZERO;

        // 默认押金率
        BigDecimal decimalDeposit = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementDepositRate.getCode()));
        // 默认微信率
        BigDecimal decimalWechat = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementWXRate.getCode()));
        // 默认支付率
        BigDecimal decimalAlipay = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementAliRate.getCode()));
        // 默认材料费率
        BigDecimal decimalMaterial = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementMaterialRate.getCode()));
        // 默认系统维护费率
        BigDecimal decimalSystem = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementManageRate.getCode()));
        // // 洗衣费率
        BigDecimal decimalWashCloth = new BigDecimal(configService.selectConfigByKey(SysConfigKey.StoreSettlementFactoryRate.getCode()));
        if (CollUtil.isEmpty(sysSettlementRates)) {
            payableDeposit = addMemberBalance.multiply(decimalDeposit);
            welfareDeposit = totalWelfareBalance.multiply(decimalDeposit);
            cardPasswordDeposit = totalUnopenedCard.multiply(decimalDeposit);
            wechatAmount = totalWechat.multiply((new BigDecimal("1").subtract(decimalWechat)));
            alipayAmount = totalAlipay.multiply((new BigDecimal("1").subtract(decimalAlipay)));
            materialAmount = totalMaterialAmount.multiply(decimalMaterial);
            systemMaintenanceAmount = (totalMaterialAmount.add(totalSystemAmount)).multiply(decimalSystem);
            washClothAmount = totalWashAmount.multiply(decimalWashCloth);

            // 设置费率
            settlementManageStore.setFactoryRate(decimalWashCloth);
            settlementManageStore.setManageRate(decimalSystem);
            settlementManageStore.setDepositRate(decimalDeposit);
            settlementManageStore.setMaterialRate(decimalMaterial);
            settlementManageStore.setWxPayRate(decimalWechat);
            settlementManageStore.setAliPayRate(decimalAlipay);
        } else {
            SysSettlementRate rate = sysSettlementRates.get(0);
            payableDeposit = addMemberBalance.multiply(rate.getDepositRate() == null ? decimalDeposit : rate.getDepositRate());
            welfareDeposit = totalWelfareBalance.multiply(rate.getDepositRate() == null ? decimalDeposit : rate.getDepositRate());
            cardPasswordDeposit = totalUnopenedCard.multiply(rate.getDepositRate() == null ? decimalDeposit : rate.getDepositRate());
            wechatAmount = totalWechat.multiply((new BigDecimal("1").subtract(rate.getWxPayRate() == null ? decimalWechat : rate.getWxPayRate())));
            alipayAmount = totalAlipay.multiply((new BigDecimal("1").subtract(rate.getAliPayRate() == null ? decimalAlipay : rate.getAliPayRate())));
            materialAmount = totalMaterialAmount.multiply(rate.getMaterialRate() == null ? decimalMaterial : rate.getMaterialRate());
            systemMaintenanceAmount = (totalMaterialAmount.add(totalSystemAmount)).multiply(rate.getManageRate() == null ? decimalSystem : rate.getManageRate());
            washClothAmount = totalWashAmount.multiply(rate.getFactoryRate() == null ? decimalWashCloth : rate.getFactoryRate());

            // 设置费率
            settlementManageStore.setFactoryRate(rate.getFactoryRate());
            settlementManageStore.setManageRate(rate.getManageRate());
            settlementManageStore.setDepositRate(rate.getDepositRate());
            settlementManageStore.setMaterialRate(rate.getMaterialRate());
            settlementManageStore.setWxPayRate(rate.getWxPayRate());
            settlementManageStore.setAliPayRate(rate.getAliPayRate());
        }

        // 设置微信金额
        settlementManageStore.setWechatAmount(wechatAmount);
        // 设置支付宝金额
        settlementManageStore.setAlipayAmount(alipayAmount);
        // 设置应付押金 payable_deposit = 会员剩余金额* 押金率
        settlementManageStore.setPayableDeposit(payableDeposit);
        // 设置'应付福利押金' `welfare_deposit`,
        settlementManageStore.setWelfareDeposit(welfareDeposit);
        //  设置'应付卡密押金' `card_password_deposit`,
        settlementManageStore.setCardPasswordDeposit(cardPasswordDeposit);
        //原材料备用金（材料费）
        settlementManageStore.setMaterialImprestAmount(materialAmount);
        //系统维护费
        settlementManageStore.setSystemMaintenanceAmount(systemMaintenanceAmount);
        //洗衣费
        settlementManageStore.setWashClothAmount(washClothAmount);
        //跨店结算金
        settlementManageStore.setCrossStoreSettlementAmount(totalCrossSend.subtract(totalCrossReceive));
        //超额订货金额
        settlementManageStore.setOverOrderingAmount(BigDecimal.ZERO);

        // 查询上期结算
        List<SettlementManageStore> settlementManageStoreLastList = settlementManageStoreService.list(new QueryWrapper<SettlementManageStore>().lambda()
                .eq(SettlementManageStore::getOrgId, sysStore.getId())
                .eq(SettlementManageStore::getBeginTime, DateUtils.addMonths(settlementManageStore.getBeginTime(), -1)));

        if (CollUtil.isEmpty(settlementManageStoreLastList)) {
            // `paid_deposit` '已付押金', = 上个月的应付押金
            settlementManageStore.setPaidDeposit(BigDecimal.ZERO);
            // `paid_welfare_deposit`  '已付福利押金',= 上个月的应付福利押金
            settlementManageStore.setPaidWelfareDeposit(BigDecimal.ZERO);
            //   `paid_card_password_deposit`'已付卡密押金',
            settlementManageStore.setPaidCardPasswordDeposit(BigDecimal.ZERO);
        } else {
            SettlementManageStore settlementManageStoreLast = settlementManageStoreLastList.get(0);
            settlementManageStore.setPaidDeposit(settlementManageStoreLast.getPayableDeposit());
            settlementManageStore.setPaidWelfareDeposit(settlementManageStoreLast.getWelfareDeposit());
            settlementManageStore.setPaidCardPasswordDeposit(settlementManageStoreLast.getCardPasswordDeposit());
        }

        //结算金额

        BigDecimal total = wechatAmount.add(alipayAmount).subtract(
                payableDeposit.subtract(settlementManageStore.getPaidDeposit())
        ).subtract(
                welfareDeposit.subtract(settlementManageStore.getPaidWelfareDeposit())
        ).subtract(
                cardPasswordDeposit.subtract(settlementManageStore.getPaidCardPasswordDeposit())
        ).subtract(
                materialAmount
        ).subtract(
                systemMaintenanceAmount
        ).subtract(
                washClothAmount
        ).subtract(
                totalCrossSend.subtract(totalCrossReceive)
        );

        settlementManageStore.setSettlementAmount(total);
        settlementManageStoreList.add(settlementManageStore);


        settlementManageBill.setStatus(SettlementBillStatusType.WAITING.getCode());
        this.updateById(settlementManageBill);
        settlementManageStoreService.saveBatch(settlementManageStoreList);
    }

    private void build0ClothStore(SettlementManageStore settlementManageStore) {
        // 会员剩余金额总和
        settlementManageStore.setMemberBalance(BigDecimal.ZERO);
        // 未开卡卡密押金
        settlementManageStore.setUnopenedCardPasswordAmount(BigDecimal.ZERO);
        // 已付卡密押金
        settlementManageStore.setPaidCardPasswordDeposit(BigDecimal.ZERO);
        // 支付宝/微信
        settlementManageStore.setAlipayAndWechatAmount(BigDecimal.ZERO);
        // 原材料备用金
        settlementManageStore.setMaterialImprestAmount(BigDecimal.ZERO);
        // 系统维护费
        settlementManageStore.setSystemMaintenanceAmount(BigDecimal.ZERO);
        // 洗衣费
        settlementManageStore.setWashClothAmount(BigDecimal.ZERO);
        // 跨店结算金
        settlementManageStore.setCrossStoreSettlementAmount(BigDecimal.ZERO);
        // 超额进货金额
        settlementManageStore.setOverOrderingAmount(BigDecimal.ZERO);
        // 结算金额
        settlementManageStore.setSettlementAmount(BigDecimal.ZERO);
    }

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

    /**
     * 工厂结算处理
     *
     * @param settlementManageBill
     * @return
     */
    private void buildFactorySettlement(SettlementManageBill settlementManageBill, ManageFactory factory, List<OrderClothItem> orderClothItemList) {
        SettlementFactoryRate settlementFactoryRate = settlementFactoryRateService.getByFactoryId(factory.getId(), settlementManageBill.getBeginTime());
        if (settlementFactoryRate == null) {
            SettlementManageFactory settlementManageFactory = new SettlementManageFactory();
            this.buildFactorySettlementInfo(settlementManageFactory, settlementManageBill, factory);
            this.build0ClothFactory(settlementManageFactory);
            settlementManageFactory.setStatus(SettlementStatusType.FAIL.getCode());
            settlementManageFactory.setRemark("结算费率无效，结算失败");
            settlementManageFactoryService.save(settlementManageFactory);
        }
        if (CollUtil.isEmpty(orderClothItemList)) {
            SettlementManageFactory settlementManageFactory = new SettlementManageFactory();
            this.buildFactorySettlementInfo(settlementManageFactory, settlementManageBill, factory);
            this.build0ClothFactory(settlementManageFactory);
            settlementManageFactoryService.save(settlementManageFactory);
            return;
        }
        SettlementManageFactory settlementManageFactory = new SettlementManageFactory();
        this.buildFactorySettlementInfo(settlementManageFactory, settlementManageBill, factory);

        settlementManageFactory.setTotalTransactionNum(orderClothItemList.size());
        //计算衣服总价格
        BigDecimal orderClothItemTotalPrice = orderClothItemList.stream().map(OrderClothItem::getTotalPrice).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 总交易金额
        settlementManageFactory.setTotalTransactionAmount(orderClothItemTotalPrice);
        //材料结算金额总和
        BigDecimal materialAmount = CurrencyUtil.mul(settlementFactoryRate.getMaterialRate(), orderClothItemTotalPrice);
        settlementManageFactory.setMaterialAmount(materialAmount);
        //管理费
        BigDecimal managetAmount = CurrencyUtil.mul(settlementFactoryRate.getManagementRate(), orderClothItemTotalPrice);
        settlementManageFactory.setManageAmount(managetAmount);
        //工厂结算金额总和
        BigDecimal factorySettlementAmount = orderClothItemList.stream().map(OrderClothItem::getFactorySettlementAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
        settlementManageFactory.setFactorySettlementAmount(factorySettlementAmount);
        // 工厂消费 = 材料费+ 管理费
        BigDecimal payMoney = settlementManageFactory.getManageAmount().add(settlementManageFactory.getMaterialAmount());
        // 工厂实际收入 = 工厂结算金额总和 - 工厂消费
        settlementManageFactory.setRealIncomeAmount(settlementManageFactory.getFactorySettlementAmount().subtract(payMoney));
        settlementManageFactoryService.save(settlementManageFactory);

        // 设置账单洗衣费
        settlementManageBill.setWashClothAmount(
                orderClothItemList.stream().map(OrderClothItem::getFactorySettlementAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add)
        );
        settlementManageBill.setStatus(SettlementBillStatusType.WAITING.getCode());
        this.updateById(settlementManageBill);
    }

    /**
     * 本月订单全部为空时，默认所有工厂都是设置为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);
        //
        settlementManageFactory.setRemark("无入厂洗衣订单");
    }

    /**
     * 工厂本月有衣服时，计算数量
     *
     * @param settlementManageFactory
     */
    private void buildHasClothFactory(SettlementManageFactory settlementManageFactory, List<OrderClothItem> orderClothItemList) {
        // 工厂结算金额总和
        settlementManageFactory.setFactorySettlementAmount(
                orderClothItemList.stream().map(OrderClothItem::getFactorySettlementAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 材料结算金额总和
        settlementManageFactory.setMaterialAmount(
                orderClothItemList.stream().map(OrderClothItem::getMaterialAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 管理结算金额总和
        settlementManageFactory.setManageAmount(
                orderClothItemList.stream().map(OrderClothItem::getManageAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add));
        // 总交易金额
        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());
    }

}
