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.constants.SysConfigConstants;
import com.zbkj.common.dto.HuifuWalletTransferDto;
import com.zbkj.common.enums.*;
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.BcxDoSettleRequest;
import com.zbkj.common.request.BcxSettleBillSearchRequest;
import com.zbkj.common.request.BcxSettleSearchRequest;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.response.*;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.DateUtils;
import com.zbkj.common.vo.DateLimitUtilVo;
import com.zbkj.service.config.PaymentChannel;
import com.zbkj.service.dao.BcxSettleDao;
import com.zbkj.service.factory.PaymentFactory;
import com.zbkj.service.service.*;
import com.zbkj.service.service.bcx.BcxFapiaoSourceService;
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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * description: 结算表 服务实现类
 * author : linchunpeng
 * date : 2023/9/1
 */
@Slf4j
@Service
public class BcxSettleServiceImpl extends ServiceImpl<BcxSettleDao, BcxSettle> implements BcxSettleService {
    
    @Resource
    private BcxSettleDao dao;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    @Lazy
    private BcxSettleBillService bcxSettleBillService;
    @Autowired
    @Lazy
    private BcxPerformanceReportService bcxPerformanceReportService;
    @Autowired
    private BcxDepartmentService bcxDepartmentService;
    @Autowired
    private BcxDepartmentMemberService bcxDepartmentMemberService;
    @Autowired
    private UserService userService;
    @Autowired
    private BcxFapiaoSourceService bcxFapiaoSourceService;

    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private PaymentFactory paymentFactory;

    private static final String SETTLE_NO_PREFIX = "FXJS";

    /**
     * description：根据id，查询结算单
     * author：linchunpeng
     * date：2023/8/17
     */
    @Override
    public BcxSettleDetailResponse findId(Long id) {
        BcxSettleDetailResponse result = new BcxSettleDetailResponse();
        BcxSettle bcxSettle = this.getById(id);
        BeanUtil.copyProperties(bcxSettle, result);
        int belongType = bcxSettle.getBelongType();
        Long belongId = bcxSettle.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<BcxSettleResponse> getPage(BcxSettleSearchRequest request, PageParamRequest pageParamRequest) throws ParseException {
        Page<BcxSettle> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        List<BcxSettleResponse> 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 BcxSettleStatisticsResponse statistics(BcxSettleSearchRequest request) throws ParseException {
        BcxSettleStatisticsResponse response = new BcxSettleStatisticsResponse();
        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(BcxSettleSearchRequest 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.getSettleStatus())) {
            map.put("settleStatus", request.getSettleStatus());
        }
        if (ObjectUtil.isNotNull(request.getUploadAttachments())) {
            map.put("uploadAttachments", request.getUploadAttachments());
        }
        if (StrUtil.isNotBlank(request.getName())) {
            map.put("name", request.getName());
        }
        if (StrUtil.isNotBlank(request.getDateLimit())) {
            DateLimitUtilVo dateLimitUtilVo = CrmebDateUtil.getDateLimit(request.getDateLimit());
            map.put("settleTimeStart", dateLimitUtilVo.getStartTime());
            map.put("settleTimeEnd", dateLimitUtilVo.getEndTime());
        }
        if (StrUtil.isNotBlank(request.getSettleNo())) {
            map.put("settleNo", request.getSettleNo());
        }
        if (ObjectUtil.isNotNull(request.getUserId())) {
            map.put("userId", request.getUserId());
        }
        if (ObjectUtil.isNotNull(request.getSpreadUid())) {
            map.put("spreadUid", request.getSpreadUid());
        }
        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/9/4
     */
    @Override
    public void generateSettle(BcxSettleBill settleBill, Long settleId, Long fxsSettleId, String settleNo, BcxSettleBillInfoResponse bcxSettleBillInfoResponse, Date now) {
        BcxSettle bcxSettle = new BcxSettle();
        bcxSettle.setId(settleId);
        bcxSettle.setSettleBillId(settleBill.getId());
        bcxSettle.setBelongId(settleBill.getBelongId());
        bcxSettle.setFxsSettleId(fxsSettleId);
        bcxSettle.setBelongType(settleBill.getBelongType());
        bcxSettle.setBillPeriod(settleBill.getBillPeriod());
        bcxSettle.setSettleNo(settleNo);
        bcxSettle.setReportCount(bcxSettleBillInfoResponse.getSettleReportCount());
        bcxSettle.setTotalPrice(bcxSettleBillInfoResponse.getPayTotalPrice());
        bcxSettle.setBrokerageTotalPrice(bcxSettleBillInfoResponse.getSettleTotalPrice());
        bcxSettle.setBrokerageSettledPrice(bcxSettleBillInfoResponse.getSettledPrice());
        bcxSettle.setBrokerageNotSettledPrice(bcxSettleBillInfoResponse.getNotSettledPrice());
        bcxSettle.setSettleStatus(BcxSettleStatusEnum.WAIT_SETTLED.getValue());
        bcxSettle.setCreateTime(now);
        bcxSettle.setUpdateTime(now);
        this.save(bcxSettle);

        //推送结算单数据到发票中心
        bcxFapiaoSourceService.saveSourceFromBrokerage(bcxSettle);
    }

    /**
     * description：当天最后一个结算单
     * author：linchunpeng
     * date：2023/9/4
     */
    @Override
    public BcxSettle getLastNoSettle() {
        QueryWrapper<BcxSettle> queryWrapper = Wrappers.query();
        queryWrapper.likeRight("settle_no", getSettleNoPrefix());
        queryWrapper.orderByDesc("create_time");
        return this.getOne(queryWrapper, false);
    }

    /**
     * description：结算单号前缀
     * author：linchunpeng
     * date：2023/9/4
     */
    @Override
    public String getSettleNoPrefix() {
        return SETTLE_NO_PREFIX.concat(DateUtils.getDate("yyyyMMdd"));
    }

    /**
     * description：获取生成结算单数据
     * author：linchunpeng
     * date：2023/8/22
     */
    @Override
    public BcxSettleInfoResponse getSettleInfo(BcxDoSettleRequest request) {
        //获取要结算的结算单
        List<BcxSettle> settleList = getByBcxDoSettleRequest(request);
        //获取结算汇总信息
        BcxSettleInfoResponse response = getBcxSettleInfoResponse(settleList);
        return response;
    }

    /**
     * description：根据结算请求，获取结算单
     * author：linchunpeng
     * date：2023/9/4
     */
    private List<BcxSettle> getByBcxDoSettleRequest(BcxDoSettleRequest request) {
        QueryWrapper<BcxSettle> queryWrapper = Wrappers.query();
        queryWrapper.in("id", request.getSettleIdList());
        return this.list(queryWrapper);
    }

    /**
     * description：获取结算信息
     * author：linchunpeng
     * date：2023/9/4
     */
    private BcxSettleInfoResponse getBcxSettleInfoResponse(List<BcxSettle> settleList) {
        BcxSettleInfoResponse response = new BcxSettleInfoResponse();
        if (CollectionUtil.isNotEmpty(settleList)) {
            //汇总
            int settleReportCount = 0;
            Set<Integer> settleOrderIdSet = new HashSet<>();
            BigDecimal payTotalPrice = BigDecimal.ZERO;
            BigDecimal settleTotalPrice = BigDecimal.ZERO;
            for (BcxSettle bcxSettle : settleList) {
                settleReportCount++;
                payTotalPrice = payTotalPrice.add(bcxSettle.getTotalPrice());
                settleTotalPrice = settleTotalPrice.add(bcxSettle.getBrokerageTotalPrice());
            }
            response.setSettleCount(settleList.size());
            response.setSettleReportCount(settleReportCount);
            response.setPayTotalPrice(payTotalPrice);
            response.setSettleTotalPrice(settleTotalPrice);
        }
        return response;
    }

    /**
     * description：结算
     * author：linchunpeng
     * date：2023/8/22
     */
    @Override
    @Transactional
    public Boolean doSettle(BcxDoSettleRequest request) {
        log.info("==================结算==================");
        log.info("结算参数：{}", JSONObject.toJSONString(request));
        if (request.getPayWay() == null) {
            throw new CrmebException(CommonResultCode.ERROR.setMessage("支付方式不能为空"));
        }
        Date now = new Date();
        //获取要结算的结算单
        List<BcxSettle> settleList = getByBcxDoSettleRequest(request);
        if (CollectionUtil.isNotEmpty(settleList)) {
            for (BcxSettle bcxSettle : settleList) {
                if (bcxSettle.getBelongType().intValue() == BcxPerformanceReportBelongTypeEnum.USER_FXY.getValue().intValue()) {
                    throw new CrmebException(CommonResultCode.ERROR.setMessage("要结算的结算单中，包含分销员的结算，请重新选择"));
                }
            }
            log.info("要结算的结算单数量：{}", settleList.size());
            //修改结算信息
            for (BcxSettle bcxSettle : settleList) {
                //分布式锁key
                String lockKey = "BCX_SETTLE_SETTLE_" + bcxSettle.getId().toString();
                //取锁
                log.info("结算， lockKey：{}，取锁中.....", lockKey);
                RLock lock = redissonClient.getLock(lockKey);
                //加锁，并设置过期时间 300s
                lock.lock(30, TimeUnit.SECONDS);
                log.info("取到锁");
                try {
                    log.info("========================");
                    List<BcxPerformanceReport> reportList = getSettleReportList(bcxSettle.getId());
                    log.info("结算单的id：{}，业绩报表数量：{}", bcxSettle.getId(), reportList.size());
                    log.info("结算金额：{}", bcxSettle.getBrokerageTotalPrice().toPlainString());

                    //修改业绩报表结算状态\支付方式
                    for (BcxPerformanceReport report : reportList) {
                        report.setSettleTime(now);
                        report.setSettleStatus(BcxReportSettleStatusEnum.SETTLED.getValue());
                        report.setPayWay(request.getPayWay());
                        report.setUpdateTime(now);
                        log.info("修改业绩报表id：{}，结算状态：{}", report.getId().toString(), BcxReportSettleStatusEnum.SETTLED.getName());
                    }
                    bcxPerformanceReportService.updateBatchById(reportList);

                    //修改账单状态
                    BcxSettleBill settleBill = bcxSettleBillService.getById(bcxSettle.getSettleBillId());
                    settleBill.setBrokerageSettleTotalPrice(settleBill.getBrokerageSettleTotalPrice().add(bcxSettle.getBrokerageTotalPrice()));
                    //账单的所有业绩报表
                    List<BcxPerformanceReport> billReportList = getSettleBillReportList(settleBill.getId());
                    if (billReportList.stream().allMatch(report -> report.getSettleStatus().intValue() == BcxReportSettleStatusEnum.SETTLED.getValue().intValue())) {
                        //如果全部的业绩报表都是已结算，全部结算
                        settleBill.setSettleStatus(BcxBillSettleStatusEnum.SETTLED.getValue());
                    } else {
                        //如果没有都结算，部分结算
                        settleBill.setSettleStatus(BcxBillSettleStatusEnum.PART_SETTLED.getValue());
                    }
                    settleBill.setUpdateTime(now);
                    bcxSettleBillService.updateById(settleBill);

                    //修改结算单状态
                    bcxSettle.setSettleStatus(BcxSettleStatusEnum.SETTLED.getValue());
                    bcxSettle.setPayWay(request.getPayWay());
                    bcxSettle.setSettleTime(now);
                    bcxSettle.setUpdateTime(now);
                    this.updateById(bcxSettle);

                    //对接支付接口，只有分销商走企业钱包、分销员走第三方支付，其他都线下支付
                    if (request.getPayWay().intValue() == BcxPerformanceReportPayWayEnum.PURSE.getValue()) {
                        //企业钱包支付
                        try {
                            log.info("企业钱包支付");
                            this.settlePayWithPurse(bcxSettle);
                        } catch (Exception e) {
                            log.error("企业钱包支付失败：{}", e.getMessage(), e);
                            throw e;
                        }
                    } else if (request.getPayWay().intValue() == BcxPerformanceReportPayWayEnum.THIRD_PARTY.getValue()) {
                        //第三方支付

                    }
                    log.info("========================");
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("结算异常，{}", e.getMessage(), e);
                } finally {
                    if (lock.isLocked()) {
                        lock.unlock();
                    }
                    log.info("结算，lockKey：{}，解锁", lockKey);
                }
            }
        } else {
            log.info("无结算的结算单");
        }
        log.info("==================结算完成==================");
        return true;
    }


    /**
     * description：结算支付-企业钱包
     * author：linchunpeng
     * date：2023/8/24
     */
    private void settlePayWithPurse(BcxSettle bcxSettle) {
        User user = userService.getById(bcxSettle.getBelongId());
        if (user != null && !user.getIsLogoff()) {
            String settleDetail = String.format("结算单，id：%s，结算金额：%s", bcxSettle.getId().toString(), bcxSettle.getBrokerageTotalPrice().toPlainString());
            HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
            transferDto.setAmount(bcxSettle.getBrokerageNotSettledPrice().toPlainString())//未结算佣金金额
                    .setBusinessCode("99")//99 分销转账
                    .setBusinessPartnerSeq(bcxSettle.getSettleNo())//业务交易流水号
                    .setComment(settleDetail)
                    .setGoodsName(settleDetail)
                    .setGoodsUnit("元")
                    .setGoodsNumber("1")
                    .setInId(user.getIdentityNo())
                    .setSellFeePriority(1)//先分给商户
                    .setNeedActiveCode("0")//是否需要验证码
                    .setPlatAmount("0")//平台分账金额 （没有传0）
                    .setTradeType("03");//03-无解冻，直接支付。 05-解冻再支付
            try {
                paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).platAccountRetailTransfer(transferDto);
            } catch (Exception e) {
                log.error("结算支付-企业钱包-调用钱包解冻出错，{}", e.getMessage(), e);
            }
        }
    }

    /**
     * description：业绩报表直接转账
     * author：linchunpeng
     * date：2024/5/27
     */
    @Override
    public boolean settleReportWithPurse(BcxPerformanceReport report) {
        log.info("业绩报表直接转账，业绩报表id：{}，转账金额：{}", report.getId().toString(), report.getBrokeragePrice().toPlainString());
        User user = userService.getById(report.getBelongId());
        if (user != null && !user.getIsLogoff()) {
            String settleDetail = String.format("业绩报表直接转账，业绩报表id：%s，转账金额：%s", report.getId().toString(), report.getBrokeragePrice().toPlainString());
            HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
            transferDto.setAmount(report.getBrokeragePrice().toPlainString())//结算金额
                    .setBusinessCode("99")//99 分销转账
                    .setBusinessPartnerSeq(report.getId().toString())//业务交易流水号
                    .setComment(settleDetail)
                    .setGoodsName(settleDetail)
                    .setGoodsUnit("元")
                    .setGoodsNumber("1")
                    .setInId(user.getIdentityNo())
                    .setSellFeePriority(1)//先分给商户
                    .setNeedActiveCode("0")//是否需要验证码
                    .setPlatAmount("0")//平台分账金额 （没有传0）
                    .setTradeType("04");//03-无解冻，直接支付。 05-解冻再支付
            try {
                paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).platAccountRetailTransfer(transferDto);
                return true;
            } catch (Exception e) {
                log.error("业绩报表直接转账-调用钱包解冻出错，{}", e.getMessage(), e);
                return false;
            }
        }
        return false;
    }

    /**
     * description：业绩报表佣金解冻
     * author：linchunpeng
     * date：2024/5/30
     */
    @Override
    public void unFrozenReportWithPurse(BcxPerformanceReport report) {
        log.info("业绩报表解冻，业绩报表id：{}，解冻金额：{}", report.getId().toString(), report.getBrokeragePrice().toPlainString());
        User user = userService.getById(report.getBelongId());
        if (user != null && !user.getIsLogoff()) {
            String unFrozenDetail = String.format("业绩报表解冻，业绩报表id：%s，解冻金额：%s", report.getId().toString(), report.getBrokeragePrice().toPlainString());
            HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
            transferDto.setAmount(report.getBrokeragePrice().toPlainString())//结算金额
                    .setBusinessCode("99")//99 分销转账
                    .setBusinessPartnerSeq(report.getId().toString())//业务交易流水号
                    .setComment(unFrozenDetail)
                    .setGoodsName(unFrozenDetail)
                    .setGoodsUnit("元")
                    .setGoodsNumber("1")
                    .setInId(user.getIdentityNo())
                    .setSellFeePriority(1)//先分给商户
                    .setNeedActiveCode("0")//是否需要验证码
                    .setPlatAmount("0")//平台分账金额 （没有传0）
                    .setTradeType("05");//03-无解冻，直接支付。 05-解冻再支付
            try {
                paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountLock(transferDto);
            } catch (Exception e) {
                log.error("业绩报表佣金解冻-调用钱包解冻出错，{}", e.getMessage(), e);
            }
        }
    }

    /**
     * description：获取结算单的业绩报表
     * author：linchunpeng
     * date：2023/9/4
     */
    private List<BcxPerformanceReport> getSettleReportList(Long settleId) {
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.eq("settle_id", settleId);
        return bcxPerformanceReportService.list(queryWrapper);
    }

    /**
     * description：获取账单的业绩报表
     * author：linchunpeng
     * date：2023/9/4
     */
    private List<BcxPerformanceReport> getSettleBillReportList(Long settleBillId) {
        QueryWrapper<BcxPerformanceReport> queryWrapper = Wrappers.query();
        queryWrapper.eq("settle_bill_id", settleBillId);
        return bcxPerformanceReportService.list(queryWrapper);
    }

    /**
     * description：撤销结算单
     * author：linchunpeng
     * date：2023/9/6
     */
    @Override
    @Transactional
    public Boolean cancel(Long id) {
        log.info("==================撤销结算单==================");
        //分布式锁key
        String lockKey = "BCX_SETTLE_SETTLE_" + id.toString();
        //取锁
        log.info("结算， lockKey：{}，取锁中.....", lockKey);
        RLock lock = redissonClient.getLock(lockKey);
        //加锁，并设置过期时间 300s
        lock.lock(30, TimeUnit.SECONDS);
        log.info("取到锁");
        try {
            BcxSettle bcxSettle = this.getById(id);
            if (bcxSettle.getSettleStatus().intValue() == BcxSettleStatusEnum.SETTLED.getValue().intValue()) {
                throw new CrmebException(CommonResultCode.ERROR.setMessage("已结算的结算单不能撤销"));
            }
            //先删除开票源
            bcxFapiaoSourceService.deleteSourceFromBrokerage(bcxSettle.getSettleNo());
            //修改业绩报表状态
            List<BcxPerformanceReport> reportList = getSettleReportList(bcxSettle.getId());
            if (CollectionUtil.isNotEmpty(reportList)) {
                Date now = new Date();
                for (BcxPerformanceReport report : reportList) {
                    report.setSettleStatus(BcxReportSettleStatusEnum.WAIT_SETTLED.getValue());
                    report.setSettleId(null);
                    report.setUpdateTime(now);
                    log.info("修改业绩报表id：{}，结算状态：{}", report.getId().toString(), BcxReportSettleStatusEnum.WAIT_SETTLED.getName());
                }
                bcxPerformanceReportService.updateBatchById(reportList);
            }
            //再删除结算单
            this.removeById(id);
        } 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;
    }
}