package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.constants.BrokerageRecordConstants;
import com.zbkj.common.constants.OrderConstants;
import com.zbkj.common.constants.ProductConstants;
import com.zbkj.common.constants.SysConfigConstants;
import com.zbkj.common.dto.BrokerageConfigSnapshotDto;
import com.zbkj.common.enums.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.bcx.*;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.order.OrderDetail;
import com.zbkj.common.model.order.RefundOrder;
import com.zbkj.common.model.order.RefundOrderInfo;
import com.zbkj.common.model.product.Product;
import com.zbkj.common.model.product.ProductAttrValue;
import com.zbkj.common.model.user.User;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.BcxBrokerageConfigSearchRequest;
import com.zbkj.common.request.BcxPerformanceReportSearchRequest;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.BcxBrokerageConfigResponse;
import com.zbkj.common.response.BcxBrokerageStatisticsResponse;
import com.zbkj.common.response.BcxPerformanceReportResponse;
import com.zbkj.common.response.BcxPerformanceReportStatisticsResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.IdGeneratorSnowflake;
import com.zbkj.common.vo.DateLimitUtilVo;
import com.zbkj.service.dao.BcxPerformanceReportDao;
import com.zbkj.service.service.*;
import com.zbkj.service.service.bcx.BcxPayOfflineService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * description: 业绩报表 服务实现类
 * author : linchunpeng
 * date : 2023/8/3
 */
@Slf4j
@Service
public class BcxPerformanceReportServiceImpl extends ServiceImpl<BcxPerformanceReportDao, BcxPerformanceReport> implements BcxPerformanceReportService {
    
    @Resource
    private BcxPerformanceReportDao dao;

    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private RefundOrderService refundOrderService;
    @Autowired
    private RefundOrderInfoService refundOrderInfoService;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Autowired
    private BcxBrokerageConfigService bcxBrokerageConfigService;
    @Autowired
    private BcxDepartmentService bcxDepartmentService;
    @Autowired
    private BcxDepartmentMemberService bcxDepartmentMemberService;
    @Autowired
    private UserBrokerageRecordService userBrokerageRecordService;
    @Autowired
    private IdGeneratorSnowflake snowflake;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private BcxDepartmentMemberServeService bcxDepartmentMemberServeService;
    @Autowired
    private BcxProductBenefitsService bcxProductBenefitsService;
    @Autowired
    private BcxSettleService bcxSettleService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Resource
    private BcxPayOfflineService bcxPayOfflineService;


    /**
     * description：根据订单，把业绩报表改为冻结中
     * author：linchunpeng
     * date：2023/8/11
     */
    @Override
    @Async
    @Transactional
    public void frozenByOrder(String orderNo) {
        log.info("==================业绩报表改为冻结中==================");
        log.info("参数orderNo：{}", orderNo);
        if (StringUtils.isNotBlank(orderNo)) {
            //分布式锁key
            String lockKey = "FROZEN_BY_ORDER_" + orderNo;
            //取锁
            log.info("业绩报表改为冻结中， lockKey：{}，取锁中.....", lockKey);
            RLock lock = redissonClient.getLock(lockKey);
            //加锁，并设置过期时间 300s
            lock.lock(30, TimeUnit.SECONDS);
            log.info("取到锁");
            try {
                LambdaQueryWrapper<BcxPerformanceReport> lqw = Wrappers.lambdaQuery();
                lqw.eq(BcxPerformanceReport::getOrderNo, orderNo);
                List<BcxPerformanceReport> reportList = dao.selectList(lqw);
                if (CollectionUtil.isNotEmpty(reportList)) {
                    List<BcxPerformanceReport> updateList = new ArrayList<>();
                    Date now = new Date();
                    //冻结天数
                    Date unFreezeTime = getUnFreezeTime(now);
                    for (BcxPerformanceReport report : reportList) {
                        if (report.getSettleStatus().intValue() == BcxReportSettleStatusEnum.WAIT_EFFECTIVE.getValue().intValue()) {
                            //只有待生效的业绩，才能改为冻结中
                            if (report.getSeparateAccountStatus() != null && report.getSeparateAccountStatus() == 1) {
                                //如果是已经分账的，改为待结算
                                report.setSettleStatus(BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
                                report.setUnFreezeTime(now);
                                //同时需要解冻的企业钱包
                                bcxSettleService.unFrozenReportWithPurse(report);
                            } else {
                                report.setSettleStatus(BcxReportSettleStatusEnum.FROZEN.getValue());
                                report.setUnFreezeTime(unFreezeTime);
                            }
                            report.setUpdateTime(now);
                            updateList.add(report);
                        }
                        //分销商或分销员，修改佣金记录表的状态
                        if (report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()
                                || report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue().intValue()) {
                            userBrokerageRecordService.updateStatusByOrderNo(report.getBelongId().intValue(), report.getOrderNo(), BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_FROZEN);
                        }
                    }
                    if (CollectionUtil.isNotEmpty(updateList)) {
                        this.updateBatchById(updateList);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("业绩报表改为冻结中异常，{}", e.getMessage(), e);
                throw new CrmebException(CommonResultCode.ERROR.setMessage("业绩报表改为冻结中异常:"+e.getMessage()));
            } finally {
                if (lock.isLocked()) {
                    lock.unlock();
                }
                log.info("业绩报表改为冻结中，lockKey：{}，解锁", lockKey);
            }
        }
        log.info("==================业绩报表改为冻结中完成==================");
    }

    /**
     * description：把冻结中业绩报表改为待结算
     * author：linchunpeng
     * date：2023/8/11
     */
    @Override
    @Transactional
    public void waitSettledByFrozen() {
        log.info("==================业绩报表改为待结算==================");
        //分布式锁key
        String lockKey = "WAIT_SETTLED_BY_FROZEN";
        //取锁
        log.info("业绩报表改为待结算， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            Date now = new Date();
            LambdaQueryWrapper<BcxPerformanceReport> lqw = Wrappers.lambdaQuery();
            //冻结中
            lqw.eq(BcxPerformanceReport::getSettleStatus, BcxReportSettleStatusEnum.FROZEN.getValue());
            //解冻日期小于现在的时间
            lqw.le(BcxPerformanceReport::getUnFreezeTime, now);
            List<BcxPerformanceReport> reportList = dao.selectList(lqw);
            if (CollectionUtil.isNotEmpty(reportList)) {
                List<BcxPerformanceReport> updateList = new ArrayList<>();
                for (BcxPerformanceReport report : reportList) {
                    //改为待结算
                    report.setSettleStatus(BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
                    report.setUpdateTime(now);
                    updateList.add(report);

                    //分销商或分销员，修改佣金记录表的状态
                    if (report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()
                            || report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue().intValue()) {
                        userBrokerageRecordService.updateStatusByOrderNo(report.getBelongId().intValue(), report.getOrderNo(), BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_COMPLETE);
                    }
                }
                if (CollectionUtil.isNotEmpty(updateList)) {
                    this.updateBatchById(updateList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("业绩报表改为待结算异常，{}", e.getMessage(), e);
            throw new CrmebException(CommonResultCode.ERROR.setMessage("业绩报表改为待结算异常:"+e.getMessage()));
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
            log.info("业绩报表改为待结算，lockKey：{}，解锁", lockKey);
        }
        log.info("==================业绩报表改为待结算完成==================");
    }

//    /**
//     * description：生成业绩报表（补偿）
//     * author：linchunpeng
//     * date：2023/9/6
//     */
//    @Override
//    @Transactional
//    public void generateReportWithCompensation() {
//        List<OrderDetail> notBrokerageList = orderDetailService.getNotBrokerageList();
//        if (CollectionUtil.isNotEmpty(notBrokerageList)) {
//            Set<String> orderNoList = notBrokerageList.stream().map(OrderDetail::getOrderNo).collect(Collectors.toSet());
//            for (String orderNo : orderNoList) {
//                this.generateReport(orderNo);
//            }
//        }
//    }

    /**
     * description：根据订单编号，生成对应的业绩报表
     * author：linchunpeng
     * date：2023/8/11
     */
    @Override
    @Transactional
    public void generateReport(String orderNo) {
        log.info("==================生成业绩报表==================");
        log.info("参数orderNo：{}", orderNo);
        //分布式锁key
        String lockKey = "GENERATE_REPORT_" + orderNo;
        //取锁
        log.info("生成业绩报表， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            Order order = orderService.getByOrderNo(orderNo);
            if (order != null) {
                List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
                if (CollectionUtil.isNotEmpty(orderDetailList)) {
                    log.info("订单号：{}，订单明细数量：{}", orderNo, orderDetailList.size());
                    Date now = new Date();
                    Date unFreezeTime = null;
                    if (order.getStatus().intValue() == OrderConstants.ORDER_STATUS_COMPLETE.intValue()) {
                        //如果付完款，就是已完成，则需要把业绩报表状态改为冻结中
                        unFreezeTime = getUnFreezeTime(now);
                    }
                    //订单不为空，才需要生成业绩报表
                    String regionCode = order.getRegionCode();
                    if (StringUtils.isNotBlank(regionCode)) {
                        log.info("订单号区域：{}", regionCode);
                        List<BcxPerformanceReport> reportList = new ArrayList<>();
                        //循环每条订单明细，生成：一级分销员业绩报表、二级分销员业绩报表、渠道业绩报表、部门业绩报表、部门成员业绩报表
                        for (OrderDetail orderDetail : orderDetailList) {
                            Integer productId = orderDetail.getProductId();
                            Product product = productService.getById(productId);
                            //判断商品是否开启分销 && 订单明细未计算过业绩报表
                            if (product.getIsBrokerage() == 1 && orderDetail.getBrokerageStatus() == 0) {
                                Integer fxyRatio = Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FIRST_RATIO));
                                Integer fxsRatio = Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_SECOND_RATIO));
                                if (product.getIsSub()) {
                                    //单独配置
                                    List<ProductAttrValue> skuList = productAttrValueService.getListByProductIdAndType(productId, 0);
                                    if (CollectionUtil.isNotEmpty(skuList)) {
                                        fxyRatio = skuList.get(0).getBrokerage();
                                        fxsRatio = skuList.get(0).getBrokerageTwo();
                                    }
                                }
                                log.info("商品id：{}，商品名称：{}有开启分销，是否单独计算分佣：{}，一级比例：{}， 二级比例：{}",
                                        product.getId(), product.getName(), product.getIsSub() ? "是" : "否", fxyRatio, fxsRatio);
                                Integer brokerageTotal = fxyRatio + fxsRatio;
                                //一级分销员
                                User first = null;
                                //二级分销员
                                User second = null;
                                //购买者
                                User buyer = userService.getById(orderDetail.getUid());
                                if (orderDetail.getUid() != null && orderDetail.getUid() != 0) {
                                    if (buyer.getSpreadUid() != null && buyer.getSpreadUid() != 0) {
                                        //说明有上级分销员
                                        first = userService.getById(buyer.getSpreadUid());
                                        if (first.getSpreadUid() != null && first.getSpreadUid() != 0) {
                                            //说明有上级分销员
                                            second = userService.getById(first.getSpreadUid());
                                        }
                                    }
                                }
                                //分销员所属公司id
                                String companyId = null;
                                if (first != null && first.getUserType() == 1) {
                                    //企业账号，companyId就是本身
                                    log.info("一级分销员是企业账号，companyId就是本身");
                                    companyId = first.getAccount();
                                } else if (second != null && second.getUserType() == 1) {
                                    //其他账号取上级的账号
                                    log.info("二级分销员是企业账号，companyId就是上级");
                                    companyId = second.getAccount();
                                }
                                //判断一级分销员，所属公司，有没有授权分销商品，如果有，才给计算佣金
                                boolean isCalcBrokerage = false;
                                if (StringUtils.isNotBlank(companyId)) {
                                    List<BcxProductBenefits> productBenefitsList = bcxProductBenefitsService.findListByCompanyId(companyId);
                                    if (CollectionUtil.isNotEmpty(productBenefitsList)) {
                                        for (BcxProductBenefits bcxProductBenefits : productBenefitsList) {
                                            log.info("公司id：{}，授权商品id：{}，授权商品id：{}", companyId, bcxProductBenefits.getProductId(), bcxProductBenefits.getProductName());
                                            if (bcxProductBenefits.getProductId().intValue() == product.getId().intValue()) {
                                                //授权分销商品列表，包含订单商品，可以计算分销
                                                isCalcBrokerage = true;
                                                //判断分销商是否单独设置分销比例
                                                if (bcxProductBenefits.getIsEnableConfig() == 1) {
                                                    //分销商启用单独配置分销比例
                                                    fxyRatio = bcxProductBenefits.getBrokerage();
                                                    fxsRatio = brokerageTotal - fxyRatio;
                                                }
                                                break;
                                            }
                                        }
                                    } else {
                                        log.info("公司id：{}，没有授权分销商品", companyId);
                                    }
                                    log.info("是否可以计算一级二级分销：{}", isCalcBrokerage);
                                } else {
                                    log.info("分销员所属公司id为空，不计算一级二级佣金");
                                }

                                //最多可分佣金额
                                BigDecimal maxBrokeragePrice = product.getMaxBrokerage() == null ? orderDetail.getCanBrokeragePrice() : orderDetail.getCanBrokeragePrice().multiply(product.getMaxBrokerage()).divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
                                log.info("订单号：{}，商品：{}，最多可分佣金额：{}", orderNo, product.getName(), maxBrokeragePrice.toPlainString());
                                log.info("购买者id：{}，一级分销员：{}，二级分销员：{}", orderDetail.getUid(), first == null ? "" : first.getRealName(), second == null ? "" : second.getRealName());
                                //是否单独分佣
                                Integer searchProductId = product.getIsSub() ? productId : null;
                                //渠道佣金配置列表
                                List<BcxBrokerageConfigResponse> channelConfigList = bcxBrokerageConfigService.getList(
                                        new BcxBrokerageConfigSearchRequest(searchProductId, BcxBrokerageConfigBelongTypeEnum.CHANNEL.getValue(), regionCode));
                                //业务渠道佣金配置列表
                                List<BcxBrokerageConfigResponse> businessChannelConfigList = channelConfigList.stream()
                                        .filter(config -> config.getChannelType() != null
                                                && config.getChannelType().intValue() == ChangeTypeEnum.BUSINESS.getValue().intValue())
                                        .collect(Collectors.toList());
                                //区域渠道佣金配置列表
                                List<BcxBrokerageConfigResponse> regionChannelConfigList = channelConfigList.stream()
                                        .filter(config -> config.getChannelType() != null
                                                && config.getChannelType().intValue() == ChangeTypeEnum.REGION.getValue().intValue())
                                        .collect(Collectors.toList());

                                //部门佣金配置列表
                                List<BcxBrokerageConfigResponse> departmentConfigList = bcxBrokerageConfigService.getList(
                                        new BcxBrokerageConfigSearchRequest(searchProductId, BcxBrokerageConfigBelongTypeEnum.DEPARTMENT.getValue(), regionCode));
                                //部门成员佣金配置列表
                                List<BcxBrokerageConfigResponse> departmentMemberConfigList = bcxBrokerageConfigService.getList(
                                        new BcxBrokerageConfigSearchRequest(searchProductId, BcxBrokerageConfigBelongTypeEnum.DEPARTMENT_MEMBER.getValue(), regionCode));

                                //分销订单类型，判断分销订单类型，0：无分销（没有一级、二级）  1：普通分销  2：业务渠道分销  3：区域渠道分销  4：部门成员分销
                                int brokerageOrderType = this.getBrokerageOrderType(first, second, businessChannelConfigList, regionChannelConfigList, departmentMemberConfigList);

                                if (brokerageOrderType == BrokerageOrderTypeEnum.NOTHING.getValue()) {
                                    log.info("订单号：{}，分销订单类型为：无分销：区域渠道（满的）、部门，分佣", orderNo);
                                } else if (brokerageOrderType == BrokerageOrderTypeEnum.NORMAL.getValue()) {
                                    log.info("订单号：{}，分销订单类型为：普通分销，分销商（一级、二级）、区域渠道（打折）、部门，分佣", orderNo);
                                } else if (brokerageOrderType == BrokerageOrderTypeEnum.BUSINESS_CHANNEL.getValue()) {
                                    log.info("订单号：{}，分销订单类型为：业务渠道分销，业务渠道、区域渠道（打折）、部门，分佣", orderNo);
                                } else if (brokerageOrderType == BrokerageOrderTypeEnum.REGION_CHANNEL.getValue()) {
                                    log.info("订单号：{}，分销订单类型为：区域渠道分销，区域渠道（满的）、部门，分佣", orderNo);
                                } else if (brokerageOrderType == BrokerageOrderTypeEnum.DEPARTMENT_MEMBER.getValue()) {
                                    log.info("订单号：{}，分销订单类型为：部门成员分销，区域渠道（满的）、部门、部门成员，分佣", orderNo);
                                }

                                //无分销： 区域渠道（满的）、部门，分佣
                                //普通分销，分销商（一级、二级）、区域渠道（打折）、部门，分佣
                                //业务渠道分销，业务渠道、区域渠道（打折）、部门，分佣
                                //区域渠道分销，区域渠道（满的）、部门，分佣
                                //部门成员分销，区域渠道（满的）、部门、部门成员，分佣

                                BigDecimal brokeragePriceTotal = new BigDecimal(0);
                                //佣金配置快照
                                BrokerageConfigSnapshotDto brokerageConfigSnapshotDto = new BrokerageConfigSnapshotDto(order, orderDetail, product);
                                if (isCalcBrokerage
                                        && brokerageOrderType == BrokerageOrderTypeEnum.NORMAL.getValue()
                                        && maxBrokeragePrice.compareTo(BigDecimal.ZERO) > 0) {
                                    //普通分销，一级分销员分佣
                                    BigDecimal fxyRatioBigDecimal = new BigDecimal(fxyRatio);
                                    BigDecimal firstBrokerageFee = orderDetail.getCanBrokeragePrice().multiply(fxyRatioBigDecimal)
                                            .divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
                                    brokeragePriceTotal = brokeragePriceTotal.add(firstBrokerageFee);
                                    log.info("一级分销员分佣：{}", firstBrokerageFee.toPlainString());
                                    if (firstBrokerageFee.compareTo(BigDecimal.ZERO) > 0) {
                                        BcxPerformanceReport report = this.createReport(first.getId().longValue(), BcxPerformanceReportBelongTypeEnum.USER_FXY,
                                                order, orderDetail, product.getIsSub(), JSONObject.toJSONString(brokerageConfigSnapshotDto),
                                                BrokerageConfigTypeEnum.RATIO.getValue(), fxyRatioBigDecimal,
                                                new BigDecimal(100), firstBrokerageFee, now, unFreezeTime, false);
                                        maxBrokeragePrice = maxBrokeragePrice.subtract(report.getBrokeragePrice());

                                        log.info("计算出可分佣金额：{}", report.getBrokeragePrice().toPlainString());
                                        log.info("当前剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());

                                        if (maxBrokeragePrice.compareTo(BigDecimal.ZERO) < 0) {
                                            //最多可分佣金额 - 佣金 < 0，说明钱不够分了，需要重新设置可分金额
                                            report.setBrokeragePrice(maxBrokeragePrice.add(report.getBrokeragePrice()));
                                            log.info("计算出可分佣金额 > 当前剩余可分佣金额，重置可分佣金额：{}", report.getBrokeragePrice().toPlainString());
                                        }
                                        reportList.add(report);
                                        log.info("剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());
                                    }
                                }
                                if (isCalcBrokerage
                                        && brokerageOrderType == BrokerageOrderTypeEnum.NORMAL.getValue()
                                        && second != null
                                        && maxBrokeragePrice.compareTo(BigDecimal.ZERO) > 0) {
                                    //普通分销，二级分销员分佣
                                    BigDecimal fxsRatioBigDecimal = new BigDecimal(fxsRatio);
                                    BigDecimal secondBrokerageFee = orderDetail.getCanBrokeragePrice().multiply(fxsRatioBigDecimal)
                                            .divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
                                    brokeragePriceTotal = brokeragePriceTotal.add(secondBrokerageFee);
                                    log.info("二级分销员分佣：{}", secondBrokerageFee.toPlainString());
                                    if (secondBrokerageFee.compareTo(BigDecimal.ZERO) > 0) {
                                        BcxPerformanceReport report = this.createReport(second.getId().longValue(), BcxPerformanceReportBelongTypeEnum.USER_FXS,
                                                order, orderDetail, product.getIsSub(), JSONObject.toJSONString(brokerageConfigSnapshotDto),
                                                BrokerageConfigTypeEnum.RATIO.getValue(), fxsRatioBigDecimal,
                                                new BigDecimal(100),  secondBrokerageFee, now, unFreezeTime, false);
                                        report.setBrokeragePriceTotal(brokeragePriceTotal);
                                        maxBrokeragePrice = maxBrokeragePrice.subtract(report.getBrokeragePrice());

                                        log.info("计算出可分佣金额：{}", report.getBrokeragePrice().toPlainString());
                                        log.info("当前剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());

                                        if (maxBrokeragePrice.compareTo(BigDecimal.ZERO) < 0) {
                                            //最多可分佣金额 - 佣金 < 0，说明钱不够分了，需要重新设置可分金额
                                            report.setBrokeragePrice(maxBrokeragePrice.add(report.getBrokeragePrice()));
                                            log.info("计算出可分佣金额 > 当前剩余可分佣金额，重置可分佣金额：{}", report.getBrokeragePrice().toPlainString());
                                        }
                                        reportList.add(report);
                                        log.info("剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());
                                    }
                                }

                                brokerageConfigSnapshotDto.setMaxBrokeragePrice(maxBrokeragePrice);

                                if (brokerageOrderType == BrokerageOrderTypeEnum.BUSINESS_CHANNEL.getValue() && CollectionUtil.isNotEmpty(businessChannelConfigList)) {
                                    //业务渠道分佣
                                    BcxBrokerageConfigResponse configResponse = null;
                                    for (BcxBrokerageConfigResponse response : businessChannelConfigList) {
                                        if (first != null && response.getBelongId() == first.getId().longValue()) {
                                            //一级，在：业务渠道  里面，则是：业务渠道分销
                                            configResponse = response;
                                            break;
                                        }
                                        if (second != null && response.getBelongId() == second.getId().longValue()) {
                                            //二级，在：业务渠道  里面，则是：业务渠道分销
                                            configResponse = response;
                                            break;
                                        }
                                    }
                                    if (configResponse != null) {
                                        reportList.addAll(this.createReport(Collections.singletonList(configResponse), BcxPerformanceReportBelongTypeEnum.CHANNEL,
                                                order, orderDetail, product.getIsSub(), false, brokerageConfigSnapshotDto,
                                                now, unFreezeTime, false));
                                    }
                                }

                                if (CollectionUtil.isNotEmpty(regionChannelConfigList)) {
                                    //区域渠道分佣
                                    boolean isDiscount = brokerageOrderType == BrokerageOrderTypeEnum.NORMAL.getValue()
                                            || brokerageOrderType == BrokerageOrderTypeEnum.BUSINESS_CHANNEL.getValue();
                                    //普通分销，区域渠道（打折）
                                    //业务渠道分销，区域渠道（打折）
                                    List<BcxPerformanceReport> changeReportList = this.createReport(regionChannelConfigList, BcxPerformanceReportBelongTypeEnum.CHANNEL,
                                            order, orderDetail, product.getIsSub(), isDiscount, brokerageConfigSnapshotDto,
                                            now, unFreezeTime, false);
                                    if (CollectionUtil.isNotEmpty(changeReportList) &&
                                            order.getBizType().intValue() == ProductConstants.BIZ_TYPE_RISK.intValue()) {
                                        //如果是风评订单，需要马上进行转账
                                        for (BcxPerformanceReport report : changeReportList) {
                                            BcxPayOffline offline = bcxPayOfflineService.queryByOrderNo(order.getOrderNo());
                                            if (offline.getStatus() == 3 && bcxSettleService.settleReportWithPurse(report)) {
                                                report.setSeparateAccountStatus(1);
                                            }
                                        }
                                    }
                                    reportList.addAll(changeReportList);
                                }

                                if (CollectionUtil.isNotEmpty(departmentConfigList)) {
                                    //部门分佣
                                    reportList.addAll(this.createReport(departmentConfigList, BcxPerformanceReportBelongTypeEnum.DEPARTMENT,
                                            order, orderDetail, product.getIsSub(), false, brokerageConfigSnapshotDto,
                                            now, unFreezeTime, false));
                                }

                                if (CollectionUtil.isNotEmpty(departmentMemberConfigList)) {
                                    //部门成员-服务绩效分佣
                                    List<String> orgIdList = new ArrayList<>();
                                    if (buyer != null && buyer.getAccount().startsWith("org_")) {
                                        orgIdList.add(buyer.getAccount().substring(4));
                                    }
                                    if (first != null && first.getAccount().startsWith("org_")) {
                                        orgIdList.add(first.getAccount().substring(4));
                                    }
                                    if (second != null && second.getAccount().startsWith("org_")) {
                                        orgIdList.add(second.getAccount().substring(4));
                                    }
                                    for (BcxBrokerageConfigResponse configResponse : departmentMemberConfigList) {
                                        if (bcxDepartmentMemberServeService.isDepartmentMemberServe(configResponse.getBcxId(), orgIdList)
                                                && configResponse.getServiceRatio() != null
                                                && configResponse.getServiceRatio().compareTo(BigDecimal.ZERO) > 0) {
                                            //判断是否在成员服务的公司范围里面，且服务绩效>0
                                            reportList.addAll(this.createReport(Collections.singletonList(configResponse), BcxPerformanceReportBelongTypeEnum.DEPARTMENT_MEMBER,
                                                    order, orderDetail, product.getIsSub(), false, brokerageConfigSnapshotDto,
                                                    now, unFreezeTime, true));
                                        }
                                    }
                                }

                                if (brokerageOrderType == BrokerageOrderTypeEnum.DEPARTMENT_MEMBER.getValue() && CollectionUtil.isNotEmpty(departmentMemberConfigList)) {
                                    //部门成员分销，部门成员分佣
                                    Long memberId = -1L;
                                    List<Long> departmentMemberIdList = departmentMemberConfigList.stream().map(BcxBrokerageConfigResponse::getBelongId).collect(Collectors.toList());
                                    List<BcxDepartmentMember> departmentMemberList = bcxDepartmentMemberService.listByIds(departmentMemberIdList);
                                    for (BcxDepartmentMember departmentMember : departmentMemberList) {
                                        String account = "emp_" + departmentMember.getBcxId();
                                        if (first != null && account.equals(first.getAccount())) {
                                            //一级，在：部门成员  里面，则是：部门成员分销
                                            memberId = departmentMember.getId();
                                            break;
                                        }
                                    }
                                    Long finalMemberId = memberId;
                                    Optional<BcxBrokerageConfigResponse> configResponseOptional = departmentMemberConfigList.stream().filter(config -> config.getBelongId().longValue() == finalMemberId.longValue()).findFirst();
                                    if (configResponseOptional.isPresent()) {
                                        reportList.addAll(this.createReport(Collections.singletonList(configResponseOptional.get()), BcxPerformanceReportBelongTypeEnum.DEPARTMENT_MEMBER,
                                                order, orderDetail, product.getIsSub(), false, brokerageConfigSnapshotDto,
                                                now, unFreezeTime, false));
                                    }
                                }
                                //修改订单明细分佣状态
                                orderDetail.setBrokerageStatus(1);
                                orderDetailService.updateById(orderDetail);
                            }
                        }
                        //保存入库
                        log.info("保存入库");
                        if (CollectionUtil.isNotEmpty(reportList)) {
                            log.info("保存入库数量：{}", reportList.size());
                            this.saveBatch(reportList);
                        }
                    } else {
                        log.info("订单号：{}，区域为空，不纳入计算分销", orderNo);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成业绩报表异常，{}", e.getMessage(), e);
            throw new CrmebException(CommonResultCode.ERROR.setMessage("生成业绩报表异常:"+e.getMessage()));
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
            log.info("生成业绩报表，lockKey：{}，解锁", lockKey);
        }
        log.info("==================生成业绩报表完成==================");
    }


    /**
     判断分销订单类型，0：无分销（没有一级、二级）  1：普通分销  2：业务渠道分销  3：区域渠道分销  4：部门成员分销
     一级、二级，都没有，则是：无分销
     一级、二级，都不在：业务渠道、区域渠道、部门成员  里面，则是：普通分销
     一级、二级，只要有一个在：业务渠道  里面，则是：业务渠道分销
     一级、二级，只要有一个在：区域渠道  里面，则是：区域渠道分销
     一级、二级，只要有一个在：部门成员  里面，则是：部门成员分销
     */
    private int getBrokerageOrderType(User first, User second, List<BcxBrokerageConfigResponse> businessChannelConfigList,
                                      List<BcxBrokerageConfigResponse> regionChannelConfigList,
                                      List<BcxBrokerageConfigResponse> departmentMemberConfigList) {
        //业务渠道id列表
        List<Long> businessChannelIdList = CollectionUtil.isEmpty(businessChannelConfigList) ? Collections.singletonList(-1L) : businessChannelConfigList.stream().map(BcxBrokerageConfigResponse::getBelongId).collect(Collectors.toList());
        //区域渠道id列表
        List<Long> regionChannelIdList = CollectionUtil.isEmpty(regionChannelConfigList) ? Collections.singletonList(-1L) : regionChannelConfigList.stream().map(BcxBrokerageConfigResponse::getBelongId).collect(Collectors.toList());
        List<Long> departmentMemberIdList = CollectionUtil.isEmpty(departmentMemberConfigList) ? Collections.singletonList(-1L) : departmentMemberConfigList.stream().map(BcxBrokerageConfigResponse::getBelongId).collect(Collectors.toList());
        List<BcxDepartmentMember> departmentMemberList = bcxDepartmentMemberService.listByIds(departmentMemberIdList);
        //部门成员account列表
        List<String> departmentMemberBcxIdList = CollectionUtil.isEmpty(departmentMemberList) ? Collections.singletonList("-1") : departmentMemberList.stream().map(member -> "emp_" + member.getBcxId()).collect(Collectors.toList());
        log.info("业务渠道id列表：{}", businessChannelIdList);
        log.info("区域渠道id列表：{}", regionChannelIdList);
        log.info("部门成员account列表，brokerageOrderType：{}", departmentMemberBcxIdList);

        //分销订单类型，默认无分销
        int brokerageOrderType = BrokerageOrderTypeEnum.NOTHING.getValue();
        //一级、二级，都不在：业务渠道、区域渠道、部门成员  里面，则是：普通分销
        if ((first != null || second != null)
                && (first == null || (!businessChannelIdList.contains(first.getId().longValue())
                && !regionChannelIdList.contains(first.getId().longValue())
                && !departmentMemberBcxIdList.contains(first.getAccount())))
                && (second == null || (!businessChannelIdList.contains(second.getId().longValue())
                && !regionChannelIdList.contains(second.getId().longValue())
                && !departmentMemberBcxIdList.contains(second.getAccount())))) {
            log.info("一级、二级，都不在：业务渠道、区域渠道、部门成员  里面，则是：普通分销，brokerageOrderType：{}", brokerageOrderType);
            brokerageOrderType = BrokerageOrderTypeEnum.NORMAL.getValue();
        } else {
            if (first != null) {
                if (businessChannelIdList.contains(first.getId().longValue())) {
                    //一级，在：业务渠道  里面，则是：业务渠道分销
                    log.info("一级，在：业务渠道  里面，则是：业务渠道分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.BUSINESS_CHANNEL.getValue();
                } else if (regionChannelIdList.contains(first.getId().longValue())) {
                    //一级，在：区域渠道  里面，则是：区域渠道分销
                    log.info("一级，在：区域渠道  里面，则是：区域渠道分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.REGION_CHANNEL.getValue();
                } else if (departmentMemberBcxIdList.contains(first.getAccount())) {
                    //一级，在：部门成员  里面，则是：部门成员分销
                    log.info("一级，在：部门成员  里面，则是：部门成员分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.DEPARTMENT_MEMBER.getValue();
                }
            }
            if (second != null && brokerageOrderType == 0) {
                if (businessChannelIdList.contains(second.getId().longValue())) {
                    //二级，在：业务渠道  里面，则是：业务渠道分销
                    log.info("二级，在：业务渠道  里面，则是：业务渠道分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.BUSINESS_CHANNEL.getValue();
                } else if (regionChannelIdList.contains(second.getId().longValue())) {
                    //二级，在：区域渠道  里面，则是：区域渠道分销
                    log.info("二级，在：区域渠道  里面，则是：区域渠道分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.REGION_CHANNEL.getValue();
                }/* else if (departmentMemberBcxIdList.contains(second.getAccount())) {
                    //二级，在：部门成员  里面，则是：部门成员分销
                    log.info("二级，在：部门成员  里面，则是：部门成员分销，brokerageOrderType：{}", brokerageOrderType);
                    brokerageOrderType = BrokerageOrderTypeEnum.DEPARTMENT_MEMBER.getValue();
                }*/
            }
        }
        return brokerageOrderType;
    }

    /**
     * description：根据分佣配置，创建业绩报表列表
     * author：linchunpeng
     * date：2023/8/11
     */
    private List<BcxPerformanceReport> createReport(List<BcxBrokerageConfigResponse> configList, BcxPerformanceReportBelongTypeEnum belongTypeEnum,
                                                    Order order, OrderDetail orderDetail, boolean isSub, boolean isDiscount,
                                                    BrokerageConfigSnapshotDto brokerageConfigSnapshotDto, Date now, Date unFreezeTime,
                                                    boolean isServe) {
        List<BcxPerformanceReport> list = new ArrayList<>();
        BigDecimal maxBrokeragePrice = brokerageConfigSnapshotDto.getMaxBrokeragePrice();
        for (BcxBrokerageConfigResponse configResponse : configList) {
            if (maxBrokeragePrice.compareTo(BigDecimal.ZERO) > 0) {
                //佣金配置存入快照
                brokerageConfigSnapshotDto.setBcxBrokerageConfig(configResponse);
                //佣金
                BigDecimal brokeragePrice = BigDecimal.ZERO;
                //判断是不是部门成员的服务绩效
                BigDecimal ratio = isServe ? configResponse.getServiceRatio() : configResponse.getRatio();
                BigDecimal payNum = new BigDecimal(orderDetail.getPayNum());
                if (configResponse.getType().intValue() == BrokerageConfigTypeEnum.RATIO.getValue().intValue()) {
                    //按比例，计算佣金
                    brokeragePrice = orderDetail.getCanBrokeragePrice().multiply(ratio)
                            .divide(new BigDecimal("100"), 2, RoundingMode.DOWN);
                } else if (configResponse.getType().intValue() == BrokerageConfigTypeEnum.FIXATION.getValue().intValue()) {
                    //按固定金额，计算佣金
//                    if (ratio.compareTo(orderDetail.getCanBrokeragePrice()) > 0) {
//                        //固定金额 > 实付金额，最多给实付金额
//                        brokeragePrice = orderDetail.getCanBrokeragePrice();
//                    } else {
                        brokeragePrice = ratio.multiply(payNum);
//                    }
                } else if (configResponse.getType().intValue() == BrokerageConfigTypeEnum.RETENTION.getValue().intValue()) {
                    //按自留金额，计算佣金
                    BigDecimal price = orderDetail.getCanBrokeragePrice().divide(payNum, 2, RoundingMode.DOWN);
                    if (ratio.compareTo(price) < 0) {
                        //自留金额 < 实付单价，才有佣金
                        brokeragePrice = price.subtract(ratio).multiply(payNum);
                    }
                }
                BigDecimal brokerageCalculateRatio = new BigDecimal("100");
                if (isDiscount) {
                    //打折
                    log.info("有产生分佣冲突，打折，按照计算系数进行计算");
                    brokerageCalculateRatio = configResponse.getCalculateRatio();
                    brokeragePrice = brokeragePrice.multiply(brokerageCalculateRatio)
                            .divide(new BigDecimal("100"), 2, RoundingMode.DOWN);

                }
                log.info("计算出可分佣金额：{}", brokeragePrice.toPlainString());
                log.info("当前剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());

                maxBrokeragePrice = maxBrokeragePrice.subtract(brokeragePrice);
                if (maxBrokeragePrice.compareTo(BigDecimal.ZERO) < 0) {
                    //最多可分佣金额 - 佣金 < 0，说明钱不够分了，需要重新设置可分金额
                    brokeragePrice = maxBrokeragePrice.add(brokeragePrice);
                    log.info("计算出可分佣金额 > 当前剩余可分佣金额，重置可分佣金额：{}", brokeragePrice.toPlainString());
                }
                log.info("分销类型：{}，名称：{}，佣金类型：{}, 计算系数：{}, 分佣金额：{}", belongTypeEnum.getName(), configResponse.getName(),
                        BrokerageConfigTypeEnum.getInstance(configResponse.getType()).getValue(), configResponse.getCalculateRatio().toPlainString(),
                        brokeragePrice.toPlainString());

                if (brokeragePrice.compareTo(BigDecimal.ZERO) > 0) {
                    list.add(this.createReport(configResponse.getBelongId(), belongTypeEnum, order, orderDetail, isSub,
                            JSONObject.toJSONString(brokerageConfigSnapshotDto), configResponse.getType(), ratio,
                            brokerageCalculateRatio, brokeragePrice, now, unFreezeTime, isServe));
                }
                log.info("剩余可分佣金额：{}", maxBrokeragePrice.toPlainString());
            }
        }
        brokerageConfigSnapshotDto.setMaxBrokeragePrice(maxBrokeragePrice);
        return list;
    }


    /**
     * description：创建业绩报表
     * author：linchunpeng
     * date：2023/8/11
     */
    private BcxPerformanceReport createReport(Long belongId, BcxPerformanceReportBelongTypeEnum belongType,
                                              Order order, OrderDetail orderDetail, boolean isSub,
                                              String brokerageConfigSnapshot, Integer brokerageType,
                                              BigDecimal brokerageRatio, BigDecimal brokerageCalculateRatio,
                                              BigDecimal brokeragePrice, Date now, Date unFreezeTime, boolean isServe) {
        BcxPerformanceReport report = new BcxPerformanceReport();
        report.setId(snowflake.snowflakeId());
        report.setBelongId(belongId);
        report.setBelongType(belongType.getValue());

        report.setOrderId(order.getId());
        report.setOrderNo(order.getOrderNo());
        report.setOrderUserId(orderDetail.getUid());
        report.setOrderTime(orderDetail.getCreateTime());
        report.setOrderDetailId(orderDetail.getId());
        report.setProductId(orderDetail.getProductId());
        report.setProductName(orderDetail.getProductName());
        report.setAttrValueId(orderDetail.getAttrValueId());
        report.setSku(orderDetail.getSku());
        report.setPayPrice(orderDetail.getCanBrokeragePrice());
        if (brokerageCalculateRatio.compareTo(new BigDecimal(100)) == 0) {
            report.setPayPriceCalculate(orderDetail.getCanBrokeragePrice());
        } else {
            report.setPayPriceCalculate(orderDetail.getCanBrokeragePrice().multiply(brokerageCalculateRatio)
                    .divide(new BigDecimal("100"), 2, RoundingMode.DOWN));
        }
        report.setBrokerageConfigType(isSub ? 2 : 1);
        report.setBrokerageConfigSnapshot(brokerageConfigSnapshot);
        report.setIsServe(isServe ? 1 : 0);
        report.setBrokerageType(brokerageType);
        report.setBrokerageRatio(brokerageRatio);
        report.setBrokerageCalculateRatio(brokerageCalculateRatio);
        report.setBrokeragePrice(brokeragePrice);
        report.setCanRefundPrice(brokeragePrice);
        if (order.getStatus().intValue() == OrderConstants.ORDER_STATUS_COMPLETE.intValue()) {
            //如果付完款，就是已完成，则需要把业绩报表状态改为冻结中
            report.setSettleStatus(BcxReportSettleStatusEnum.FROZEN.getValue());
            report.setUnFreezeTime(unFreezeTime == null ? now : unFreezeTime);
        } else {
            report.setSettleStatus(BcxReportSettleStatusEnum.WAIT_EFFECTIVE.getValue());
        }
        report.setSeparateAccountStatus(0);
        report.setCreateTime(now);
        report.setUpdateTime(now);

        return report;
    }


    /**
     * description：根据退款单订单编号，生成对应的退款单业绩报表
     * author：linchunpeng
     * date：2023/8/11
     */
    @Override
    @Async
    @Transactional
    public void generateRefundReport(String refundOrderNo) {
        log.info("==================生成退款单业绩报表==================");
        log.info("参数refundOrderNo：{}", refundOrderNo);
        //分布式锁keyL
        String lockKey = "GENERATE_REFUND_REPORT_" + refundOrderNo;
        //取锁
        log.info("生成退款单业绩报表， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            RefundOrder refundOrder = refundOrderService.getByRefundOrderNo(refundOrderNo);
            if (refundOrder != null) {
                List<RefundOrderInfo> refundOrderInfoList = refundOrderInfoService.getListByRefundOrderNo(refundOrderNo);
                if (CollectionUtil.isNotEmpty(refundOrderInfoList)) {
                    log.info("退款订单号：{}，退款订单明细数量：{}", refundOrderNo, refundOrderInfoList.size());
                    List<BcxPerformanceReport> reportList = new ArrayList<>();
                    for (RefundOrderInfo refundOrderInfo : refundOrderInfoList) {
                        if (refundOrderInfo.getBrokerageStatus() != 0) {
                            log.info("退款订单明细id：{}，已生成退款订单业绩报表，不能重复生成", refundOrderInfo.getId());
                            continue;
                        }
                        //查询退款订单明细对应的订单明细产生的原业绩报表
                        List<BcxPerformanceReport> originalReportList = this.listByOrderDetailId(refundOrderInfo.getOrderDetailId());
                        if (CollectionUtil.isEmpty(originalReportList)) {
                            log.info("退款订单明细id：{}，无已产生的业绩报表，不需要生成退款订单业绩报表", refundOrderInfo.getId());
                            continue;
                        }
                        log.info("退款订单明细id：{}，已产生的业绩报表数量：{}", refundOrderInfo.getId(), originalReportList.size());
                        //退款单，就是已完成，则需要把业绩报表状态改为冻结中
                        Date now = new Date();
                        Date unFreezeTime = getUnFreezeTime(now);
                        reportList.addAll(createRefundReport(originalReportList, refundOrder, refundOrderInfo, now, unFreezeTime));
                        //修改退款订单明细分佣状态
                        refundOrderInfo.setBrokerageStatus(1);
                        refundOrderInfoService.updateById(refundOrderInfo);
                    }
                    //保存入库
                    log.info("保存入库");
                    if (CollectionUtil.isNotEmpty(reportList)) {
                        log.info("保存入库数量：{}", reportList.size());
                        this.saveBatch(reportList);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成退款单业绩报表异常，{}", e.getMessage(), e);
            throw new CrmebException(CommonResultCode.ERROR.setMessage("生成退款单业绩报表异常:"+e.getMessage()));
        } finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
            log.info("生成退款单业绩报表，lockKey：{}，解锁", lockKey);
        }
        log.info("==================生成退款单业绩报表完成==================");
    }


    /**
     * description：根据业绩报表、退款单，创建退款单的业绩报表列表
     * author：linchunpeng
     * date：2023/8/11
     */
    private List<BcxPerformanceReport> createRefundReport(List<BcxPerformanceReport> performanceReportList, RefundOrder refundOrder,
                                                          RefundOrderInfo refundOrderInfo, Date now, Date unFreezeTime) {
        List<BcxPerformanceReport> list = new ArrayList<>();
        for (BcxPerformanceReport originalReport : performanceReportList) {
            if (originalReport.getSettleStatus().intValue() == BcxReportSettleStatusEnum.WAIT_EFFECTIVE.getValue().intValue()) {
                //如果是待生效的状态，需要改为冻结中
                originalReport.setSettleStatus(BcxReportSettleStatusEnum.FROZEN.getValue());
                originalReport.setUnFreezeTime(unFreezeTime);
                originalReport.setUpdateTime(now);

            }

            //计算退款佣金，和黎总确认，不存在退一半的情况
            BigDecimal brokeragePrice = refundOrderInfo.getRefundPrice().negate();

//            //佣金
//            BigDecimal brokeragePrice = BigDecimal.ZERO;
//            //判断是不是部门成员的服务绩效
//            BigDecimal ratio = originalReport.getBrokerageRatio();
//            if (originalReport.getBrokerageType().intValue() == BrokerageConfigTypeEnum.RATIO.getValue().intValue()) {
//                //按比例，计算佣金
//                brokeragePrice = refundOrderInfo.getRefundPrice().multiply(ratio)
//                        .divide(new BigDecimal("100"), 2, RoundingMode.DOWN).negate();
//            } else if (originalReport.getBrokerageType().intValue() == BrokerageConfigTypeEnum.FIXATION.getValue().intValue()) {
//                //按固定金额，计算佣金
//                brokeragePrice = refundOrderInfo.getRefundPrice().negate();
//            } else if (originalReport.getBrokerageType().intValue() == BrokerageConfigTypeEnum.RETENTION.getValue().intValue()) {
//                //按自留金额，计算佣金
//                brokeragePrice = refundOrderInfo.getRefundPrice().negate();
//            }


            //能退款的佣金余额 = 能退款的佣金余额 + (-佣金)
            BigDecimal canRefundPrice = originalReport.getCanRefundPrice().add(brokeragePrice);
            if (canRefundPrice.compareTo(BigDecimal.ZERO) < 0) {
                log.info("分销belongType：{}，belongId：{}，能退款的佣金余额不足，不能产生退款业绩报表", originalReport.getBelongType(), originalReport.getBelongId());
                continue;
            }
            originalReport.setCanRefundPrice(canRefundPrice);
            this.updateById(originalReport);
            log.info("分销belongType：{}，belongId：{}，退款佣金：{}", originalReport.getBelongType(), originalReport.getBelongId(), brokeragePrice.toPlainString());
            list.add(this.createRefundReport(originalReport, refundOrder, refundOrderInfo, brokeragePrice, now, unFreezeTime));
        }
        return list;
    }


    /**
     * description：创建退款单业绩报表
     * author：linchunpeng
     * date：2023/8/11
     */
    private BcxPerformanceReport createRefundReport(BcxPerformanceReport originalReport, RefundOrder refundOrder,
                                                    RefundOrderInfo refundOrderInfo, BigDecimal brokeragePrice,
                                                    Date now, Date unFreezeTime) {
        BcxPerformanceReport report = new BcxPerformanceReport();
        report.setId(snowflake.snowflakeId());
        report.setBelongId(originalReport.getBelongId());
        report.setBelongType(originalReport.getBelongType());

        report.setOrderId(originalReport.getOrderId());
        report.setOrderNo(originalReport.getOrderNo());
        report.setOrderUserId(originalReport.getOrderUserId());
        report.setOrderTime(originalReport.getOrderTime());
        report.setOrderDetailId(originalReport.getOrderDetailId());
        report.setProductId(originalReport.getProductId());
        report.setProductName(originalReport.getProductName());
        report.setAttrValueId(originalReport.getAttrValueId());
        report.setSku(originalReport.getSku());
        //退款单
        report.setRefundOrderId(refundOrder.getId());
        report.setRefundOrderNo(refundOrder.getRefundOrderNo());
        report.setRefundOrderInfoId(refundOrderInfo.getId());

        report.setPayPrice(originalReport.getPayPrice());
        report.setBrokerageConfigType(originalReport.getBrokerageConfigType());
        report.setBrokerageConfigSnapshot(originalReport.getBrokerageConfigSnapshot());
        report.setIsServe(originalReport.getIsServe());
        report.setBrokerageType(originalReport.getBrokerageType());
        report.setBrokerageRatio(originalReport.getBrokerageRatio());
        report.setBrokerageCalculateRatio(originalReport.getBrokerageCalculateRatio());
        report.setBrokeragePrice(brokeragePrice);
        //负数，表示退款的，不能再次退款
        report.setCanRefundPrice(BigDecimal.ZERO);
        //退款单，则需要把业绩报表状态改为冻结中
        report.setSettleStatus(BcxReportSettleStatusEnum.FROZEN.getValue());
        report.setUnFreezeTime(unFreezeTime == null ? now : unFreezeTime);
        report.setSeparateAccountStatus(0);
        report.setCreateTime(now);
        report.setUpdateTime(now);

        //分销商或分销员，生成退款负数佣金记录
        if (report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()
                || report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue().intValue()) {
            userBrokerageRecordService.createRefundBrokerageRecord(report.getBelongId().intValue(), report.getOrderNo(), report.getBrokeragePrice());
        }

        return report;
    }


    /**
     * description：获取解冻时间
     * author：linchunpeng
     * date：2023/8/31
     */
    private Date getUnFreezeTime(Date now) {
        //冻结天数
        int frozenDay = Integer.parseInt(systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FREEZING_TIME));
        //计算解冻时间
        Calendar unFreezeTimeCalendar = Calendar.getInstance();
        unFreezeTimeCalendar.setTime(now);
        unFreezeTimeCalendar.add(Calendar.DAY_OF_YEAR, frozenDay);
        return unFreezeTimeCalendar.getTime();
    }


    /**
     * description：查询业绩报表
     * author：linchunpeng
     * date：2023/8/15
     */
    @Override
    public PageInfo<BcxPerformanceReportResponse> getPage(BcxPerformanceReportSearchRequest request, PageParamRequest pageParamRequest) {
        List<BcxPerformanceReportResponse> list = new ArrayList<>();
        Page<BcxPerformanceReport> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        if (request.getSearchType() != null) {
            HashMap<String, Object> map = getSearchParamMap(request);
            if (request.getSearchType() == 1) {
                //1，渠道
                list = dao.selectChannelList(map);
            } else if (request.getSearchType() == 2) {
                //2，部门
                list = dao.selectDepartmentList(map);
            } else if (request.getSearchType() == 3) {
                //3，部门成员
                list = dao.selectDepartmentMemberList(map);
            } else if (request.getSearchType() == 4) {
                //4，分销商
                list = dao.selectFxsList(map);
            } else if (request.getSearchType() == 5) {
                //5，分销员
                list = dao.selectFxyList(map);
            } else if (request.getSearchType() == 6) {
                //6，关联eb_user表
                list = dao.selectUserList(map);
            }
        }
        return CommonPage.copyPageInfo(page, list);
    }

    /**
     * description：根据结束时间，查询所有未结算业绩报表
     * author：linchunpeng
     * date：2023/8/17
     */
    @Override
    public List<BcxPerformanceReport> listWaitSettledByEndTime(Date endTime) {
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.le("un_freeze_time", endTime);
        queryWrapper.eq("settle_status", BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
        queryWrapper.isNull("settle_bill_id");
        return this.list(queryWrapper);
    }


    /**
     * description：根据结束时间，查询所有未结算业绩报表
     * author：linchunpeng
     * date：2023/8/17
     */
    private List<BcxPerformanceReport> listByOrderDetailId(Integer orderDetailId) {
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.eq("order_detail_id", orderDetailId);
        return this.list(queryWrapper);
    }

    /**
     * description：收益中心统计
     * author：linchunpeng
     * date：2023/8/28
     */
    @Override
    public BcxBrokerageStatisticsResponse brokerageStatistics() {
        BcxBrokerageStatisticsResponse response = new BcxBrokerageStatisticsResponse();
        Integer userId = userService.getUserId();
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.eq("belong_id", userId);
        //查询冻结中、待结算、已结算
        queryWrapper.in("settle_status", Arrays.asList(BcxReportSettleStatusEnum.FROZEN.getValue(),
                BcxReportSettleStatusEnum.WAIT_SETTLED.getValue(),
                BcxReportSettleStatusEnum.SETTLED.getValue()));
        //查询渠道、分销商、分销员
        queryWrapper.in("belong_type", Arrays.asList(BcxPerformanceReportBelongTypeEnum.CHANNEL.getValue(),
                BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue(),
                BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue()));
        List<BcxPerformanceReport> performanceReportList = this.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(performanceReportList)) {
            for (BcxPerformanceReport report : performanceReportList) {
                if (report.getSettleStatus().intValue() == BcxReportSettleStatusEnum.FROZEN.getValue()) {
                    //冻结金额
                    response.setFrozenBrokeragePrice(response.getFrozenBrokeragePrice().add(report.getBrokeragePrice()));
                } else if (report.getSettleStatus().intValue() == BcxReportSettleStatusEnum.WAIT_SETTLED.getValue()) {
                    //待结算金额
                    response.setWaitSettledBrokeragePrice(response.getWaitSettledBrokeragePrice().add(report.getBrokeragePrice()));
                } else if (report.getSettleStatus().intValue() == BcxReportSettleStatusEnum.SETTLED.getValue()) {
                    //已结算金额
                    response.setSettledBrokeragePrice(response.getSettledBrokeragePrice().add(report.getBrokeragePrice()));
                }
                //总收益
                response.setTotalBrokeragePrice(response.getTotalBrokeragePrice().add(report.getBrokeragePrice()));
                //总笔数
                response.setTotalCount(response.getTotalCount() + 1);
            }
        }
        return response;
    }

    /**
     * description：业绩报表统计
     * author：linchunpeng
     * date：2024/3/28
     */
    @Override
    public BcxPerformanceReportStatisticsResponse statistics(BcxPerformanceReportSearchRequest request) {
        BcxPerformanceReportStatisticsResponse response = new BcxPerformanceReportStatisticsResponse();
        if (request.getSearchType() != null) {
            HashMap<String, Object> map = getSearchParamMap(request);
            if (request.getSearchType() == 1) {
                //1，渠道
                response = dao.selectChannelCount(map);
            } else if (request.getSearchType() == 2) {
                //2，部门
                response = dao.selectDepartmentCount(map);
            } else if (request.getSearchType() == 3) {
                //3，部门成员
                response = dao.selectDepartmentMemberCount(map);
            } else if (request.getSearchType() == 4) {
                //4，分销商
                response = dao.selectFxsCount(map);
            } else if (request.getSearchType() == 5) {
                //5，分销员
                response = dao.selectFxyCount(map);
            } else if (request.getSearchType() == 6) {
                //6，关联eb_user表
                response = dao.selectUserCount(map);
            }
        }
        return response;
    }

    /**
     * description：获取查询查询参数
     * author：linchunpeng
     * date：2024/3/28
     */
    private HashMap<String, Object> getSearchParamMap(BcxPerformanceReportSearchRequest request) {
        HashMap<String, Object> map = CollUtil.newHashMap();
        if (StrUtil.isNotBlank(request.getDateLimit())) {
            DateLimitUtilVo dateLimitUtilVo = CrmebDateUtil.getDateLimit(request.getDateLimit());
            map.put("orderStartTime", dateLimitUtilVo.getStartTime());
            map.put("orderEndTime", dateLimitUtilVo.getEndTime());
        }
        if (ObjectUtil.isNotNull(request.getUserId())) {
            map.put("userId", request.getUserId());
        }
        if (ObjectUtil.isNotNull(request.getSpreadUid())) {
            map.put("spreadUid", request.getSpreadUid());
        }
        if (request.getSettleBillId() != null) {
            map.put("settleBillId", request.getSettleBillId());
        }
        if (request.getSettleId() != null) {
            map.put("settleId", request.getSettleId());
        }
        if (CollectionUtil.isNotEmpty(request.getSettleBillIdList())) {
            map.put("settleBillIdList", request.getSettleBillIdList());
        }
        if (StrUtil.isNotBlank(request.getSettleStatus())) {
            List<String> settleStatusList = Arrays.stream(request.getSettleStatus().split(",")).collect(Collectors.toList());
            map.put("settleStatusList", settleStatusList);
        }
        if (StrUtil.isNotBlank(request.getName())) {
            map.put("name", request.getName());
        }
        if (StrUtil.isNotBlank(request.getBrokerageUserPhone())) {
            map.put("brokerageUserPhone", request.getBrokerageUserPhone());
        }
        if (StrUtil.isNotBlank(request.getOrderNo())) {
            map.put("orderNo", request.getOrderNo());
        }
        if (StrUtil.isNotBlank(request.getOrderRegionCode())) {
            map.put("orderRegionCode", request.getOrderRegionCode().substring(0, 2));
        }
        if (StrUtil.isNotBlank(request.getOrderUserName())) {
            map.put("orderUserName", request.getOrderUserName());
        }
        if (request.getSearchType() == 2) {
            //2，部门
            if (StringUtils.isNotBlank(request.getBcxId())) {
                BcxDepartment department = bcxDepartmentService.findByBcxId(request.getBcxId());
                if (department != null) {
                    map.put("departmentId", department.getId());
                } else {
                    map.put("departmentId", -1);
                }
            }
        } else if (request.getSearchType() == 3) {
            //3，部门成员
            if (StringUtils.isNotBlank(request.getBcxId())) {
                BcxDepartment department = bcxDepartmentService.findByBcxId(request.getBcxId());
                if (department != null) {
                    map.put("departmentId", department.getId());
                } else {
                    BcxDepartmentMember departmentMember = bcxDepartmentMemberService.findByBcxId(request.getBcxId());
                    if (departmentMember != null) {
                        map.put("departmentMemberId", departmentMember.getId());
                    } else {
                        map.put("departmentMemberId", -1);
                    }
                }
            }
        }
        return map;
    }
}