package com.tofly.third.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
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.tofly.common.core.util.StringUtil;
import com.tofly.third.common.constant.BcFylxEnum;
import com.tofly.third.common.constant.CbjsfsEnum;
import com.tofly.third.common.constant.JtjslxEnum;
import com.tofly.third.common.constant.PjztEnum;
import com.tofly.third.common.dto.SfJsJg;
import com.tofly.third.common.dto.Sjmx;
import com.tofly.third.common.exception.BusinessException;
import com.tofly.third.common.req.Cbxx;
import com.tofly.third.common.util.ServerUtil;
import com.tofly.third.entity.*;
import com.tofly.third.mapper.ZnbCsjsLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Slf4j
@Service
public class ZnbCsjsLogService extends ServiceImpl<ZnbCsjsLogMapper, ZnbCsjsLog> {

    private final static Map<String, BmSj> sjCache = new HashMap<>();

    @Autowired
    private BmSjService bmSjService;
    @Autowired
    private YhCbkxxService cbkxxService;
    @Autowired
    private YhKhjbxxService khjbxxService;
    @Autowired
    private YyCblrService cblrService;
    @Autowired
    private BmDbhysyhService bmDbhysyhService;


    /**
     * 智能表算费(同普表算费)
     * 附加费、消防栓费为每月一算
     */
    public ZnbCsjsLog znbsf(Cbxx cbxx, ZnbCbLog znbcb, YhKhjbxx yhKhjbxx, YhCbkxx cbkxx) {
        ZnbCsjsLog znbCsjsLog = new ZnbCsjsLog();

        String znbcbId = znbcb.getId();
        znbCsjsLog.setCbLogId(znbcbId);
        znbCsjsLog.setCbjsbz("0");

        sjCache();

        BigDecimal ljsl = ObjectUtil.isNull(yhKhjbxx.getJtzqljl()) ? BigDecimal.ZERO : yhKhjbxx.getJtzqljl();
        BigDecimal bcjssl = znbcb.getCbSl();

        // 费用计算:水费+其他费(附加、水资源等)，阶梯用水量更新
        SfJsJg sfJsJg = fyjs(cbkxx, yhKhjbxx, ljsl, bcjssl, String.valueOf(znbcb.getCwrq()));
        jtyslgx(sfJsJg, cbkxx, yhKhjbxx);

        BeanUtil.copyProperties(yhKhjbxx, znbCsjsLog, ServerUtil.getNullFields(yhKhjbxx));
        BeanUtils.copyProperties(znbcb, znbCsjsLog, "sl", "id");
        BeanUtils.copyProperties(sfJsJg, znbCsjsLog, ServerUtil.getNullFields(sfJsJg));
        znbCsjsLog.setYsyf(znbcb.getCwrq());
        //判断是否进行过算费
        long count = this.baseMapper.selectCount(new QueryWrapper<ZnbCsjsLog>().lambda()
                .eq(ZnbCsjsLog::getCbkid, znbCsjsLog.getCbkid())
                .eq(ZnbCsjsLog::getCwrq, znbCsjsLog.getCwrq())
                .eq(ZnbCsjsLog::getYsyf, znbCsjsLog.getYsyf()));
        if (count == 0) {
            // 附加费
            if (cbkxx.getFjf() != null && cbkxx.getFjf().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal fjf = cbkxx.getFjf();
                znbCsjsLog.setYsfjf(fjf);
                znbCsjsLog.setFjf(fjf);
                znbCsjsLog.setFjfdj(fjf);
            }
            // 消防栓费
            if (cbkxx.getXfsf() != null && cbkxx.getXfsf().compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal xfsf = cbkxx.getXfsf();
                znbCsjsLog.setYsqt(xfsf);
            }
            znbCsjsLog.setYsje(znbCsjsLog.getYsje().add(znbCsjsLog.getYsfjf()).add(znbCsjsLog.getYsqt()));
        }
        znbCsjsLog.setSfbc("0");
        znbCsjsLog.setFylx(BcFylxEnum.Zhfy.getValue().toString());
        znbCsjsLog.setFylxmc(BcFylxEnum.Zhfy.getName());
        znbCsjsLog.setCbly("3");


        znbCsjsLog.setChbz(PjztEnum.ZC.getValue());
        znbCsjsLog.setCbrq(DateUtil.parse(cbxx.getCbsj(), DatePattern.NORM_DATETIME_FORMAT));
        znbCsjsLog.setSfrybm("3");
        znbCsjsLog.setSfryxm("系统机器");
        znbCsjsLog.setSflx("1");
        znbCsjsLog.setBjbh(cbxx.getBjbh());
        znbCsjsLog.setSbsccj(cbkxx.getSbsccj());

        save(znbCsjsLog);
        return znbCsjsLog;
    }

    private void sjCache() {
        sjCache.clear();
        List<BmSj> sjList = bmSjService.list();
        if (CollectionUtil.isEmpty(sjList)) {
            throw new BusinessException("系统未配置水价信息");
        }

        sjList.forEach(sj -> sjCache.put(sj.getCode(), sj));
    }


    private SfJsJg fyjs(YhCbkxx cbkxx, YhKhjbxx yhxx, BigDecimal ljsl, BigDecimal bcsl, String cwrq) {
        SfJsJg sfJsJg = new SfJsJg();
        sfJsJg.setRks(yhxx.getRks().toString());
        //判断用户是否是低保户并且月累计量是否大于配置
        if (StringUtil.isNotEmpty(yhxx.getKhlb()) && yhxx.getKhlb().equals("2")) {
            String year = cwrq.substring(0, cwrq.length() - 2);
            String month = cwrq.substring(cwrq.length() - 2);
            BmDbhysyh bmDbhysyh = bmDbhysyhService.lambdaQuery()
                    .eq(BmDbhysyh::getIsdisabled, "1")
                    .eq(BmDbhysyh::getYear, year)
                    .eq(BmDbhysyh::getSdys, Integer.parseInt(month))
                    .one();
            BigDecimal dbhsdsl = bmDbhysyh.getSdsl();
            if (yhxx.getDbhndljl().compareTo(dbhsdsl) < 0) {
                BigDecimal yhsl;
                BigDecimal syyhsl = dbhsdsl.subtract(yhxx.getDbhndljl());
                if (bcsl.compareTo(syyhsl) > 0) {
                    yhsl = syyhsl;
                    bcsl = bcsl.subtract(syyhsl);
                } else {
                    yhsl = bcsl;
                    bcsl = BigDecimal.ZERO;
                    sfJsJg.setSfbz("4");
                }
                sfJsJg.setJyType("2");
                sfJsJg.setIsYh("1");
                sfJsJg.setYhsl(yhsl);
            }
        }

        String cbkid = cbkxx.getCbkid();
        Date now = new Date();
        sfJsJg.setJsrq(now);
        Map<String, BigDecimal> ljslMap = new HashMap<>();
        TreeMap<String, String> slMap = getSlMap(cbkxx, bcsl);

        Map<String, Object> fymxMap = new LinkedHashMap<>();
        slMap.forEach((key, value) -> {
            if (key.equals("L0") || key.equals("L1")) {
                String sjTag = StrUtil.EMPTY;
                String sjTag2 = StrUtil.EMPTY;
                Map<String, Object> values1 = fymxjs(value, ljsl, sjTag, sjTag2, cbkxx, yhxx);
                if (values1.containsKey("ljsl")) {
                    ljslMap.put("ljsljsh", (BigDecimal) values1.get("ljsl"));
                }
                fymxMap.putAll(values1);
            } else if (key.equals("L2")) {
                String sjTag = "sj1";
                String sjTag2 = "1";
                Map<String, Object> values1 = fymxjs(value, ljsl, sjTag, sjTag2, cbkxx, yhxx);
                if (values1.containsKey("ljsl")) {
                    ljslMap.put("ljsljsh", (BigDecimal) values1.get("ljsl"));
                }
                fymxMap.putAll(values1);
            } else if (key.equals("L3")) {
                String sjTag = "sj2";
                String sjTag2 = "2";
                Map<String, Object> values1 = fymxjs(value, ljsl, sjTag, sjTag2, cbkxx, yhxx);
                if (values1.containsKey("ljsl")) {
                    ljslMap.put("ljsljsh", (BigDecimal) values1.get("ljsl"));
                }
                fymxMap.putAll(values1);
            }
        });

        List<BigDecimal> sls = getMxValues(fymxMap, "sl");
        List<BigDecimal> sfs = getMxValues(fymxMap, "sf");
        List<BigDecimal> wsfs = getMxValues(fymxMap, "wsf");
        List<BigDecimal> ljfs = getMxValues(fymxMap, "ljf");
        List<BigDecimal> szyfs = getMxValues(fymxMap, "szyf");
        List<BigDecimal> ecjyfs = getMxValues(fymxMap, "ecjyf");
        List<BigDecimal> fjfs = getMxValues(fymxMap, "fjf");
        List<BigDecimal> xfsfs = getMxValues(fymxMap, "xfsf");


        BigDecimal yssl = sls.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yssf = sfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal yswsf = wsfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysljf = ljfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysszyf = szyfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysecjyf = ecjyfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysfjf = fjfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal ysxfsf = xfsfs.stream().reduce(BigDecimal.ZERO, BigDecimal::add);

        BeanUtil.copyProperties(fymxMap, sfJsJg, ServerUtil.getNullFields(fymxMap));
        //重新赋值
        sfJsJg.setEcjyf(ysecjyf);
        sfJsJg.setSzys(ysszyf);

        CbjsfsEnum cbjsfs = getCbjsfs(slMap, fymxMap);
        sfJsJg.setCbjsbz(cbjsfs.getValue());
        sfJsJg.setCbjsfs(cbjsfs.getDesc());
        sfJsJg.setJtzqljlJsq(ljsl);
        sfJsJg.setJtzqljl(ljslMap.getOrDefault("ljsljsh", BigDecimal.ZERO));
        sfJsJg.setYssl(yssl);
        sfJsJg.setYssf(yssf);
        sfJsJg.setYsljf(ysljf);
        sfJsJg.setYsszys(ysszyf);
        sfJsJg.setYswsf(yswsf);
        sfJsJg.setYsecjyf(ysecjyf);
        sfJsJg.setYsfjf(ysfjf);
        sfJsJg.setYsqt(ysxfsf);
        sfJsJg.setYsje(yssf.add(ysljf).add(yswsf).add(ysszyf).add(ysfjf).add(ysxfsf).add(ysecjyf));

        log.info("用户抄表卡:{}; 水价:{};", cbkid, fymxMap);
        return sfJsJg;
    }

    private TreeMap<String, String> getSlMap(YhCbkxx cbkxx, BigDecimal bcsl) {
        TreeMap<String, String> slMap = new TreeMap<>();
        String cbkid = cbkxx.getCbkid();
        String ybdjbz = cbkxx.getYbdjbz();

        if (StrUtil.isEmpty(ybdjbz) || "0".equals(ybdjbz)) {
            String sjbm = cbkxx.getSjbm();
            if (StrUtil.isEmpty(sjbm)) {
                throw new BusinessException("用户水表未配置水价信息");
            }

            slMap.put("L0", String.format("%s_%s", sjbm, bcsl));
            return slMap;
        } else {
            String sjbm1 = cbkxx.getSjbm();
            String sjbm2 = cbkxx.getSjbm1();
            String sjbm3 = cbkxx.getSjbm2();
            BigDecimal slbl1 = cbkxx.getSlbl();
            BigDecimal slbl2 = cbkxx.getSlbl1();
            BigDecimal slbl3 = cbkxx.getSlbl2();
            //定量
            BigDecimal sl1 = null;
            BigDecimal sl2 = null;
            BigDecimal sl3 = null;

            BigDecimal sysl = bcsl;
            if (slbl1 != null && slbl1.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm1)) {
                if (slbl1.compareTo(BigDecimal.ONE) > 0) {//按量
                    if (sysl.compareTo(slbl1) >= 0) {
                        sl1 = slbl1;
                        sysl = sysl.subtract(slbl1);
                    } else {
                        sl1 = sysl;
                        sysl = BigDecimal.ZERO;
                    }
                    slMap.put("L1", String.format("%s_%s", sjbm1, sl1));
                }

            }

            if (slbl2 != null && slbl2.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm2)) {
                if (slbl2.compareTo(BigDecimal.ONE) > 0) {//按量
                    if (sysl.compareTo(slbl2) >= 0) {
                        sl2 = slbl2;
                        sysl = sysl.subtract(slbl2);
                    } else {
                        sl2 = sysl;
                        sysl = BigDecimal.ZERO;
                    }
                    slMap.put("L2", String.format("%s_%s", sjbm2, sl2));
                }
            }

            if (slbl3 != null && slbl3.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm3)) {
                if (slbl3.compareTo(BigDecimal.ONE) > 0) {//按量
                    if (sysl.compareTo(slbl3) >= 0) {
                        sl3 = slbl3;
                        sysl = sysl.subtract(slbl3);
                    } else {
                        sl3 = sysl;
                        sysl = BigDecimal.ZERO;
                    }
                    slMap.put("L3", String.format("%s_%s", sjbm3, sl3));
                }
            }

            BigDecimal sysl2 = sysl;//按量以外的剩余水量
            if (slbl1 != null && slbl1.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm1)) {
                if (slbl1.compareTo(BigDecimal.ONE) <= 0) {//按比例
                    sl1 = sysl2.multiply(slbl1).setScale(0, RoundingMode.HALF_UP);
                    sysl = sysl.subtract(sl1);
                    slMap.put("L1", String.format("%s_%s", sjbm1, sl1));
                }
            }

            if (slbl2 != null && slbl2.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm2)) {
                if (slbl2.compareTo(BigDecimal.ONE) <= 0) {//按比例
                    //判断水价3是否存在，存在继续进行比例计算，否则按剩余量计算
                    if (slbl3 != null && slbl3.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm3)) {
                        sl2 = sysl2.multiply(slbl2).setScale(0, RoundingMode.HALF_UP);
                        sysl = sysl.subtract(sl2);
                    } else {
                        sl2 = sysl2.subtract(sl1);
                        sysl = BigDecimal.ZERO;
                    }
                    slMap.put("L2", String.format("%s_%s", sjbm2, sl2));
                }
            }

            if (slbl3 != null && slbl3.compareTo(BigDecimal.ZERO) > 0 && StringUtils.isNotEmpty(sjbm3)) {
                if (slbl3.compareTo(BigDecimal.ONE) <= 0 && sysl2.compareTo(BigDecimal.ZERO) > 0) {
                    sl3 = sysl2.subtract(sl1.add(sl2));
                    sysl = BigDecimal.ZERO;
                    slMap.put("L3", String.format("%s_%s", sjbm3, sl3));
                }
            }

            if (slbl1 != null && slbl1.compareTo(BigDecimal.ZERO) == 0 && StringUtils.isNotEmpty(sjbm1)) {
                sl1 = sysl;
                sysl = BigDecimal.ZERO;
                slMap.put("L1", String.format("%s_%s", sjbm1, sl1));

            }

            if (slbl2 != null && slbl2.compareTo(BigDecimal.ZERO) == 0 && StringUtils.isNotEmpty(sjbm2)) {
                sl2 = sysl;
                sysl = BigDecimal.ZERO;
                slMap.put("L2", String.format("%s_%s", sjbm2, sl2));
            }

            if (slbl3 != null && slbl3.compareTo(BigDecimal.ZERO) == 0 && StringUtils.isNotEmpty(sjbm3)) {
                sl3 = sysl;
                sysl = BigDecimal.ZERO;
                slMap.put("L3", String.format("%s_%s", sjbm3, sl3));
            }

            if (sysl.compareTo(BigDecimal.ZERO) > 0) {
                throw new BusinessException("一表多价有水量未进入计算");
            }
            return slMap;
        }
    }

    private List<BigDecimal> getMxValues(Map<String, Object> values, String prefix) {
        List<BigDecimal> mxValues = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            String key;
            if (i == 0) {
                key = String.format("%s", prefix);
            } else {
                key = String.format("%s%s", prefix, i);
            }

            if (values.containsKey(key)) {
                mxValues.add((BigDecimal) values.getOrDefault(key, BigDecimal.ZERO));
            }
        }
        return mxValues;
    }

    private Map<String, Object> fymxjs(String value, BigDecimal ljsl, String sjTag1, String sjTag2, YhCbkxx cbkxx, YhKhjbxx yhxx) {
        String wsfbz = cbkxx.getWsfbz();
        String ljfbz = cbkxx.getLjfbz();

        String[] values = value.split("_");
        String sjbm = values[0];
        BigDecimal sl = new BigDecimal(values[1]);
        // 根据水价信息计算水费
        Sjmx sjmx = sfjs(sl, sjbm, ljsl, yhxx);
        Map<String, Object> map = new LinkedHashMap<>();
        String prefix = "";
        String suffix = sjTag2;
        map.put(String.format("%s%s%s", prefix, "sjbm", suffix), sjbm);

        // 根据阶梯明细判断是否有阶梯
        Sjmx.Jtmx jtmx = sjmx.getJtmx();
        if (ObjectUtil.isNotNull(jtmx)) {
            // 无阶梯
            prefix = sjTag1;
            suffix = sjTag2;
            map.put(String.format("%s%s%s", prefix, "sl", suffix), jtmx.getSl());
            map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx.getSj());
            map.put(String.format("%s%s%s", prefix, "sf", suffix), jtmx.getSf());

            prefix = StrUtil.EMPTY;
            suffix = sjTag2;
            map.put(String.format("%s%s%s", prefix, "sl", suffix), jtmx.getSl());
            map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx.getSj());
            map.put(String.format("%s%s%s", prefix, "sf", suffix), jtmx.getSf());
            map.put(String.format("%s%s", "sjjtbz", suffix), "0");
        } else {
            // 有阶梯
            map.put(String.format("%s%s", "sjjtbz", suffix), "1");
            Sjmx.Jtmx jtmx1 = sjmx.getJtmx1();
            BigDecimal zsl = BigDecimal.ZERO;
            BigDecimal zsf = BigDecimal.ZERO;

            if (ObjectUtil.isNotNull(jtmx1)) {
                prefix = "jt1";
                if (StringUtils.isNotBlank(sjTag1)) {
                    prefix = sjTag1 + "Jt1";
                }

                suffix = "";
                BigDecimal sl1 = jtmx1.getSl();
                zsl = zsl.add(sl1);
                map.put(String.format("%s%s%s", prefix, "sl", suffix), sl1);
                map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx1.getSj());
                BigDecimal sf = jtmx1.getSf();
                zsf = zsf.add(sf);
                map.put(String.format("%s%s%s", prefix, "sf", suffix), sf);
            }

            Sjmx.Jtmx jtmx2 = sjmx.getJtmx2();
            if (ObjectUtil.isNotNull(jtmx2)) {
                prefix = "jt2";
                if (StringUtils.isNotBlank(sjTag1)) {
                    prefix = sjTag1 + "Jt2";
                }

                suffix = "";
                BigDecimal sl1 = jtmx2.getSl();
                zsl = zsl.add(sl1);
                map.put(String.format("%s%s%s", prefix, "sl", suffix), sl1);
                map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx2.getSj());
                BigDecimal sf = jtmx2.getSf();
                zsf = zsf.add(sf);
                map.put(String.format("%s%s%s", prefix, "sf", suffix), sf);
            }

            Sjmx.Jtmx jtmx3 = sjmx.getJtmx3();
            if (ObjectUtil.isNotNull(jtmx3)) {
                prefix = "jt3";
                if (StringUtils.isNotBlank(sjTag1)) {
                    prefix = sjTag1 + "Jt3";
                }

                suffix = "";
                BigDecimal sl1 = jtmx3.getSl();
                zsl = zsl.add(sl1);
                map.put(String.format("%s%s%s", prefix, "sl", suffix), sl1);
                map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx3.getSj());
                BigDecimal sf = jtmx3.getSf();
                zsf = zsf.add(sf);
                map.put(String.format("%s%s%s", prefix, "sf", suffix), sf);
            }

            Sjmx.Jtmx jtmx4 = sjmx.getJtmx4();
            if (ObjectUtil.isNotNull(jtmx4)) {
                prefix = "jt4";
                if (StringUtils.isNotBlank(sjTag1)) {
                    prefix = sjTag1 + "Jt4";
                }

                suffix = "";
                BigDecimal sl1 = jtmx4.getSl();
                zsl = zsl.add(sl1);
                map.put(String.format("%s%s%s", prefix, "sl", suffix), sl1);
                map.put(String.format("%s%s%s", prefix, "sj", suffix), jtmx4.getSj());
                BigDecimal sf = jtmx4.getSf();
                zsf = zsf.add(sf);
                map.put(String.format("%s%s%s", prefix, "sf", suffix), sf);
            }

            prefix = "";
            suffix = sjTag2;
            map.put(String.format("%s%s%s", prefix, "sl", suffix), zsl);
            map.put(String.format("%s%s%s", prefix, "sf", suffix), zsf);
        }

        //其它费用计算
        BmSj bmSj = sjCache.get(sjbm);
        if (ObjectUtil.isNotNull(bmSj)) {
            if (ObjectUtil.isNotNull(bmSj.getJtjslx()) && (bmSj.getJtjslx().equals(JtjslxEnum.YEAR.getValue())
                    || bmSj.getJtjslx().equals(JtjslxEnum.MONTH.getValue()))) {
                map.put("ljsl", ljsl.add(sl));
            }

            prefix = "";
            suffix = sjTag2;
            BigDecimal wsfdj = bmSj.getWsfdj();
            BigDecimal ljfdj = bmSj.getLjfdj();
            BigDecimal szyfdj = bmSj.getSzyfdj();
            BigDecimal ecjyfdj = new BigDecimal("0.1");

            map.put(String.format("%s%s%s", prefix, "wsfdj", suffix), wsfdj);
            map.put(String.format("%s%s%s", prefix, "szysdj", suffix), szyfdj);
            map.put(String.format("%s%s%s", prefix, "ecjyfdj", suffix), ecjyfdj);

            // 二次加压费
            if (cbkxx.getEcjybz() != null && cbkxx.getEcjybz().equals("1")) {
                BigDecimal ecjyf = fyjs(sl, ecjyfdj);
                map.put(String.format("%s%s%s", prefix, "ecjyf", suffix), ecjyf);
            }

//            // 附加费
//            if (cbkxx.getFjf() != null && cbkxx.getFjf().compareTo(BigDecimal.ZERO) > 0) {
//                //附加费只收取一次
//                if (StrUtil.isEmpty(sjTag1) && StrUtil.isEmpty(sjTag2)) {
//                    BigDecimal fjf = cbkxx.getFjf();
//                    map.put(String.format("%s%s%s", prefix, "fjf", suffix), fjf);
//                }
//            }
//
//            // 消防栓费
//            if (cbkxx.getXfsf() != null && BigDecimal.valueOf(cbkxx.getXfsf()).compareTo(BigDecimal.ZERO) > 0) {
//                //消防栓费只收取一次
//                if (StrUtil.isEmpty(sjTag1) && StrUtil.isEmpty(sjTag2)) {
//                    BigDecimal xfsf = BigDecimal.valueOf(cbkxx.getXfsf());
//                    map.put(String.format("%s%s%s", prefix, "xfsf", suffix), xfsf);
//                }
//            }

            // 污水费
            if ("1".equals(wsfbz)) {
                BigDecimal wsf = fyjs(sl, wsfdj);
                map.put(String.format("%s%s%s", prefix, "wsf", suffix), wsf);
            }

            // 垃圾费
            if ("1".equals(ljfbz) && sl.compareTo(BigDecimal.ZERO) > 0) {
                //按量收取垃圾费
                if (cbkxx.getLjffs().equals("1")) {
                    map.put(String.format("%s%s%s", prefix, "ljfdj", suffix), ljfdj);
                    BigDecimal ljf = fyjs(sl, ljfdj);
                    map.put(String.format("%s%s%s", prefix, "ljf", suffix), ljf);
                } else {
                    Integer num = 1;
                    //判断总分表或子母表是否存在
                    Integer fbsjtj = cblrService.fbsjtj(yhxx.getYhbh(), cbkxx.getCbkh());
                    num = fbsjtj == 0 ? 1 : fbsjtj;

                    //按户收取垃圾费是只需要算一次
                    if (StrUtil.isEmpty(sjTag1) && StrUtil.isEmpty(sjTag2)) {
                        map.put(String.format("%s%s%s", prefix, "ljfdj", suffix), cbkxx.getLjfje());
                        BigDecimal ljf = cbkxx.getLjfje().multiply(new BigDecimal(num));
                        map.put(String.format("%s%s%s", prefix, "ljf", suffix), ljf);
                    }
                }
            }

            // 水资源费
            if (szyfdj != null && szyfdj.compareTo(BigDecimal.ZERO) > 0) {
                map.put(String.format("%s%s%s", prefix, "szyfdj", suffix), szyfdj);
                BigDecimal szyf = fyjs(sl, szyfdj);
                map.put(String.format("%s%s%s", prefix, "szyf", suffix), szyf);
            }
        }

        return map;
    }

    private Sjmx sfjs(BigDecimal sl, String sjbm, BigDecimal ljsl, YhKhjbxx yhKhjbxx) {
        BmSj bmSj = sjCache.get(sjbm);
        if (ObjectUtil.isNull(bmSj)) {
            throw new BusinessException("水价编码不存在");
        }

        String jtbz = bmSj.getJtbz();

        if ("1".equals(jtbz)) {
            Long rks = yhKhjbxx.getRks();
            BigDecimal rksqs = BigDecimal.ZERO;//人口数起数
            BigDecimal jtzl = BigDecimal.ZERO;//阶梯增量
            BigDecimal jtZszl = BigDecimal.ZERO;//阶梯止数增量

            BmSj sjdata = bmSjService.getById(sjbm);
            rksqs = sjdata.getJtrkjs();
            jtzl = sjdata.getJtrksl();

            if (rks != null && rks > 0) {
                if (BigDecimal.valueOf(rks).compareTo(rksqs) > 0) {
                    jtZszl = BigDecimal.valueOf(rks).subtract(rksqs).multiply(jtzl);
                }
            }
            Sjmx.Jtmx jtmx1 = null;
            Sjmx.Jtmx jtmx2 = null;
            Sjmx.Jtmx jtmx3 = null;
            Sjmx.Jtmx jtmx4 = null;
            BigDecimal yssl = BigDecimal.ZERO;
            BigDecimal yssf = BigDecimal.ZERO;

            BigDecimal jt1Zs = bmSj.getJt1Zs();
            BigDecimal jt1Sj = bmSj.getJt1Sj();
            BigDecimal sjJtZs = BigDecimal.ZERO;
            if (isEnabled(jt1Zs)) {
                jtmx1 = getJtSf(sl, jt1Zs.add(jtZszl), jt1Sj, sjJtZs, ljsl);
                sjJtZs = jt1Zs;
                yssl = yssl.add(jtmx1.getSl());
                yssf = yssf.add(jtmx1.getSf());
            }

            BigDecimal jt2Zs = bmSj.getJt2Zs();
            BigDecimal jt2Sj = bmSj.getJt2Sj();
            if (isEnabled(jt2Zs) && isEnabled(jt1Zs)) {
                jtmx2 = getJtSf(sl, jt2Zs.add(jtZszl), jt2Sj, sjJtZs.add(jtZszl), ljsl);
                sjJtZs = jt2Zs;
                yssl = yssl.add(jtmx2.getSl());
                yssf = yssf.add(jtmx2.getSf());
            }

            BigDecimal jt3Zs = bmSj.getJt3Zs();
            BigDecimal jt3Sj = bmSj.getJt3Sj();
            if (isEnabled(jt3Zs) && isEnabled(jt2Zs)) {
                jtmx3 = getJtSf(sl, jt3Zs.add(jtZszl), jt3Sj, sjJtZs.add(jtZszl), ljsl);
                sjJtZs = jt3Zs;
                yssl = yssl.add(jtmx3.getSl());
                yssf = yssf.add(jtmx3.getSf());
            }

            BigDecimal jt4Zs = bmSj.getJt4Zs();
            BigDecimal jt4Sj = bmSj.getJt4Sj();
            if (isEnabled(jt4Zs) && isEnabled(jt3Zs)) {
                jtmx4 = getJtSf(sl, jt4Zs.add(jtZszl), jt4Sj, sjJtZs.add(jtZszl), ljsl);
                //sjJtZs = jt4Zs;
                yssl = yssl.add(jtmx4.getSl());
                yssf = yssf.add(jtmx4.getSf());
            }

            if (ljsl.add(sl).compareTo(sjJtZs) > 0) {
                throw new BusinessException("用户水量超过" + sjJtZs + ",无法计算");
            }

            return new Sjmx(jtmx1, jtmx2, jtmx3, jtmx4, yssl, yssf);
        } else {
            BigDecimal sj = bmSj.getSj();
            // 水费计算
            BigDecimal sf = fyjs(sl, sj);
            return new Sjmx(sj, sl, sf);
        }
    }

    private CbjsfsEnum getCbjsfs(TreeMap<String, String> slMap, Map<String, Object> values) {
        CbjsfsEnum cbjsfs = CbjsfsEnum.ZCDJJF;

        if (slMap.containsKey("L0")) {
            String sjjtbz = (String) values.get("sjjtbz");
            if (sjjtbz.equals("0")) {
                cbjsfs = CbjsfsEnum.ZCDJJF;
            } else {
                cbjsfs = CbjsfsEnum.JTJF;
            }
        } else if (slMap.containsKey("L1")) {
            cbjsfs = CbjsfsEnum.YBDJJF;
            for (long i = 0; i <= 2; i++) {
                String Tag = "sjjtbz";
                if (i != 0) {
                    Tag = String.format("sjjtbz%s", i);
                }
                if (values.containsKey(Tag)) {
                    String sjjtbz = (String) values.get(Tag);
                    if (sjjtbz.equals("0")) {
                        cbjsfs = CbjsfsEnum.YBDJJF;
                    } else {
                        cbjsfs = CbjsfsEnum.JTYBDJJF;
                    }
                }
            }
        }
        return cbjsfs;
    }

    /**
     * 阶梯用水量更新
     */
    private void jtyslgx(SfJsJg sfJsJg, YhCbkxx cbkxx, YhKhjbxx yhKhjbxx) {
        if (sfJsJg.getJtzqljl().compareTo(BigDecimal.ZERO) > 0) {
            cbkxxService.updateLjsl(cbkxx.getCbkid(), sfJsJg.getJtzqljl());
            khjbxxService.lambdaUpdate().set(YhKhjbxx::getJtzqljl, sfJsJg.getJtzqljl()).eq(YhKhjbxx::getYhbh, yhKhjbxx.getYhbh()).update();
        }
        if (sfJsJg.getYhsl().compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal dbhndljl = sfJsJg.getYhsl().add(yhKhjbxx.getDbhndljl());
            khjbxxService.lambdaUpdate().set(YhKhjbxx::getDbhndljl, dbhndljl).eq(YhKhjbxx::getYhbh, yhKhjbxx.getYhbh()).update();
        }
    }

    private BigDecimal fyjs(BigDecimal sl, BigDecimal sj) {
        if (sj != null) {
            return sl.multiply(sj);
        }

        return BigDecimal.ZERO;
    }

    private boolean isEnabled(BigDecimal jtZs) {
        return jtZs != null && jtZs.compareTo(BigDecimal.ZERO) > 0;
    }

    private Sjmx.Jtmx getJtSf(BigDecimal sl, BigDecimal jtZs, BigDecimal jtSj, BigDecimal sjJtZs, BigDecimal ljsl) {
        //累计水量小于阶梯止数 并且 累计水量+本次水量大于上一阶梯止数
        if (ljsl.compareTo(jtZs) < 0 && ljsl.add(sl).compareTo(sjJtZs) > 0) {
            BigDecimal jtSf;//阶梯水费
            BigDecimal ys = jtZs.subtract(ljsl.add(sl));//求阶梯余数
            BigDecimal jtsl;
            if (ys.compareTo(BigDecimal.ZERO) >= 0) {//阶梯余数大于0则没有超过阶梯止数
                if (ljsl.compareTo(sjJtZs) >= 0) {//累计水量大于上一阶梯止数则无需排除上一阶梯水量直接用sl
                    jtsl = sl;
                } else {//累计水量小于上一阶梯止数则需要排除上一阶梯的sl
                    jtsl = sl.subtract(sjJtZs).add(ljsl);
                }
            } else {//阶梯余数小于0则超过阶梯止数 需要求阶梯剩余水量
                if (ljsl.add(sl).compareTo(jtZs) > 0) {//累计水量加水量大于阶梯止数则直接求阶梯剩余水量
                    if (ljsl.compareTo(sjJtZs) > 0) {//累计水量大于上一阶梯止数则表示当前阶梯有累计水量
                        jtsl = jtZs.subtract(ljsl);
                    } else {
                        jtsl = jtZs.subtract(sjJtZs);
                    }
                } else {//累计水量小于上一阶梯止数则需要sl加上ljsl再减去上一阶梯止数求当前阶梯水量
                    jtsl = sl.subtract(sjJtZs).add(ljsl);
                }
            }
            jtSf = fyjs(jtsl, jtSj);
            return new Sjmx.Jtmx(jtSj, jtsl, jtSf);
        }
        return new Sjmx.Jtmx(jtSj, BigDecimal.ZERO, BigDecimal.ZERO);
    }

}
