package com.zbkj.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
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.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.enums.BcxBillSettleStatusEnum;
import com.zbkj.common.enums.BcxPerformanceReportBelongTypeEnum;
import com.zbkj.common.enums.BcxReportSettleStatusEnum;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.bcx.*;
import com.zbkj.common.model.user.User;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.BcxBillGenerateSettleRequest;
import com.zbkj.common.request.BcxSettleBillSearchRequest;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.BcxSettleBillDetailResponse;
import com.zbkj.common.response.BcxSettleBillInfoResponse;
import com.zbkj.common.response.BcxSettleBillResponse;
import com.zbkj.common.response.BcxSettleBillStatisticsResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.DateUtils;
import com.zbkj.common.utils.IdGeneratorSnowflake;
import com.zbkj.service.dao.BcxSettleBillDao;
import com.zbkj.service.service.*;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * description: 业绩账单表 服务实现类
 * author : linchunpeng
 * date : 2023/8/3
 */
@Slf4j
@Service
public class BcxSettleBillServiceImpl extends ServiceImpl<BcxSettleBillDao, BcxSettleBill> implements BcxSettleBillService {
    
    @Resource
    private BcxSettleBillDao dao;

    @Autowired
    private BcxPerformanceReportService bcxPerformanceReportService;
    @Autowired
    private BcxDepartmentService bcxDepartmentService;
    @Autowired
    private BcxDepartmentMemberService bcxDepartmentMemberService;
    @Autowired
    private UserService userService;
    @Autowired
    private BcxSettleService bcxSettleService;
    @Autowired
    private IdGeneratorSnowflake snowflake;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * description：生成业绩账单
     * author：linchunpeng
     * date：2023/8/17
     */
    @Override
    @Transactional
    public void generateSettleBill(Date endTime) {
        log.info("==================生成业绩账单==================");
        log.info("账单结束时间：{}", endTime);
        //根据结束时间，生成账期
        String billPeriod = DateUtils.formatDate(endTime, "yyyy-MM");
        log.info("账期：{}", billPeriod);
        //分布式锁key
        String lockKey = "GENERATE_SETTLE_BILL";
        //取锁
        log.info("生成业绩账单， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            //查询到期时间之前的所有未结算的业绩报表
            List<BcxPerformanceReport> performanceReportList = bcxPerformanceReportService.listWaitSettledByEndTime(endTime);
            if (CollectionUtil.isNotEmpty(performanceReportList)) {
                Date now = new Date();
                List<BcxSettleBill> bcxSettleBillList = new ArrayList<>();
                log.info("账期：{}，业绩报表条数为：{}", billPeriod, performanceReportList.size());
                //根据belongId-belongType分组
                Map<String, List<BcxPerformanceReport>> belongReportListMap = performanceReportList.stream().collect(
                        Collectors.groupingBy(bcxPerformanceReport -> bcxPerformanceReport.getBelongId().toString().concat("_").concat(bcxPerformanceReport.getBelongType().toString())));
                //根据分组，生成新的账单，如果账期已存在，那就不生成了
                for (Map.Entry<String, List<BcxPerformanceReport>> belongReportListEntry : belongReportListMap.entrySet()) {
                    String[] key = belongReportListEntry.getKey().split("_");
                    long belongId = Long.parseLong(key[0]);
                    int belongType = Integer.parseInt(key[1]);
                    BcxSettleBill exist = this.findByBelongIdAndBillPeriod(belongId, belongType, billPeriod);
                    if (exist != null) {
                        log.info("belongId：{}，belongType：{}，账期：{}，的账单已存在，不能重复生成", belongId, belongType, billPeriod);
                    } else {
                        List<BcxPerformanceReport> reportList = belongReportListEntry.getValue();
                        log.info("生成belongId：{}，belongType：{}，的账单，账期：{}，业绩报表条数为：{}", belongId, belongType, billPeriod, reportList.size());
//                        //清空之前关联的账单id
//                        for (BcxPerformanceReport report : reportList) {
//                            report.setSettleBillId(null);
//                            report.setSettleAttachmentsId(null);
//                        }
                        Long billId = snowflake.snowflakeId();
                        //订单id set，用来计算订单数量
                        Set<Integer> orderIdSet = new HashSet<>();
                        //总订单实付金额
                        BigDecimal orderTotalPrice = BigDecimal.ZERO;
                        //总分佣金额
                        BigDecimal brokerageTotalPrice = BigDecimal.ZERO;
                        for (BcxPerformanceReport report : reportList) {
                            orderIdSet.add(report.getOrderId());
                            orderTotalPrice = orderTotalPrice.add(report.getPayPrice());
                            if (report.getSeparateAccountStatus() == null || report.getSeparateAccountStatus() == 0) {
                                brokerageTotalPrice = brokerageTotalPrice.add(report.getBrokeragePrice());
                            }
                            //设置新的账单id
                            report.setSettleBillId(billId);
                        }
                        //生成账单
                        bcxSettleBillList.add(this.createBcxSettleBill(billId, belongId, belongType, null, billPeriod, orderIdSet.size(),
                                orderTotalPrice, brokerageTotalPrice, now));

                        if (CollectionUtil.isNotEmpty(reportList)
                                && reportList.get(0).getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()) {
                            List<String> orderNoList = reportList.stream().map(BcxPerformanceReport::getOrderNo).collect(Collectors.toList());
                            List<BcxPerformanceReport> fxyReportList = getFxyReportListByOrderNo(orderNoList);

                            Map<Long, List<BcxPerformanceReport>> fxyReportListMap = fxyReportList.stream().collect(
                                    Collectors.groupingBy(BcxPerformanceReport::getBelongId));

                            for (Map.Entry<Long, List<BcxPerformanceReport>> fxyReportListEntry : fxyReportListMap.entrySet()) {
                                List<BcxPerformanceReport> list = fxyReportListEntry.getValue();
                                Long fxyId = fxyReportListEntry.getKey();
                                log.info("生成belongId：{}，belongType：{}，的账单，账期：{}，业绩报表条数为：{}", fxyId, BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue(), billPeriod, list.size());
                                Long fxyBillId = snowflake.snowflakeId();
                                //订单id set，用来计算订单数量
                                Set<Integer> fxyOrderIdSet = new HashSet<>();
                                //总订单实付金额
                                BigDecimal fxyOrderTotalPrice = BigDecimal.ZERO;
                                //总分佣金额
                                BigDecimal fxyBrokerageTotalPrice = BigDecimal.ZERO;
                                for (BcxPerformanceReport report : list) {
                                    fxyOrderIdSet.add(report.getOrderId());
                                    fxyOrderTotalPrice = fxyOrderTotalPrice.add(report.getPayPrice());
                                    fxyBrokerageTotalPrice = fxyBrokerageTotalPrice.add(report.getBrokeragePrice());
                                    //设置新的账单id
                                    report.setSettleBillId(fxyBillId);
                                }
                                //生成账单
                                bcxSettleBillList.add(this.createBcxSettleBill(fxyBillId, fxyId, BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue(),
                                        billId, billPeriod, fxyOrderIdSet.size(),
                                        fxyOrderTotalPrice, fxyBrokerageTotalPrice, now));
                            }
                        }
                    }
                }
                //保存数据
                log.info("保存数据");
                bcxPerformanceReportService.updateBatchById(performanceReportList);
                this.saveBatch(bcxSettleBillList);
            } else {
                log.info("账期：{}，业绩报表为空，不需要生成业绩账单", billPeriod);
            }
            log.info("生成业绩账单完成，账单结束时间：{}", endTime);
        } 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/17
     */
    private BcxSettleBill createBcxSettleBill(Long id, Long belongId, Integer belongType, Long fxsSettleBillId, String billPeriod,
                                              int orderCount, BigDecimal orderTotalPrice, BigDecimal brokerageTotalPrice, Date now) {
        BcxSettleBill bill = new BcxSettleBill();
        bill.setId(id);
        bill.setBelongId(belongId);
        bill.setBelongType(belongType);
        bill.setFxsSettleBillId(fxsSettleBillId);
        bill.setBillPeriod(billPeriod);
        bill.setOrderCount(orderCount);
        bill.setOrderTotalPrice(orderTotalPrice);
        bill.setBrokerageTotalPrice(brokerageTotalPrice);
        bill.setBrokerageSettleTotalPrice(BigDecimal.ZERO);
        bill.setSettleStatus(BcxBillSettleStatusEnum.WAIT_SETTLED.getValue());
        bill.setCreateTime(now);
        bill.setUpdateTime(now);
        return bill;
    }

    /**
     * description：根据关联id和账期，查询账单
     * author：linchunpeng
     * date：2023/8/17
     */
    private BcxSettleBill findByBelongIdAndBillPeriod(Long belongId, Integer belongType, String billPeriod) {
        QueryWrapper<BcxSettleBill> queryWrapper = Wrappers.query();
        queryWrapper.eq("belong_id", belongId);
        queryWrapper.eq("belong_type", belongType);
        queryWrapper.eq("bill_period", billPeriod);
        return this.getOne(queryWrapper);
    }


    /**
     * description：根据id，查询账单
     * author：linchunpeng
     * date：2023/8/17
     */
    @Override
    public BcxSettleBillDetailResponse findId(Long id) {
        BcxSettleBillDetailResponse result = new BcxSettleBillDetailResponse();
        BcxSettleBill bcxSettleBill = this.getById(id);
        BeanUtil.copyProperties(bcxSettleBill, result);
        int belongType = bcxSettleBill.getBelongType();
        Long belongId = bcxSettleBill.getBelongId();
        if (belongType == BcxPerformanceReportBelongTypeEnum.CHANNEL.getValue()
                || belongType == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue()
                || belongType == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue()) {
            //关联用户表
            User user = userService.getById(belongId);
            if (user != null) {
                result.setSettleName(user.getRealName());
            }
        } else if (belongType == BcxPerformanceReportBelongTypeEnum.DEPARTMENT.getValue()) {
            //关联部门
            BcxDepartment department = bcxDepartmentService.getById(belongId);
            if (department != null) {
                result.setSettleName(department.getName());
            }
        } else if (belongType == BcxPerformanceReportBelongTypeEnum.DEPARTMENT_MEMBER.getValue()) {
            //关联部门成员
            BcxDepartmentMember departmentMember = bcxDepartmentMemberService.getById(belongId);
            if (departmentMember != null) {
                result.setSettleName(departmentMember.getName());
            }
        }
        return result;
    }


    /**
     * description：查询业绩账单
     * author：linchunpeng
     * date：2023/8/15
     */
    @Override
    public PageInfo<BcxSettleBillResponse> getPage(BcxSettleBillSearchRequest request, PageParamRequest pageParamRequest) throws ParseException {
        Page<BcxSettleBill> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<BcxSettleBillResponse> list = new ArrayList<>();
        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：2024/3/28
     */
    @Override
    public BcxSettleBillStatisticsResponse statistics(BcxSettleBillSearchRequest request) throws ParseException {
        BcxSettleBillStatisticsResponse response = new BcxSettleBillStatisticsResponse();
        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(BcxSettleBillSearchRequest request) throws ParseException {
        HashMap<String, Object> map = CollUtil.newHashMap();
        if (ObjectUtil.isNotNull(request.getBillPeriodStart())) {
            map.put("billPeriodStart", DateUtils.parseDate(request.getBillPeriodStart().concat("-01 00:00:00"), "yyyy-MM-dd HH:mm:ss"));
        }
        if (ObjectUtil.isNotNull(request.getBillPeriodEnd())) {
            map.put("billPeriodEnd", DateUtils.parseDate(request.getBillPeriodEnd().concat("-01 00:00:00"), "yyyy-MM-dd HH:mm:ss"));
        }
        if (ObjectUtil.isNotNull(request.getUserId())) {
            map.put("userId", request.getUserId());
        }
        if (ObjectUtil.isNotNull(request.getSpreadUid())) {
            map.put("spreadUid", request.getSpreadUid());
        }
        if (ObjectUtil.isNotNull(request.getSettleStatus())) {
            map.put("settleStatus", request.getSettleStatus());
        }
        if (StrUtil.isNotBlank(request.getName())) {
            map.put("name", request.getName());
        }
        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;
    }

    /**
     * description：获取生成结算单数据
     * author：linchunpeng
     * date：2023/8/22
     */
    @Override
    public BcxSettleBillInfoResponse getSettleInfo(BcxBillGenerateSettleRequest request) {
        if (CollectionUtil.isEmpty(request.getSettleBillIdList())
                && request.getSettleBillId() == null && CollectionUtil.isEmpty(request.getPerformanceReportIdList())) {
            throw new CrmebException(CommonResultCode.ERROR.setMessage("请选择要结算的账单或业绩报表"));
        }
        //获取要结算的业绩报表
        List<BcxPerformanceReport> performanceReportList = getSettleReportList(request);
        //获取结算汇总信息
        BcxSettleBillInfoResponse response = getBcxBillSettleInfoResponse(performanceReportList);
        return response;
    }

    /**
     * description：生成结算单
     * author：linchunpeng
     * date：2023/8/22
     */
    @Override
    @Transactional
    public Boolean generateSettle(BcxBillGenerateSettleRequest request) {
        log.info("==================生成结算单==================");
        log.info("生成结算单,参数：{}", JSONObject.toJSONString(request));
        //分布式锁key
        String lockKey = "BCX_SETTLE_BILL_GENERATE_SETTLE";
        //取锁
        log.info("生成结算单， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            if (CollectionUtil.isEmpty(request.getSettleBillIdList())
                    && request.getSettleBillId() == null && CollectionUtil.isEmpty(request.getPerformanceReportIdList())) {
                throw new CrmebException(CommonResultCode.ERROR.setMessage("请选择要生成结算单的账单或业绩报表"));
            }

            Date now = new Date();
            //获取要生成结算单的业绩报表
            List<BcxPerformanceReport> performanceReportList = getSettleReportList(request);
            if (CollectionUtil.isNotEmpty(performanceReportList)) {
                if (performanceReportList.stream().anyMatch(report ->
                        report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue().intValue())) {
                    throw new CrmebException(CommonResultCode.ERROR.setMessage("选择要生成结算单包含分销员的账单或业绩报表，请重新选择"));
                }

                log.info("要生成结算单的业绩报表数量：{}", performanceReportList.size());
                Map<Long, List<BcxPerformanceReport>> reportListMap = performanceReportList.stream().collect(Collectors.groupingBy(BcxPerformanceReport::getSettleBillId));
                log.info("要生成结算单的账单数量：{}", reportListMap.size());

                BcxSettle lastNoSettle = bcxSettleService.getLastNoSettle();
                int settleNoNum = 1;
                if (lastNoSettle != null) {
                    //今天的结算单不为空，则取最后的序号
                    int length = lastNoSettle.getSettleNo().length();
                    settleNoNum = Integer.parseInt(lastNoSettle.getSettleNo().substring(length-5, length)) + 1;
                }
                DecimalFormat settleNoFormat = new DecimalFormat("00000");
                for (Map.Entry<Long, List<BcxPerformanceReport>> reportListEntry : reportListMap.entrySet()) {
                    //循环内部生成结算单号，FXJS2023090100001，FXJS + 日期 + 序号
                    String settleNo = bcxSettleService.getSettleNoPrefix().concat(settleNoFormat.format(settleNoNum));

                    Long settleId = snowflake.snowflakeId();
                    Long settleBillId = reportListEntry.getKey();
                    List<BcxPerformanceReport> reportList = reportListEntry.getValue();
                    log.info("========================");
                    log.info("要生成结算单的账单id：{}，业绩报表数量：{}", settleBillId, reportList.size());
                    //修改业绩报表结算状态
                    for (BcxPerformanceReport report : reportList) {
                        report.setSettleStatus(BcxReportSettleStatusEnum.SETTLING.getValue());
                        report.setSettleId(settleId);
                        report.setUpdateTime(now);
                        log.info("修改业绩报表id：{}，结算状态：{}", report.getId().toString(), BcxReportSettleStatusEnum.SETTLING.getName());
                    }

                    //获取结算汇总信息
                    BcxSettleBillInfoResponse response = getBcxBillSettleInfoResponse(reportList);
                    if (response.getSettleTotalPrice().compareTo(BigDecimal.ZERO) < 0) {
                        throw new CrmebException(CommonResultCode.ERROR.setMessage("结算金额必须大于等于0"));
                    }
                    BcxSettleBill settleBill = this.getById(settleBillId);
                    //生成结算单
                    bcxSettleService.generateSettle(settleBill, settleId, null, settleNo, response, now);
                    //保存业绩报表状态
                    bcxPerformanceReportService.updateBatchById(reportList);
                    settleNoNum++;
                    log.info("========================");

                    if (CollectionUtil.isNotEmpty(reportList)
                            && reportList.get(0).getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()) {
                        List<String> orderNoList = reportList.stream().map(BcxPerformanceReport::getOrderNo).collect(Collectors.toList());
                        List<BcxPerformanceReport> fxyReportList = getFxyReportListByOrderNo(orderNoList);

                        Map<Long, List<BcxPerformanceReport>> fxyReportListMap = fxyReportList.stream().collect(Collectors.groupingBy(BcxPerformanceReport::getSettleBillId));

                        for (Map.Entry<Long, List<BcxPerformanceReport>> fxyReportListEntry : fxyReportListMap.entrySet()) {
                            //循环内部生成结算单号，FXJS2023090100001，FXJS + 日期 + 序号
                            String fxySettleNo = bcxSettleService.getSettleNoPrefix().concat(settleNoFormat.format(settleNoNum));

                            Long fxySettleId = snowflake.snowflakeId();
                            Long fxySettleBillId = fxyReportListEntry.getKey();
                            List<BcxPerformanceReport> list = fxyReportListEntry.getValue();
                            log.info("========================");
                            log.info("要生成结算单的账单id：{}，业绩报表数量：{}", fxySettleBillId, list.size());
                            //修改业绩报表结算状态
                            for (BcxPerformanceReport report : list) {
                                report.setSettleStatus(BcxReportSettleStatusEnum.SETTLING.getValue());
                                report.setSettleId(fxySettleId);
                                report.setUpdateTime(now);
                                log.info("修改业绩报表id：{}，结算状态：{}", report.getId().toString(), BcxReportSettleStatusEnum.SETTLING.getName());
                            }

                            //获取结算汇总信息
                            BcxSettleBillInfoResponse billInfoResponse = getBcxBillSettleInfoResponse(list);
                            if (billInfoResponse.getSettleTotalPrice().compareTo(BigDecimal.ZERO) < 0) {
                                throw new CrmebException(CommonResultCode.ERROR.setMessage("结算金额必须大于等于0"));
                            }
                            BcxSettleBill fxySettleBill = this.getById(fxySettleBillId);
                            //生成结算单
                            bcxSettleService.generateSettle(fxySettleBill, fxySettleId, settleId, fxySettleNo, billInfoResponse, now);
                            //保存业绩报表状态
                            bcxPerformanceReportService.updateBatchById(list);
                            settleNoNum++;
                            log.info("========================");
                        }
                    }
                }
            } else {
                log.info("无结算的业绩报表");
            }
        } 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("==================生成结算单完成==================");
        return true;
    }

    /**
     * description：获取要生成结算单的业绩报表
     * author：linchunpeng
     * date：2023/8/22
     */
    private List<BcxPerformanceReport> getSettleReportList(BcxBillGenerateSettleRequest request) {
        List<BcxPerformanceReport> performanceReportList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(request.getSettleBillIdList())) {
            //生成结算单，查询所有业绩报表
            QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
            queryWrapper.in("settle_bill_id", request.getSettleBillIdList());
            queryWrapper.eq("settle_status", BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
            queryWrapper.ne("belong_type", BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue());
            performanceReportList = bcxPerformanceReportService.list(queryWrapper);
        } else {
            //业绩报表生成结算单，查询对应的业绩报表
            QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
            if (CollectionUtil.isNotEmpty(request.getPerformanceReportIdList())) {
                queryWrapper.in("id", request.getPerformanceReportIdList());
            }
            if (request.getSettleBillId() != null) {
                queryWrapper.eq("settle_bill_id", request.getSettleBillId());
            }
            queryWrapper.eq("settle_status", BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
            queryWrapper.ne("belong_type", BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue());
            performanceReportList = bcxPerformanceReportService.list(queryWrapper);
        }
        return performanceReportList;
    }

    /**
     * description：获取结算汇总信息
     * author：linchunpeng
     * date：2023/8/22
     */
    private BcxSettleBillInfoResponse getBcxBillSettleInfoResponse(List<BcxPerformanceReport> performanceReportList) {
        BcxSettleBillInfoResponse response = new BcxSettleBillInfoResponse();
        if (CollectionUtil.isNotEmpty(performanceReportList)) {
            //汇总
            Set<Long> settleBillIdSet = new HashSet<>();
            int settleReportCount = 0;
            Set<Integer> settleOrderIdSet = new HashSet<>();
            BigDecimal payTotalPrice = BigDecimal.ZERO;
            BigDecimal settleTotalPrice = BigDecimal.ZERO;
            BigDecimal settledPrice = BigDecimal.ZERO;
            for (BcxPerformanceReport report : performanceReportList) {
                settleBillIdSet.add(report.getSettleBillId());
                settleReportCount++;
                settleOrderIdSet.add(report.getOrderId());
                payTotalPrice = payTotalPrice.add(report.getPayPrice());
                if (report.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXS.getValue().intValue()) {
                    settleTotalPrice = settleTotalPrice.add(report.getBrokeragePriceTotal());
                } else {
                    settleTotalPrice = settleTotalPrice.add(report.getBrokeragePrice());
                }
                if (report.getSeparateAccountStatus() != null && report.getSeparateAccountStatus() == 1) {
                    //已分账
                    settledPrice = settledPrice.add(report.getBrokeragePrice());
                }
            }
            response.setSettleCount(settleBillIdSet.size());
            response.setSettleReportCount(settleReportCount);
            response.setSettleOrderCount(settleOrderIdSet.size());
            response.setPayTotalPrice(payTotalPrice);
            response.setSettleTotalPrice(settleTotalPrice);
            response.setSettledPrice(settledPrice);
            response.setNotSettledPrice(settleTotalPrice.subtract(settledPrice));
        } else {
            response.setSettleCount(0);
            response.setSettleReportCount(0);
            response.setSettleOrderCount(0);
            response.setPayTotalPrice(BigDecimal.ZERO);
            response.setSettleTotalPrice(BigDecimal.ZERO);
            response.setSettledPrice(BigDecimal.ZERO);
            response.setNotSettledPrice(BigDecimal.ZERO);
        }
        return response;
    }


    private List<BcxPerformanceReport> getFxyReportListByOrderNo(List<String> orderNoList) {
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.in("order_no", orderNoList);
        queryWrapper.eq("settle_status", BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
        queryWrapper.eq("belong_type", BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue());
        return bcxPerformanceReportService.list(queryWrapper);
    }

}