package com.tofly.feesapi.sfgl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.google.common.collect.Lists;
import com.tofly.common.core.util.StringUtil;
import com.tofly.feesapi.bjgl.entity.YhCbkxx;
import com.tofly.feesapi.bmgl.entity.BmCbb;
import com.tofly.feesapi.bmgl.entity.BmCbpq;
import com.tofly.feesapi.bmgl.entity.BmSbsccj;
import com.tofly.feesapi.bmgl.entity.BmSj;
import com.tofly.feesapi.bmgl.service.BmCbbService;
import com.tofly.feesapi.bmgl.service.BmCbpqService;
import com.tofly.feesapi.bmgl.service.BmSbsccjService;
import com.tofly.feesapi.bmgl.service.BmSjService;
import com.tofly.feesapi.cbgl.entity.YyCblr;
import com.tofly.feesapi.cbgl.service.YyCblrService;
import com.tofly.feesapi.common.constant.CbjsfsEnum;
import com.tofly.feesapi.common.constant.SflxEnum;
import com.tofly.feesapi.common.core.dto.PageDto;
import com.tofly.feesapi.common.core.vo.PageResult;
import com.tofly.feesapi.common.dzfp.InvoiceService;
import com.tofly.feesapi.common.enums.BcFylxEnum;
import com.tofly.feesapi.common.util.GuidGenerator;
import com.tofly.feesapi.common.util.ToolsUtils;
import com.tofly.feesapi.sfgl.entity.YyQfmx;
import com.tofly.feesapi.sfgl.entity.YySspjxx;
import com.tofly.feesapi.sfgl.entity.ZnbCsjsLog;
import com.tofly.feesapi.sfgl.entity.dto.ZnbCsjsFilter;
import com.tofly.feesapi.sfgl.entity.dto.ZnbCsjsListFilter;
import com.tofly.feesapi.sfgl.entity.vo.SfJsJg;
import com.tofly.feesapi.sfgl.entity.vo.ZnbCsjsSelect;
import com.tofly.feesapi.sfgl.mapper.ZnbCsjsLogMapper;
import com.tofly.feesapi.sfgl.service.IZnbCsjsLogService;
import com.tofly.feesapi.sfgl.service.YyQfmxService;
import com.tofly.feesapi.sfgl.service.YySspjxxService;
import com.tofly.feesapi.xtgl.entity.Syscommlog;
import com.tofly.feesapi.xtgl.service.ISyscommlogService;
import com.tofly.feesapi.xtgl.service.impl.SysGdcsbServiceImpl;
import com.tofly.feesapi.yhgl.entity.YhKhjbxx;
import com.tofly.feesapi.yhgl.entity.YyZjzh;
import com.tofly.feesapi.yhgl.service.YhKhjbxxService;
import com.tofly.feesapi.yhgl.service.impl.YyZjzhServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ZnbCsjsLogServiceImpl extends ServiceImpl<ZnbCsjsLogMapper, ZnbCsjsLog> implements IZnbCsjsLogService {

    @Autowired
    private YyQfmxService qfmxService;

    @Autowired
    private YyZjzhServiceImpl zjzhService;

    @Autowired
    private YySspjxxService sspjxxService;
    @Autowired
    private BmCbbService bmCbbService;
    @Autowired
    private BmSbsccjService bmSbsccjService;

    @Autowired
    private BmCbpqService bmCbpqService;

    @Autowired
    private YhKhjbxxService yhKhjbxxService;

    @Autowired
    private SysGdcsbServiceImpl sysGdcsbService;

    @Autowired
    private InvoiceService invoiceService;

    @Autowired
    private YyCblrService yyCblrService;

    @Autowired
    private BmSjService sjService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private ISyscommlogService syscommlogService;


    @Override
    public ZnbCsjsLog csjs(YhCbkxx cbkxx, YhKhjbxx khjbxx, String cwrq, BigDecimal scds, BigDecimal bcds, String cbLogId) throws Exception {
        if (scds == null || bcds == null || scds.compareTo(BigDecimal.ZERO) < 0 || bcds.compareTo(BigDecimal.ZERO) < 0)
            return null;
        BigDecimal sjsl = bcds.subtract(scds);
        if (sjsl.compareTo(BigDecimal.ZERO) < 0) return null;
        if (this.getByCbLogId(cbLogId) != null) return null;
        ZnbCsjsLog znbCsjsLog = new ZnbCsjsLog();
        SfJsJg sfJsJg = qfmxService.znbsfJs(cbkxx, khjbxx, sjsl);
        BeanUtils.copyProperties(sfJsJg, znbCsjsLog);
        BeanUtils.copyProperties(khjbxx, znbCsjsLog, "bz", "fffs");
        BeanUtils.copyProperties(cbkxx, znbCsjsLog, "bz");
        znbCsjsLog.setCbLogId(cbLogId);
        znbCsjsLog.setCwrq(cwrq);
        String ysyf = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        znbCsjsLog.setYsyf(ysyf);
        znbCsjsLog.setScds(scds);
        znbCsjsLog.setBcds(bcds);
        this.save(znbCsjsLog);
        return znbCsjsLog;
    }

    public ZnbCsjsLog getByCbLogId(String cbLogId) {
        return this.getOne(Wrappers.lambdaQuery(ZnbCsjsLog.class).eq(ZnbCsjsLog::getCbLogId, cbLogId));
    }

    @Override
    public PageResult<ZnbCsjsSelect> getPage(PageDto pageDto, ZnbCsjsFilter filter) {
        PageDto<ZnbCsjsSelect> page = this.baseMapper.getPage(pageDto, filter);
        PageResult<ZnbCsjsSelect> pageResult = page.toVo();
        return pageResult;
    }

    @Override
    public List<ZnbCsjsLog> getYhysmxList(ZnbCsjsListFilter filter) {

        List<ZnbCsjsLog> lst = baseMapper.getYhysmxList(filter);
        List<BmCbb> bmCbbs = bmCbbService.selectList();
        List<BmCbpq> bmcbpq = bmCbpqService.list();
        if (CollUtil.isNotEmpty(lst)) {
            lst = lst.stream().map(item -> {

                BmCbb cbb = bmCbbs.stream().filter(p -> p.getCbbbm().equals(item.getSscbb())).findFirst().orElse(null);

                BmCbpq cbpq = bmcbpq.stream().filter(p -> p.getCbpqbm().equals(item.getSscbpq())).findFirst().orElse(null);
                if (!StringUtil.isNull(cbb)) {
                    item.setSscbb(cbb.getCbbmc());
                }

                if (!StringUtil.isNull(cbpq)) {
                    item.setSscbb(cbpq.getCbpqmc());
                }

                return item;
            }).collect(Collectors.toList());


        }


        return baseMapper.getYhysmxList(filter);
    }

    @Override
    public PageResult<ZnbCsjsLog> getYhysmxList2(PageDto pageDto, ZnbCsjsListFilter filter) {
        PageDto<ZnbCsjsLog> page = baseMapper.getYhysmxList(pageDto, filter);

        List<ZnbCsjsLog> records = page.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            List<BmCbb> bmCbbs = bmCbbService.selectList();

            if (CollUtil.isNotEmpty(bmCbbs)) {
                Map<String, String> cbbMap = bmCbbs.stream().collect(Collectors.toMap(BmCbb::getCbbbm, BmCbb::getCbbmc));
                records.forEach(o -> {
                    if (StrUtil.isNotEmpty(o.getSscbb())) {
                        o.setSscbb(cbbMap.get(o.getSscbb()));
                    }
                });
            }

            List<BmSbsccj> bmSbsccjs = bmSbsccjService.selectList();
            if (CollUtil.isNotEmpty(bmSbsccjs)) {
                Map<String, String> sbcjMap = bmSbsccjs.stream().collect(Collectors.toMap(BmSbsccj::getCode, BmSbsccj::getName));
                records.forEach(o -> {
                    if (StrUtil.isNotEmpty(o.getSbsccj())) {
                        o.setSccj(sbcjMap.get(o.getSbsccj()));
                    }
                });
            }
        }

        PageResult<ZnbCsjsLog> pageResult = page.toVo();
        return pageResult;

    }

    /*智能表账单生成*/
    @Transactional
    public void znbZdsc_old(String cwrq) {

        QueryWrapper<ZnbCsjsLog> queryWrapper = new QueryWrapper<>();
        //LambdaQueryWrapper<ZnbCsjsLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select("YHBH", "CBKID", "MIN(CBKH) CBKH", "bjbh", "sjbm", "CWRQ", "MIN(SCDS) SCDS", "MAX(BCDS) BCDS", "SUM(JJL) JJL", "SUM(SL) SL", "SUM(SF) SF",
                "SUM(WSF) WSF", "SUM(SL1) SL1", "SUM(SF1) SF1", "SUM(WSF1) WSF1",
                "SUM(SL2) SL2", "SUM(SF2) SF2", "SUM(WSF2) WSF2", "SUM(SL3) SL3",
                "SUM(SF3) SF3", "SUM(WSF3) WSF3", "SUM(YSSL) YSSL", "SUM(YSSF) YSSF",
                "SUM(YSWSF) YSWSF", "SUM(YSLJF) YSLJF", "SUM(YSQT) YSQT",
                "SUM(YSJE) YSJE", "SUM(JT1SL) JT1SL", "SUM(JT1SF) JT1SF",
                "SUM(JT2SL) JT2SL", "SUM(JT2SF) JT2SF", "SUM(JT3SL) JT3SL",
                "SUM(JT3SF) JT3SF", "SUM(JT4SL) JT4SL", "SUM(JT4SF) JT4SF",
                "SUM(LJF) LJF", "SUM(LJF1) LJF1", "SUM(LJF2) LJF2", "SUM(LJF3) LJF3",
                "SUM(BCKJ) BCKJ", "SUM(YSSZYS) YSSZYS", "SUM(SZYS) SZYS"
        ).eq("SFBZ", "1").and(p -> p.eq("CWRQ", cwrq)).groupBy("yhbh", "cbkid", "bjbh", "sjbm", "cwrq").orderByAsc("yhbh");


        /*循环生成账单*/
        List<ZnbCsjsLog> lstCsjs = this.list(queryWrapper);
        List<YyZjzh> zjzhs = new ArrayList<>();
        ;

        //获取客户基本信息
        List<YhKhjbxx> yhKhjbxxes = new ArrayList<>();
        List<YyCblr> cblrs = new ArrayList<>();
        ;

        List<BmSj> sjList = sjService.list();

        if (lstCsjs.size() > 1000) {
            // 超过1000分段
            List<List<ZnbCsjsLog>> znbCsjsList = Lists.partition(new ArrayList<>(lstCsjs), 1000);


            for (List<ZnbCsjsLog> znbList : znbCsjsList) {
                List<YhKhjbxx> yhjbxxs = yhKhjbxxService.getListByYhbh(znbList.stream().map(ZnbCsjsLog::getYhbh).collect(Collectors.toList()));
                if (CollUtil.isNotEmpty(yhjbxxs)) {
                    yhKhjbxxes.addAll(yhjbxxs);
                }
                cblrs.addAll(yyCblrService.lambdaQuery().in(YyCblr::getCbkid, znbList.stream().map(ZnbCsjsLog::getCbkid).collect(Collectors.toList())).list());
                zjzhs.addAll(zjzhService.lambdaQuery().in(YyZjzh::getYhbh, znbList.stream().map(ZnbCsjsLog::getYhbh).collect(Collectors.toList())).list());
            }

        } else {

            List<YhKhjbxx> yhjbxxs = yhKhjbxxService.getListByYhbh(lstCsjs.stream().map(ZnbCsjsLog::getYhbh).collect(Collectors.toList()));

            if (CollUtil.isNotEmpty(yhjbxxs)) {
                yhKhjbxxes.addAll(yhjbxxs);
            }
            List<String> yhbhs = lstCsjs.stream().map(ZnbCsjsLog::getYhbh).collect(Collectors.toList());
            if (!yhbhs.isEmpty()) {
                zjzhs = zjzhService.lambdaQuery().in(YyZjzh::getYhbh, yhbhs).list();
            }
            List<String> cbkids = lstCsjs.stream().map(ZnbCsjsLog::getCbkid).collect(Collectors.toList());
            if (!cbkids.isEmpty()) {
                cblrs = yyCblrService.lambdaQuery().in(YyCblr::getCbkid, cbkids).list();
            }
            //   lstCblr.addAll(yyCblrService.lambdaQuery().in(YyCblr::getCbkid,lstCsjs.stream().map(ZnbCsjsLog::getCbkid).collect(Collectors.toList()).list());
        }

        List<YyQfmx> lstQfmx = new ArrayList<>();
        List<YySspjxx> lstSspjxx = new ArrayList<>();
        List<YyZjzh> lstZjzh = new ArrayList<>();
        List<YyCblr> lstClbrs = new ArrayList<>();
        //在滚动财务日期之前
        String strcwrq = sysGdcsbService.selectCwrq();
        CopyOptions options = CopyOptions.create().setIgnoreNullValue(true);
        Date dateNow = new Date();


        List<YyZjzh> finalZjzhs = zjzhs;
        List<YyCblr> finalCblrs = cblrs;
        lstCsjs.forEach(p -> {

            YhKhjbxx khjbxx = yhKhjbxxes.stream().filter(yh -> yh.getYhbh().equals(p.getYhbh())).findFirst().orElse(null);

            if (khjbxx == null) {
                return;
            }

            BmSj bmSj = sjList.stream().filter(fi -> fi.getCode().equals(p.getSjbm())).findFirst().orElse(null);
            BigDecimal syzsdj = BigDecimal.ZERO;
            BigDecimal sj = BigDecimal.ZERO;
            BigDecimal wsfdj = BigDecimal.ZERO;

            if (bmSj != null) {
                syzsdj = bmSj.getSzyfdj();
                sj = bmSj.getSj();
                wsfdj = bmSj.getWsfdj();
            }

            /*欠费明细*/
            YyQfmx qfmx = new YyQfmx();
            //BeanUtils.copyProperties(p, qfmx);
            BeanUtil.copyProperties(p, qfmx, options.setOverride(true));
            String qflsbh = ToolsUtils.getGuid();
            qfmx.setSscbb(khjbxx.getSscbb());
            qfmx.setSscbpq(khjbxx.getSscbpq());
            qfmx.setId(ToolsUtils.getGuid());
            qfmx.setQflsbh(qflsbh);
            qfmx.setCbkid(p.getCbkid());
            qfmx.setCbkh(p.getCbkh());
            qfmx.setYsyf(p.getCwrq());
            qfmx.setCwrq(p.getCwrq());
            qfmx.setCbrybm("4");
            qfmx.setCbryxm("物联网抄表");
            qfmx.setCbrq(dateNow);
            qfmx.setLrrq(dateNow);
            qfmx.setJsrq(dateNow);
            qfmx.setLrrybm("3");
            qfmx.setLrryxm("系统机器");
            qfmx.setSfbz("1");
            qfmx.setYhxm(khjbxx.getYhxm());
            qfmx.setSfrq(dateNow);
            qfmx.setBz("智能表账单生成");
            qfmx.setCblx("0");
            qfmx.setCbfs("1");
            qfmx.setSzyf(p.getSzys());
            qfmx.setSzyfDj(syzsdj);
            qfmx.setYsszyf(p.getYsszys());
            qfmx.setSj(sj);
            qfmx.setWsfdj(wsfdj);
            qfmx.setCbly("3");

            String sflsbh = ToolsUtils.getGuid();
            qfmx.setSflsbh(sflsbh);
            lstQfmx.add(qfmx);

            YyZjzh zjzh = finalZjzhs.stream().filter(m -> m.getYhbh().equals(p.getYhbh())).findFirst().orElse(null);
            if (zjzh == null) {
                zjzh = new YyZjzh();
                zjzh.setYhbh(p.getYhbh());
                zjzh.setYfje(BigDecimal.ZERO);
                zjzh.setSyje(BigDecimal.ZERO);
                zjzh.setNbsyje(BigDecimal.ZERO);
                zjzh.setKjje(BigDecimal.ZERO);
            }

            /*实收明细*/
            YySspjxx sspjxx = new YySspjxx();
            BeanUtil.copyProperties(qfmx, sspjxx, options.setOverride(true));
            //  BeanUtils.copyProperties(qfmx,sspjxx);
            sspjxx.setId(ToolsUtils.getGuid());
            sspjxx.setQfid(qfmx.getId());
            sspjxx.setYsyf(qfmx.getYsyf());
            sspjxx.setScye(zjzh.getSyje());
            sspjxx.setBckj(p.getBckj());
            sspjxx.setBcye(zjzh.getSyje().subtract(p.getBckj()));
            sspjxx.setSfrq(dateNow);
            sspjxx.setSfrybm("3");
            sspjxx.setSfryxm("系统自动扣减");
            sspjxx.setBz("智能表账单生成");
            sspjxx.setSfxh(1);
            sspjxx.setNbsyje(zjzh.getNbsyje());
            sspjxx.setFffs("9"); //预存扣减
            sspjxx.setSflx(SflxEnum.预存抵扣);
            lstSspjxx.add(sspjxx);

            if (p.getBckj().compareTo(BigDecimal.ZERO) > 0) {
                zjzh.setKjje(zjzh.getKjje().add(p.getBckj()));
                zjzh.setSyje(zjzh.getSyje().subtract(p.getBckj()));
                lstZjzh.add(zjzh);
            }
            /*抄表录入*/
            YyCblr cblr = finalCblrs.stream().filter(yh -> yh.getCbkid().equals(p.getCbkid())).findFirst().orElse(null);
            if (cblr == null) {
                return;
            }
            //cblr.setScds(cblr.getNbzxds());
            cblr.setBcds(cblr.getNbzxds());
            cblr.setSl(qfmx.getYssl());
            lstClbrs.add(cblr);
        });
        /*更新业务*/
        if (qfmxService.saveBatch(lstQfmx) && sspjxxService.saveBatch(lstSspjxx) && zjzhService.saveOrUpdateBatch(lstZjzh) && yyCblrService.saveOrUpdateBatch(lstClbrs)) {
            log.info("智能表账单生成");
            if (!CollectionUtil.isEmpty(yhKhjbxxes)) {
                yhKhjbxxes.forEach(p -> {
                    List<YyQfmx> qfmxList =
                            lstQfmx.stream().filter(fi -> fi.getYhbh().equals(p.getYhbh())).collect(Collectors.toList());

                    List<YySspjxx> sspjxx =
                            lstSspjxx.stream().filter(fi -> fi.getYhbh().equals(p.getYhbh())).collect(Collectors.toList());
                    /*查询当前欠费是否大于0*/
                    BigDecimal sumQfje = qfmxList.stream()
                            .map(obj -> obj.getYsje())
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    if (CollUtil.isNotEmpty(qfmxList) && sumQfje.compareTo(BigDecimal.ZERO) > 0) {
                        invoiceService.addInvoiceData(qfmxList, sspjxx, p, "0", p.getSfkp());
                    }
                });
            }
            log.info("生成电子发票");
        }
        log.info("完成");
    }

    @Override
    @Transactional
    public void znbZdsc(String cwrq) {
        QueryWrapper<ZnbCsjsLog> queryWrapper = new QueryWrapper<>();
        //LambdaQueryWrapper<ZnbCsjsLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select("YHBH", "CBKID", "MIN(CBKH) CBKH", "bjbh",
                        "sjbm", "sjbm1", "sjbm2", "sjbm3",
                        "CWRQ", "MIN(SCDS) SCDS", "MAX(BCDS) BCDS", "SUM(JJL) JJL",
                        "MIN(JTZQLJL_JSQ) JTZQLJL_JSQ", "MAX(JTZQLJL) JTZQLJL",
                        "SUM(SL) SL", "SUM(SF) SF", "SUM(WSF) WSF", "SUM(LJF) LJF",
                        "SUM(SL1) SL1", "SUM(SF1) SF1", "SUM(WSF1) WSF1", "SUM(LJF1) LJF1",
                        "SUM(SL2) SL2", "SUM(SF2) SF2", "SUM(WSF2) WSF2", "SUM(LJF2) LJF2",
                        "SUM(SL3) SL3", "SUM(SF3) SF3", "SUM(WSF3) WSF3", "SUM(LJF3) LJF3",
                        "SUM(JT1SL) JT1SL", "SUM(JT1SF) JT1SF",
                        "SUM(JT2SL) JT2SL", "SUM(JT2SF) JT2SF",
                        "SUM(JT3SL) JT3SL", "SUM(JT3SF) JT3SF",
                        "SUM(JT4SL) JT4SL", "SUM(JT4SF) JT4SF",
                        "SUM(SJ1_JT1SL) SJ1_JT1SL", "SUM(SJ1_JT1SF) SJ1_JT1SF",
                        "SUM(SJ1_JT2SL) SJ1_JT2SL", "SUM(SJ1_JT2SF) SJ1_JT2SF",
                        "SUM(SJ1_JT3SL) SJ1_JT3SL", "SUM(SJ1_JT3SF) SJ1_JT3SF",
                        "SUM(SJ1_JT4SL) SJ1_JT4SL", "SUM(SJ1_JT4SF) SJ1_JT4SF",
                        "SUM(SJ2_JT1SL) SJ2_JT1SL", "SUM(SJ2_JT1SF) SJ2_JT1SF",
                        "SUM(SJ2_JT2SL) SJ2_JT2SL", "SUM(SJ2_JT2SF) SJ2_JT2SF",
                        "SUM(SJ2_JT3SL) SJ2_JT3SL", "SUM(SJ2_JT3SF) SJ2_JT3SF",
                        "SUM(SJ2_JT4SL) SJ2_JT4SL", "SUM(SJ2_JT4SF) SJ2_JT4SF",
                        "SUM(YSSL) YSSL", "SUM(YSSF) YSSF", "SUM(YSWSF) YSWSF", "SUM(YSLJF) YSLJF",
                        "SUM(YSJE) YSJE",
                        "SUM(BCKJ) BCKJ", "SUM(YSSZYS) YSSZYS", "SUM(SZYS) SZYS"
                ).eq("SFBZ", "1").and(p -> p.eq("CWRQ", cwrq))
                .groupBy("yhbh", "cbkid", "bjbh", "cwrq",
                        "sjbm", "sjbm1", "sjbm2", "sjbm3").orderByAsc("yhbh");
        List<ZnbCsjsLog> lstCsjs = this.list(queryWrapper);
        if (CollUtil.isEmpty(lstCsjs)) {
            log.info("当前财务日期:" + cwrq + "无智能表结算明细");
            return;
        }

        List<YhKhjbxx> yhKhjbxxes = new ArrayList<>();
        List<YyCblr> cblrs = new ArrayList<>();
        List<BmSj> sjList = sjService.list();
        List<List<String>> liststr = Lists.partition(new ArrayList<>(lstCsjs.stream()
                .map(o -> o.getYhbh()).collect(Collectors.toList())), 1000);
        for (List<String> yhbhs : liststr) {
            List<YhKhjbxx> yhKhjbxxList = yhKhjbxxService.lambdaQuery().in(YhKhjbxx::getYhbh, yhbhs).list();
            yhKhjbxxes.addAll(yhKhjbxxList);
            List<YyCblr> cblrList = yyCblrService.lambdaQuery().in(YyCblr::getYhbh, yhbhs).list();
            cblrs.addAll(cblrList);
        }
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                Runtime.getRuntime().availableProcessors() * 2,  // 核心线程数
                Runtime.getRuntime().availableProcessors() * 4,  // 最大线程数
                60L, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2000),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
        CopyOptions options = CopyOptions.create().setIgnoreNullValue(true);
        AtomicInteger count = new AtomicInteger();
        StringBuilder cbkids = new StringBuilder();
        Date defaultDate = this.DefaultDate();
        List<YyQfmx> qfmxs = new ArrayList<>();
        List<YySspjxx> sspjxxes = new ArrayList<>();
        List<CompletableFuture<Void>> futureList = lstCsjs.stream()
                .map(item -> CompletableFuture.runAsync(() -> {
                    transactionTemplate.execute(status -> {
                        try {
                            YhKhjbxx khjbxx = yhKhjbxxes.stream().filter(o -> o.getYhbh().equals(item.getYhbh())).findFirst().orElse(null);
                            if (khjbxx == null) {
                                return false;
                            }
                            /*欠费明细*/
                            YyQfmx qfmx = new YyQfmx();
                            //BeanUtils.copyProperties(p, qfmx);
                            BeanUtil.copyProperties(item, qfmx, options.setOverride(true));
                            String qflsbh = GuidGenerator.getQflsbh();
                            qfmx.setSscbb(khjbxx.getSscbb());
                            qfmx.setSscbpq(khjbxx.getSscbpq());
                            qfmx.setId(GuidGenerator.getGuid());
                            qfmx.setQflsbh(qflsbh);
                            qfmx.setCbkid(item.getCbkid());
                            qfmx.setCbkh(item.getCbkh());
                            qfmx.setYsyf(item.getCwrq());
                            qfmx.setCwrq(item.getCwrq());
                            qfmx.setCbrybm("4");
                            qfmx.setCbryxm("物联网抄表");
                            qfmx.setCbrq(defaultDate);
                            qfmx.setLrrq(defaultDate);
                            qfmx.setJsrq(defaultDate);
                            qfmx.setLrrybm("3");
                            qfmx.setLrryxm("系统机器");
                            qfmx.setSfbz("1");
                            qfmx.setYhxm(khjbxx.getYhxm());
                            qfmx.setSfrq(defaultDate);
                            qfmx.setBz("智能表账单生成测试");
                            qfmx.setCblx("0");
                            qfmx.setCbfs("1");
                            qfmx.setSzyf(item.getSzys());
                            qfmx.setYsszyf(item.getYsszys());
                            qfmx.setCbly("3");
                            BmSj bmSj = sjList.stream().filter(fi -> fi.getCode().equals(item.getSjbm())).findFirst().orElse(null);
                            if (bmSj != null) {
                                qfmx.setSj(StringUtil.isNull(bmSj.getSj()) ? BigDecimal.ZERO : bmSj.getSj());
                                qfmx.setWsfdj(StringUtil.isNull(bmSj.getWsfdj()) ? BigDecimal.ZERO : bmSj.getWsfdj());
                                qfmx.setSzyfDj(StringUtil.isNull(bmSj.getSzyfdj()) ? BigDecimal.ZERO : bmSj.getSzyfdj());
                                if ("1".equals(bmSj.getJtbz())) {
                                    qfmx.setJt1sj(StringUtil.isNull(bmSj.getJt1Sj()) ? BigDecimal.ZERO : bmSj.getJt1Sj());
                                    qfmx.setJt2sj(StringUtil.isNull(bmSj.getJt2Sj()) ? BigDecimal.ZERO : bmSj.getJt2Sj());
                                    qfmx.setJt3sj(StringUtil.isNull(bmSj.getJt3Sj()) ? BigDecimal.ZERO : bmSj.getJt3Sj());
                                }
                            }
                            BmSj bmSj1 = sjList.stream().filter(fi -> fi.getCode().equals(item.getSjbm1())).findFirst().orElse(null);
                            if (bmSj1 != null) {
                                qfmx.setSj1(StringUtil.isNull(bmSj1.getSj()) ? BigDecimal.ZERO : bmSj1.getSj());
                                qfmx.setWsfdj1(StringUtil.isNull(bmSj1.getWsfdj()) ? BigDecimal.ZERO : bmSj1.getWsfdj());
                                qfmx.setSzyfDj1(StringUtil.isNull(bmSj1.getSzyfdj()) ? BigDecimal.ZERO : bmSj1.getSzyfdj());
                                if ("1".equals(bmSj1.getJtbz())) {
                                    qfmx.setSj1Jt1sj(StringUtil.isNull(bmSj1.getJt1Sj()) ? BigDecimal.ZERO : bmSj1.getJt1Sj());
                                    qfmx.setSj1Jt2sj(StringUtil.isNull(bmSj1.getJt2Sj()) ? BigDecimal.ZERO : bmSj1.getJt2Sj());
                                    qfmx.setSj1Jt3sj(StringUtil.isNull(bmSj1.getJt3Sj()) ? BigDecimal.ZERO : bmSj1.getJt3Sj());
                                }
                            }
                            BmSj bmSj2 = sjList.stream().filter(fi -> fi.getCode().equals(item.getSjbm2())).findFirst().orElse(null);
                            if (bmSj2 != null) {
                                qfmx.setSj2(StringUtil.isNull(bmSj2.getSj()) ? BigDecimal.ZERO : bmSj2.getSj());
                                qfmx.setWsfdj2(StringUtil.isNull(bmSj2.getWsfdj()) ? BigDecimal.ZERO : bmSj2.getWsfdj());
                                qfmx.setSzyfDj2(StringUtil.isNull(bmSj2.getSzyfdj()) ? BigDecimal.ZERO : bmSj2.getSzyfdj());
                                if ("1".equals(bmSj2.getJtbz())) {
                                    qfmx.setSj2Jt1sj(StringUtil.isNull(bmSj2.getJt1Sj()) ? BigDecimal.ZERO : bmSj2.getJt1Sj());
                                    qfmx.setSj2Jt2sj(StringUtil.isNull(bmSj2.getJt2Sj()) ? BigDecimal.ZERO : bmSj2.getJt2Sj());
                                    qfmx.setSj2Jt3sj(StringUtil.isNull(bmSj2.getJt3Sj()) ? BigDecimal.ZERO : bmSj2.getJt3Sj());
                                }
                            }
                            CbjsfsEnum cbjsfs = this.getCbjsfs(bmSj, bmSj1, bmSj2);
                            qfmx.setCbjsbz(cbjsfs.getValue());
                            qfmx.setCbjsfs(cbjsfs.name());
                            qfmx.setFylx(BcFylxEnum.Zhfy.getValue().toString());
                            qfmx.setFylxmc(BcFylxEnum.Zhfy.getName());

                            String sflsbh = GuidGenerator.getSflsbh();
                            qfmx.setSflsbh(sflsbh);
                            /*实收明细*/
                            YySspjxx sspjxx = null;
                            if (qfmx.getYsje().compareTo(BigDecimal.ZERO) > 0) {
                                sspjxx = new YySspjxx();
                                YyZjzh zjzh = zjzhService.getById(item.getYhbh());
                                if (zjzh == null) {
                                    zjzh = new YyZjzh();
                                    zjzh.setYhbh(item.getYhbh());
                                    zjzh.setYfje(BigDecimal.ZERO);
                                    zjzh.setSyje(BigDecimal.ZERO);
                                    zjzh.setNbsyje(BigDecimal.ZERO);
                                    zjzh.setKjje(BigDecimal.ZERO);
                                }
                                BeanUtil.copyProperties(qfmx, sspjxx, options.setOverride(true));
                                //  BeanUtils.copyProperties(qfmx,sspjxx);
                                sspjxx.setId(GuidGenerator.getGuid());
                                sspjxx.setQfid(qfmx.getId());
                                sspjxx.setYsyf(qfmx.getYsyf());
                                sspjxx.setScye(zjzh.getSyje());
                                sspjxx.setBckj(item.getBckj());
                                sspjxx.setBcye(zjzh.getSyje().subtract(item.getBckj()));
                                sspjxx.setSfrq(defaultDate);
                                sspjxx.setSfrybm("3");
                                sspjxx.setSfryxm("系统机器");
                                sspjxx.setBz("智能表账单生成");
                                sspjxx.setSfxh(1);
                                sspjxx.setNbsyje(zjzh.getNbsyje());
                                sspjxx.setFffs("9"); //预存扣减
                                sspjxx.setSflx(SflxEnum.预存抵扣);
                                sspjxxService.save(sspjxx);

                                if (item.getBckj().compareTo(BigDecimal.ZERO) > 0) {
                                    zjzh.setKjje(zjzh.getKjje().add(item.getBckj()));
                                    zjzh.setSyje(zjzh.getSyje().subtract(item.getBckj()));
                                    zjzhService.saveOrUpdate(zjzh);
                                }
                            } else {
                                qfmx.setSfbz("4");
                            }
                            qfmxService.save(qfmx);
                            /*抄表录入*/
                            YyCblr cblr = cblrs.stream().filter(cb -> cb.getCbkid().equals(item.getCbkid())).findFirst().orElse(null);
                            if (cblr == null) {
                                return false;
                            }
                            //cblr.setScds(cblr.getNbzxds());
                            cblr.setBcds(cblr.getNbzxds());
                            cblr.setSl(qfmx.getYssl());
                            cblr.setBz(qfmx.getBz());
                            yyCblrService.updateById(cblr);
                            count.incrementAndGet();
                            if (StringUtil.isNotNull(sspjxx)) {
                                sspjxxes.add(sspjxx);
                                qfmxs.add(qfmx);
                            }
                            return true;
                        } catch (Exception e) {
                            log.error("智能表月结算异常:", e);
                            cbkids.append(item.getCbkid()).append(",");
                            status.setRollbackOnly();
                            return false;
                        }
                    });
                }, executor))
                .collect(Collectors.toList());

        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).join();
        executor.shutdown();
        //发票插入
        if (!sspjxxes.isEmpty()) {
            yhKhjbxxes.forEach(p -> {
                List<YyQfmx> qfmxList = qfmxs.stream().filter(fi -> fi.getYhbh().equals(p.getYhbh()))
                        .sorted(Comparator.comparing(YyQfmx::getCwrq)).collect(Collectors.toList());
                List<YySspjxx> sspjxx = sspjxxes.stream().filter(fi -> fi.getYhbh().equals(p.getYhbh()))
                        .sorted(Comparator.comparing(YySspjxx::getBcye).reversed()).collect(Collectors.toList());
                if (!qfmxList.isEmpty() && !sspjxx.isEmpty()) {
                    invoiceService.addInvoiceData(qfmxList, sspjxx, p, "0", p.getSfkp());
                }
            });
        }
        String msg = "";
        if (StringUtil.isNotEmpty(cbkids.toString())) {
            msg = String.format("汇总失败抄表卡ID：%s！", cbkids);
        }
        Syscommlog syscommlog = new Syscommlog();
        syscommlog.setTablename("znb_csjs_log");
        syscommlog.setMstext("智能表月结算cbymjzTask");
        syscommlog.setAddate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss")));
        syscommlog.setRemark(String.format("智能表账单汇总：共%s户，成功汇总%s户,失败%s户；%s", lstCsjs.size(), count, lstCsjs.size() - count.get(), msg));
        syscommlog.setUserid("3");
        syscommlogService.save(syscommlog);
    }

    private CbjsfsEnum getCbjsfs(BmSj bmSj, BmSj bmSj1, BmSj bmSj2) {
        CbjsfsEnum cbjsfs = CbjsfsEnum.正常单价计费;
        if (StringUtil.isNotNull(bmSj) && "1".equals(bmSj.getJtbz())) {
            cbjsfs = CbjsfsEnum.阶梯计费;
        }
        if (StringUtil.isNotNull(bmSj1)) {
            if (cbjsfs.equals(CbjsfsEnum.阶梯计费) || "1".equals(bmSj1.getJtbz())) {
                cbjsfs = CbjsfsEnum.一表多价含阶梯;
            } else {
                cbjsfs = CbjsfsEnum.一表多价计费;
            }
        }
        if (StringUtil.isNotNull(bmSj2) && cbjsfs.equals(CbjsfsEnum.一表多价计费)) {
            if ("1".equals(bmSj2.getJtbz())) {
                cbjsfs = CbjsfsEnum.一表多价含阶梯;
            }
        }
        return cbjsfs;
    }

    //默认时间为yyyyMMdd-1 23:59:59
    private Date DefaultDate() {
        //智能表结转收费日期直接默认结转日的前一天的23:59:59
        LocalDate currentDate = LocalDate.now();
        LocalDate targetDate = LocalDate.of(currentDate.getYear(),
                currentDate.getMonthValue(),
                currentDate.getDayOfMonth() - 1);
        LocalTime endTime = LocalTime.of(23, 59, 59);
        Date date = Date.from(targetDate.atTime(endTime).atZone(ZoneId.systemDefault()).toInstant());
        return date;
    }
}
