package com.tofly.xrtygis.custom.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.common.core.util.Date8Util;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.core.util.JSONUtil;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.xrtygis.custom.entity.dma.ConstomAddPipe;
import com.tofly.xrtygis.custom.entity.dma.ConstomCondition;
import com.tofly.xrtygis.custom.entity.dma.CustomPartition;
import com.tofly.xrtygis.custom.entity.enums.Calculate;
import com.tofly.xrtygis.custom.entity.enums.CompanyName;
import com.tofly.xrtygis.custom.service.CustomAreaService;
import com.tofly.xrtygis.custom.service.GetMaxIdService;
import com.tofly.xrtygis.custom.util.DateTimeUtil;
import com.tofly.xrtygis.em.Constant;
import com.tofly.xrtygis.em.ExcelExportFileTypeEnum;
import com.tofly.xrtygis.entity.*;
import com.tofly.xrtygis.entity.vo.DmaCalculatePramVo;
import com.tofly.xrtygis.service.*;
import com.tofly.xrtygis.strategy.ExcelStrategyContext;
import com.tofly.xrtygis.util.ExcelUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author FlashWJL
 * @date 2021/3/29 15:27
 */
@Service

public class CustomAreaServiceImpl implements CustomAreaService {
    @Autowired
    private  DmaregionService regionService;
    @Autowired
    private  DmaandobserService dmaandobserService;
    @Autowired
    private  DmaregionupipeService pipeService;
    @Autowired
    private  GetMaxIdService maxIdService;
    @Autowired
    private  DmaicfService dmaicfService;
    @Autowired
    private  DmatableService dmatableService;
    @Autowired
    private  ExcelStrategyContext excelStrategyContext;
    @Autowired
    private  DmausercbbService dmausercbbService;
    @Autowired
    private  DmaandcbbService dmaandcbbService;
    @Autowired
    private  DmaregionService dmaregionService;
    @Autowired
    private  DmausertableService dmausertableService;
    @Autowired
    private  DmapietypeService dmapietypeService;
    @Autowired
    private  DmaDeviceAssociationService dmaDeviceAssociationService;
    @Autowired
    private  TfDeviceArchiveManageService tfDeviceArchiveManageService;
    @Autowired
    private final static Integer MAX_NUM = 99;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${xrty.ftp.topCompanyName}")
    private String topCompanyName;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addPartition(String info) {
        List<CustomPartition> partition = JSONObject.parseArray(info, CustomPartition.class);
        CustomPartition partitionList = partition.get(0);

        //字符串转管线实体类bean
        List<Dmaregionupipe> pipeList = JSONObject.parseArray(partitionList.getPipeline(), Dmaregionupipe.class);
        //判断有没有传ID，没有传主键ID则是保存
        if (StringUtil.isNull(partitionList.getId())) {
            if (StringUtil.isNull(partitionList.getMaxDiff()) && StringUtil.isNull(partitionList.getMinDiff())) {
                throw new ToflyDeniedException("请输入最大或最小分区分差");
            }
            if (partitionList.getMaxDiff() > 100 || partitionList.getMaxDiff() < 0 || partitionList.getMinDiff() > 100 || partitionList.getMinDiff() < 0) {
                throw new ToflyDeniedException("最大、最小分区分差范围在0-100");
            }
            if (StringUtil.isEmpty(partitionList.getDmaName())) {
                throw new ToflyDeniedException("DMA分区名称必填");
            }
            //默认设置为第一级别
            partitionList.setPartitionLevel(1);
            //判断有没有父级，如果没有，则属于第一级别的分区
            if (StringUtil.isNotNull(partitionList.getPid())) {
                //如果父级ID为0
                if (partitionList.getPid().equals(0L)) {
                    //设置为父级的下一个级别
                    partitionList.setPartitionLevel(1);
                } else {
                    //如果有父级，则应该先查询父级属于第几级别，然后对应的加一个级别
                    Integer level = regionService.getOne(Wrappers.<Dmaregion>lambdaQuery()
                            .eq(Dmaregion::getId, partitionList.getPid()).select(Dmaregion::getPartitionLevel)).getPartitionLevel();
                    //设置为父级的下一个级别
                    partitionList.setPartitionLevel(level + 1);
                }
            } else {
                partitionList.setPid(0L);
            }
            Integer partitionLevel = partitionList.getPartitionLevel();
            partitionList.setDmaCode(createCode(partitionLevel));
            String guid = regionService.getGuid();
            partitionList.setDmaGid(guid);
            partitionList.setCreateTime(new Date());
            partitionList.setCreateUser(SecurityUtils.getUserId());
            //保存分区
            regionService.save(partitionList);
            //得到分区保存的ID
            Long parId = partitionList.getId();
            //得到管线情况信息表最大ID
//            Long pipeId = maxIdService.getMaxId("TF_YWPN_DMAREGIONUPIPE_W");
            //判断管线是否有
            if (StringUtil.isNotNull(pipeList) && pipeList.size() > 0) {
                //管线存在几种不同的管材
                for (int i = 0; i < pipeList.size(); i++) {
                    pipeList.get(i).setDmaId(parId);
//                    pipeList.get(i).setId(pipeId + i);
                }
                //保存管线材质信息，并得到夜间最小流量
                for (Dmaregionupipe one : pipeList) {
//                    Page<Dmaregionupipe> dmaregionupipePage = pipeService.page(new Page<>(1,1),new QueryWrapper<Dmaregionupipe>().orderByDesc("ID"));
//                    List<Dmaregionupipe> dmaregionupipeList = dmaregionupipePage.getRecords();
//                    if(dmaregionupipeList == null || dmaregionupipeList.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(dmaregionupipeList.get(0).getId() + 1);
//                    }
                    pipeService.save(one);
                }
//                pipeService.saveBatch(pipeList);

                BigDecimal minFlow = anewICF(partitionList, pipeList.size());
                if (StringUtil.isNotNull(minFlow)) {
                    regionService.update(Wrappers.<Dmaregion>lambdaUpdate().eq(Dmaregion::getId, parId)
                            .set(Dmaregion::getRefStandard, minFlow));
                }
            }
            // 设备新增绑定
            List<Long> deviceIdList = partitionList.getDeviceIdList();
            if (null != deviceIdList && deviceIdList.size() > 0) {
                List<DmaDeviceAssociation> dmaDeviceAssociationList = new ArrayList<>();
                deviceIdList.forEach(deviceId -> {
                    DmaDeviceAssociation deviceAssociation = new DmaDeviceAssociation();
                    deviceAssociation.setDmaId(parId);
                    deviceAssociation.setDeviceId(deviceId);
                    dmaDeviceAssociationList.add(deviceAssociation);
                });
                for (DmaDeviceAssociation one : dmaDeviceAssociationList) {
//                    Page<DmaDeviceAssociation> dmaDeviceAssociationPage = dmaDeviceAssociationService.page(new Page<>(1,1),new QueryWrapper<DmaDeviceAssociation>().orderByDesc("ID"));
//                    List<DmaDeviceAssociation> dmaDeviceAssociationListQ = dmaDeviceAssociationPage.getRecords();
//                    if(dmaDeviceAssociationListQ == null || dmaDeviceAssociationListQ.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(dmaDeviceAssociationListQ.get(0).getId() + 1);
//                    }
                    dmaDeviceAssociationService.save(one);
                }
//                dmaDeviceAssociationService.saveBatch(dmaDeviceAssociationList);
            }
            // 区域计量表中间表绑定
            List<Dmaandobser> dmaandobserList = partitionList.getDmaandobserList();
            if (null != dmaandobserList && dmaandobserList.size() > 0) {
                dmaandobserList.forEach(dmaandobser -> dmaandobser.setDmaId(parId));
                for (Dmaandobser one : dmaandobserList) {
//                    Page<Dmaandobser> dmaandobserPage = dmaandobserService.page(new Page<>(1,1),new QueryWrapper<Dmaandobser>().orderByDesc("ID"));
//                    List<Dmaandobser> dmaandobserListQ = dmaandobserPage.getRecords();
//                    if(dmaandobserListQ == null || dmaandobserListQ.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(dmaandobserListQ.get(0).getId() + 1);
//                    }
                    dmaandobserService.save(one);
                }
//                dmaandobserService.saveBatch(dmaandobserList);
            }
            return parId;
        } else {
            //修改
            Long parId = partitionList.getId();
            String parName = partitionList.getDmaName();
            Long fjPartition = partitionList.getPid();
            Double area = partitionList.getAreas();
            Float min = partitionList.getMinDiff();
            Float max = partitionList.getMaxDiff();
            String note = partitionList.getNotes();
            String geometry = partitionList.getGeometry();
            Double pipeLen = partitionList.getPipeLen();
            String isyc = partitionList.getIsyc();
            String dmaCode = partitionList.getDmaCode();
            //先删除再添加
            pipeService.remove(Wrappers.<Dmaregionupipe>lambdaQuery().eq(Dmaregionupipe::getDmaId, parId));
            BigDecimal minFlow = BigDecimal.ZERO;
            // 陈浩 修改不为空判断
            if (StringUtil.isNotNull(pipeList) && pipeList.size() > 0) {
                //管线存在几种不同的管材
                for (Dmaregionupipe dmaregionupipe : pipeList) {
                    dmaregionupipe.setDmaId(parId);
                }
                for (Dmaregionupipe one : pipeList) {
//                    Page<Dmaregionupipe> page = pipeService.page(new Page<>(1,1),new QueryWrapper<Dmaregionupipe>().orderByDesc("ID"));
//                    List<Dmaregionupipe> list = page.getRecords();
//                    if(list == null || list.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(list.get(0).getId() + 1);
//                    }
                    pipeService.save(one);
                }
//                pipeService.saveBatch(pipeList);
                //查询属于这个分区的管线管材信息
                List<Dmaregionupipe> dmaregionupipeList = pipeService.list(Wrappers.<Dmaregionupipe>lambdaQuery().eq(Dmaregionupipe::getDmaId, parId));
                //重新计算更新管线管材后的渗透值
                minFlow = anewICF(partitionList, dmaregionupipeList.size());
            }
            //如果修改父级ID，则需要重新计算分区等级
            Integer level = null;
            if (StringUtil.isNotNull(fjPartition)) {
                if (fjPartition.equals(0L)) {
                    //如果是顶级父ID，则设置为1级
                    level = 1;
                } else {
                    //如果有父级，则应该先查询父级属于第几级别，然后对应的加一个级别
                    level = regionService.getOne(Wrappers.<Dmaregion>lambdaQuery()
                            .eq(Dmaregion::getId, fjPartition).select(Dmaregion::getPartitionLevel)).getPartitionLevel() + 1;
                }
            }
            // 设备新增绑定
            List<Long> deviceIdList = partitionList.getDeviceIdList();
            dmaDeviceAssociationService.remove(new QueryWrapper<DmaDeviceAssociation>().lambda().eq(DmaDeviceAssociation::getDmaId, parId));
            if (null != deviceIdList && deviceIdList.size() > 0) {

                List<DmaDeviceAssociation> dmaDeviceAssociationList = new ArrayList<>();
                deviceIdList.forEach(deviceId -> {
                    DmaDeviceAssociation deviceAssociation = new DmaDeviceAssociation();
                    deviceAssociation.setDmaId(parId);
                    deviceAssociation.setDeviceId(deviceId);
                    dmaDeviceAssociationList.add(deviceAssociation);
                });
                for (DmaDeviceAssociation one : dmaDeviceAssociationList) {
//                    Page<DmaDeviceAssociation> page = dmaDeviceAssociationService.page(new Page<>(1,1),new QueryWrapper<DmaDeviceAssociation>().orderByDesc("ID"));
//                    List<DmaDeviceAssociation> list = page.getRecords();
//                    if(list == null || list.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(list.get(0).getId() + 1);
//                    }
                    dmaDeviceAssociationService.save(one);
                }
//                dmaDeviceAssociationService.saveBatch(dmaDeviceAssociationList);

            }
            // 区域计量表中间表绑定
            List<Dmaandobser> dmaandobserList = partitionList.getDmaandobserList();
            dmaandobserService.remove(new QueryWrapper<Dmaandobser>().lambda().eq(Dmaandobser::getDmaId, parId));
            if (null != dmaandobserList && dmaandobserList.size() > 0) {
                dmaandobserList.forEach(dmaandobser -> dmaandobser.setDmaId(parId));
                for (Dmaandobser one : dmaandobserList) {
//                    Page<Dmaandobser> page = dmaandobserService.page(new Page<>(1,1),new QueryWrapper<Dmaandobser>().orderByDesc("ID"));
//                    List<Dmaandobser> list = page.getRecords();
//                    if(list == null || list.size() == 0){
//                        one.setId(1L);
//                    }else {
//                        one.setId(list.get(0).getId() + 1);
//                    }
                    dmaandobserService.save(one);
                }
//                dmaandobserService.saveBatch(dmaandobserList);

            }
            //需要重新计算渗透量值再set，所以放在最后
            regionService.update(Wrappers.<Dmaregion>lambdaUpdate().eq(StringUtil.isNotNull(parId), Dmaregion::getId, parId)
                    .set(StringUtil.isNotEmpty(parName), Dmaregion::getDmaName, parName)
                    .set(StringUtil.isNotEmpty(note), Dmaregion::getNotes, note)
                    .set(StringUtil.isNotNull(fjPartition), Dmaregion::getPid, fjPartition)
                    .set(StringUtil.isNotNull(area), Dmaregion::getAreas, area)
                    .set(StringUtil.isNotNull(min), Dmaregion::getMinDiff, min)
                    .set(StringUtil.isNotNull(max), Dmaregion::getMaxDiff, max)
                    .set(StringUtil.isNotNull(pipeLen), Dmaregion::getPipeLen, pipeLen)
                    .set(StringUtil.isNotNull(isyc), Dmaregion::getIsyc, isyc)
                    .set(StringUtil.isNotEmpty(geometry), Dmaregion::getGeometry, geometry)
                    .set(StringUtil.isNotNull(minFlow), Dmaregion::getRefStandard, minFlow)
                    .set(StringUtil.isNotNull(level), Dmaregion::getPartitionLevel, level)
                    .set(StringUtil.isNotNull(dmaCode), Dmaregion::getDmaCode, dmaCode));
            return parId;
        }
    }


    @Override
    public List<Dmatable> tableCoord() {
        List<Dmatable> list = dmatableService.list(new QueryWrapper<Dmatable>().lambda().eq(Dmatable::getUsfl, 1));
        return list;
    }

    @Override
    public Map getDetailById(Long id) {
        //分区本身信息
        Dmaregion dmaregion = regionService.getOne(Wrappers.<Dmaregion>lambdaQuery().eq(Dmaregion::getId, id));
        if (dmaregion.getPid().equals(0L)) {
            dmaregion.setPName(topCompanyName);
        }
        //分区里面的管线管材信息
        List<Dmaregionupipe> pipeList = pipeService.list(Wrappers.<Dmaregionupipe>lambdaQuery().eq(Dmaregionupipe::getDmaId, id).orderByAsc(Dmaregionupipe::getCreateTime));
        //分区绑定的区域表
        List<Dmatable> dmatableList = new ArrayList<>();
        List<Dmaandobser> dmaandobserList = dmaandobserService.list(Wrappers.<Dmaandobser>lambdaQuery().eq(Dmaandobser::getDmaId, id));
        if (StringUtil.isNotNull(dmaandobserList) && dmaandobserList.size() > 0) {
            List<Long> tableIdList = dmaandobserList.stream().map(Dmaandobser::getTableId).collect(Collectors.toList());
            dmatableList = dmatableService.list(Wrappers.<Dmatable>lambdaQuery().in(Dmatable::getId, tableIdList));
        }
        //分区绑定的设备信息
        List<TfDeviceArchiveManage> deviceArchiveManageList = new ArrayList<>();
        List<DmaDeviceAssociation> dmaDeviceAssociationList = dmaDeviceAssociationService.list(new QueryWrapper<DmaDeviceAssociation>().lambda().eq(DmaDeviceAssociation::getDmaId, id));
        if (null != dmaDeviceAssociationList && dmaDeviceAssociationList.size() > 0) {
            List<Long> deviceIdList = dmaDeviceAssociationList.stream().map(DmaDeviceAssociation::getDeviceId).collect(Collectors.toList());
            deviceArchiveManageList = tfDeviceArchiveManageService.list(new QueryWrapper<TfDeviceArchiveManage>().lambda().in(TfDeviceArchiveManage::getId, deviceIdList));

        }
        Map map = new HashMap();
        map.put("dmaregion", dmaregion);
        map.put("pipeList", pipeList);
        map.put("dmatableList", dmatableList);
        map.put("dmaandobserList", dmaandobserList);
        map.put("deviceArchiveManageList", deviceArchiveManageList);
        return map;
    }

    @Override
    public Map getBingCbb(Long dmaId) {
        //所有的抄表本信息
        List<Dmausercbb> dmausercbbList = dmausercbbService.list(Wrappers.<Dmausercbb>lambdaQuery()
                .eq(Dmausercbb::getYxbz, "1").select(Dmausercbb::getCbbbm, Dmausercbb::getCbbmc));
        //获取该片区绑定的抄表本信息
        List<Dmaandcbb> dmaandcbbList = dmaandcbbService.list(Wrappers.<Dmaandcbb>lambdaQuery()
                .eq(Dmaandcbb::getDmaId, dmaId).select(Dmaandcbb::getCbbbm));
        List<Dmausercbb> noBing = new ArrayList<>();
        List<Dmausercbb> bing = new ArrayList<>();
        //如果有绑定数据
        if (StringUtil.isNotNull(dmaandcbbList) && dmaandcbbList.size() > 0) {
            //绑定了的抄表本编码
            Map<String, String> cbbBmBing = dmaandcbbList.stream().collect(Collectors.toMap(Dmaandcbb::getCbbbm, Dmaandcbb::getCbbbm));
            //过滤数据 , 这里有两层for循环了，建议后面改成SQL
            for (Dmausercbb k : dmausercbbList) {
                if (cbbBmBing.containsKey(k.getCbbbm())) {
                    bing.add(k);
                } else {
                    noBing.add(k);
                }
            }
        }//没有绑定数据
        else {
            noBing = dmausercbbList;
        }
        Map<String, List<Dmausercbb>> map = new HashMap<>();
        map.put("bing", bing);
        map.put("nobing", noBing);
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bingCbb(Long dmaId, String cbbList) {

        if (dmaId.equals(0L)) {
            throw new ToflyDeniedException("顶级分区不能绑定");
        }

        //先删除抄表本中该DMA分区的绑定信息
        dmaandcbbService.remove(Wrappers.<Dmaandcbb>lambdaQuery().eq(Dmaandcbb::getDmaId, dmaId));
        if (StringUtil.isEmpty(cbbList)) {
            return true;
        }
        List<String> cbbBmList = Arrays.asList(cbbList.split(","));
        List<Dmaandcbb> dmaandcbbList = new ArrayList<>();
        cbbBmList.forEach(k -> {
            Dmaandcbb dmaandcbb = new Dmaandcbb();
            //UUID
            UUID uuid = UUID.randomUUID();
            dmaandcbb.setId(uuid.toString().replace("-", ""));
            dmaandcbb.setCbbbm(k);
            dmaandcbb.setDmaId(dmaId);
            dmaandcbbList.add(dmaandcbb);
        });
        dmaandcbbService.insertBatch(dmaandcbbList);
        return true;
    }

    /**
     * 获取片区同级信息
     *
     * @param level 等级
     * @return list
     */
    @Override
    public List<Dmaregion> areaLevelInfo(String level) {
        return dmaregionService.list(Wrappers.<Dmaregion>lambdaQuery()
                .eq(Dmaregion::getPartitionLevel, level)
                .select(Dmaregion::getId, Dmaregion::getDmaName, Dmaregion::getGeometry));
    }

    @Override
    public Page<Dmaregion> getReginPage(Page page, Integer level) {
        return dmaregionService.page(page, Wrappers.<Dmaregion>lambdaQuery()
                .eq(Dmaregion::getPartitionLevel, level)
                .select(Dmaregion::getId, Dmaregion::getDmaName, Dmaregion::getGeometry));
    }

    @Override
    public BigDecimal getYearPressure(String year, List<Long> deviceIdList) {

        return dmaregionService.getYearPressure(year, deviceIdList);
    }


    /**
     * 删除或新增、修改管线材质后，计算渗透值
     *
     * @param partition DMA分区基础信息
     * @param pipeSize  管线数量
     * @return
     */
    public BigDecimal anewICF(CustomPartition partition, Integer pipeSize) {
        BigDecimal result = BigDecimal.ZERO;
        BigDecimal pipeLen = BigDecimal.valueOf(partition.getPipeLen());
        String algorithmType = partition.getAlgorithmType();
        if (StringUtil.isEmpty(algorithmType) || "0".equals(algorithmType)) {
            //QB——背景漏失水量（万m3）；
            //Qn——单位管长夜间最小流量[m3／（km·h）]，在DMA样本区域开展检漏后测定；
            //L——管网总长度（km）；
            //T——统计时间（h），按1年计算。 24*365
            //QB＝Qn·L·T／10000
            double minFlowPipe = partition.getMinFlowPipe() == null ? 0L : partition.getMinFlowPipe();
            result = BigDecimal.valueOf(minFlowPipe).multiply(pipeLen).multiply(BigDecimal.valueOf(8760)).divide(BigDecimal.valueOf(10000),2,BigDecimal.ROUND_HALF_UP);
        }else {
            // 参与计算 分区总管长(不为空) 总连接点数 总入户长度 总平均压力 总其他用水 管线类型ICF平均值 管线数量
            BigDecimal pointNumber = partition.getPointNumber() == null ? BigDecimal.ZERO : BigDecimal.valueOf(partition.getPointNumber());
            BigDecimal userPipeLen = partition.getUserPipeLen() == null ? BigDecimal.ZERO : BigDecimal.valueOf(partition.getUserPipeLen());
            BigDecimal avgPressure = partition.getAvgPressure() == null ? BigDecimal.ZERO : BigDecimal.valueOf(partition.getAvgPressure());
            BigDecimal otherWater = partition.getOtherWater() == null ? BigDecimal.ZERO : BigDecimal.valueOf(partition.getOtherWater());
            // 基础渗漏量 会计算不准确  直接取默认 icf值国际标准 1.5
            BigDecimal icf = BigDecimal.valueOf(1.5);
            //基础渗漏量（m3/h）＝{ICF×（0.02×L管+1.25×连接点数） + ICF×0.033×L户×（P均／50）×1.5 + 0.25×连接点数×（P均/50）×1.5+M其它}/1000
            BigDecimal one = icf.multiply(pipeLen.multiply(Calculate.CALCULATE_ONE.getCalcul()).add(Calculate.CALCULATE_TWO.getCalcul().multiply(pointNumber)));
            BigDecimal two = icf.multiply(Calculate.CALCULATE_THREE.getCalcul()).multiply(userPipeLen).multiply(avgPressure.divide(Calculate.CALCULATE_FOUR.getCalcul(), 2, BigDecimal.ROUND_HALF_UP)).multiply(Calculate.CALCULATE_FIVE.getCalcul());
            BigDecimal three = Calculate.CALCULATE_SIX.getCalcul().multiply(pointNumber).multiply(avgPressure.divide(Calculate.CALCULATE_FOUR.getCalcul(), 2, BigDecimal.ROUND_HALF_UP)).multiply(Calculate.CALCULATE_FIVE.getCalcul());
            BigDecimal sum = one.add(two).add(three).add(otherWater);
            result = sum.divide(Calculate.CALCULATE_SEVEN.getCalcul(), 2, BigDecimal.ROUND_HALF_UP);
            //得到夜间最小流量平均值。因为可能存在多个管线不同管材的情况
            result = (result==null?BigDecimal.ZERO:result).divide(new BigDecimal(pipeSize), 2, BigDecimal.ROUND_HALF_UP);
        }


        return result;

    }


    /**
     * 计算渗透量值公共方法
     *
     * @param dmaregionupipe 管线信息
     * @param dmaicfList     ICF信息
     * @return
     */
    public BigDecimal calculateICF(Dmaregionupipe dmaregionupipe, List<Dmaicf> dmaicfList) {
        //计算不同管线材质的最小夜间流量
        Long material = dmaregionupipe.getMaterial();
        //计算时间年限 格式如：2020
        Integer year = dmaregionupipe.getFixYear();
        //获取当前日期
        Integer current = Integer.parseInt(DateUtil.parseDateToStr("yyyy", Date8Util.getCurrentDate()));
        //时间相减
        Integer diffYear = current - year;
        //L管；分区内管长
        BigDecimal Lg = new BigDecimal(dmaregionupipe.getPipeLen());
        //连接点数
        BigDecimal num = new BigDecimal(dmaregionupipe.getPointNumber());
        //L户；各分户表到用户用水处管道累计总长度
        BigDecimal Lh = new BigDecimal(dmaregionupipe.getUserPipeLen());
        //P均；区域内平均压力
        BigDecimal Pj = new BigDecimal(dmaregionupipe.getAvgPressure());
        //M其他；其它可量化用水
        BigDecimal Mqt = new BigDecimal(dmaregionupipe.getOtherWater());
        //ICF值 默认为 1
        BigDecimal icf = new BigDecimal(1);
        //筛选过滤得到满足条件的状况因子；这里的过滤，我感觉用查询数据库得到结果的方式更加便捷，这里的比较不怎么对
        List<Dmaicf> dmaicfs = dmaicfList.stream().filter(m -> m.getMid().equals(material)).collect(Collectors.toList());
        //根据年限取icf，这里循环最多只有四次
        for (Dmaicf k : dmaicfs) {
            String icfByYear = dmaicfService.getIcfByYear(k.getMid(), k.getBsign(), k.getEsign(), diffYear);
            if (StringUtil.isNotEmpty(icfByYear)) {
                icf = new BigDecimal(icfByYear);
                break;
            }
        }
        //基础渗漏量（m3/h）＝{ICF×（0.02×L管+1.25×连接点数） + ICF×0.033×L户×（P均／50）×1.5 + 0.25×连接点数×（P均/50）×1.5+M其它}/1000
        BigDecimal one = icf.multiply(Lg.multiply(Calculate.CALCULATE_ONE.getCalcul()).add(Calculate.CALCULATE_TWO.getCalcul().multiply(num)));//ICF×（0.02×L管+1.25×连接点数）
        BigDecimal two = icf.multiply(Calculate.CALCULATE_THREE.getCalcul()).multiply(Lh).multiply(Pj.divide(Calculate.CALCULATE_FOUR.getCalcul(), 2, BigDecimal.ROUND_HALF_UP)).multiply(Calculate.CALCULATE_FIVE.getCalcul());//ICF×0.033×L户×（P均／50）×1.5
        BigDecimal three = Calculate.CALCULATE_SIX.getCalcul().multiply(num).multiply(Pj.divide(Calculate.CALCULATE_FOUR.getCalcul(), 2, BigDecimal.ROUND_HALF_UP)).multiply(Calculate.CALCULATE_FIVE.getCalcul());//0.25×连接点数×（P均/50）×1.5
        BigDecimal sum = one.add(two).add(three).add(Mqt);
        BigDecimal result = sum.divide(Calculate.CALCULATE_SEVEN.getCalcul(), 2, BigDecimal.ROUND_HALF_UP);//除以1000；得到基础渗透量
        return result;
    }


    @Override
    public List<CustomPartition> getPartition(String partitionName, Long partitionId, Page page) {
        if (StringUtil.isNotEmpty(partitionName) || StringUtil.isNotNull(partitionId)) {
            //根据条件查询分区
            Page<Dmaregion> regionPage = regionService.page(page, Wrappers.<Dmaregion>lambdaQuery()
                    .like(StringUtil.isNotEmpty(partitionName), Dmaregion::getDmaName, partitionName)
                    .eq(StringUtil.isNotNull(partitionId), Dmaregion::getPid, partitionId));
            List<CustomPartition> customPartitionList = JSONObject.parseArray(JSONObject.toJSONString(regionPage.getRecords()), CustomPartition.class);
            if(customPartitionList == null){
                return null;
            }
            for(CustomPartition customPartition : customPartitionList){
                List<Dmaandobser> dmaandobserList = dmaandobserService.list(Wrappers.<Dmaandobser>lambdaQuery().eq(Dmaandobser::getDmaId, customPartition.getId()));
                customPartition.setDmaandobserList(dmaandobserList);
            }
            return JSONObject.parseArray(JSONObject.toJSONString(regionPage.getRecords()), CustomPartition.class).stream().sorted(Comparator.comparing(CustomPartition::getPartitionLevel)).sorted(Comparator.comparing(CustomPartition::getDmaCode)).collect(Collectors.toList());
        }
        //查询全部
        List<Dmaregion> dmaregionList = regionService.list().stream().sorted(Comparator.comparing(Dmaregion::getPartitionLevel)).sorted(Comparator.comparing(Dmaregion::getDmaCode)).collect(Collectors.toList());
        Dmaregion dmaregion = new Dmaregion();
        //这里是默认一个顶级公司名；目前写死，后面可以写在配置文件里面
        dmaregion.setDmaName(topCompanyName);
        dmaregion.setId(0L);
        dmaregion.setDmaCode("TYSWGS");
        dmaregionList.add(dmaregion);

        //拼接远传表字符串
        dmaregionList.forEach(k -> {
            if ("1".equals(k.getIsyc())) {
                k.setDmaName(k.getDmaName() + "(远传)");
            }
        });
        //集合转json，json再转对应的bean集合
        List<CustomPartition> partitions = JSONObject.parseArray(JSONObject.toJSONString(dmaregionList), CustomPartition.class);
        if(partitions == null){
            return null;
        }
        for(CustomPartition customPartition : partitions){
            List<Dmaandobser> dmaandobserList = dmaandobserService.list(Wrappers.<Dmaandobser>lambdaQuery().eq(Dmaandobser::getDmaId, customPartition.getId()));

            customPartition.setDmaandobserList(dmaandobserList);
        }
        //生成树结构
        return JSONUtil.parTree(partitions, CustomPartition::getId, CustomPartition::getPid, CustomPartition::getPartitionList);
    }

    @Override
    public Map getPartitionById(HttpServletResponse response, Page page, ConstomCondition condition) {
        //分区信息
        //Dmaregion region = regionService.getById(id);
        //由于返回给前端的数据是父级和子级，并且需要分页显示，那么就需要将分页的size数减 1
//        IPage<Dmaregion> reagionPage = regionService.page(page, Wrappers.<Dmaregion>lambdaQuery()
//                .like(StringUtil.isNotEmpty(regionName), Dmaregion::getDmaName, regionName)
//                .eq(Dmaregion::getPid, id).or().eq(Dmaregion::getId, id).like(StringUtil.isNotEmpty(regionName), Dmaregion::getDmaName, regionName));
//        //得到page里面的数据
//        List<Dmaregion> dmaregionList = reagionPage.getRecords();
//        //Java处理父级分区名称有没有模糊搜索的
//        if (dmaregionList.size() == 1) {
//            String dmaName = dmaregionList.get(0).getDmaName();
//            //模糊比较
//            String likeName = ".*" + regionName + ".*";
//            if (StringUtil.isNotEmpty(regionName)) {
//                if (!dmaName.matches(likeName)) {
//                    //如果模糊比较没有相同的字符串，则删除这一条数据
//                    dmaregionList.clear();
//                    reagionPage.setTotal(0);
//                    reagionPage.setRecords(dmaregionList);
//                }
//            }
//        }
//        Map resultMap = new HashMap();
//        resultMap.put("region", reagionPage);
//        return resultMap;

        Long id = condition.getId();
        if (StringUtil.isNull(id)) {
            throw new ToflyDeniedException("请传入分区ID");
        }
        String content = condition.getContent();
        String template = condition.getTemplateFlag();


        if ("1".equals(template)) {
            List<Dmaregion> reagionList = null;
            //如果传入的是顶级ID=0；则需要先查询一级分区的ID，再返回
            if (id.equals(0L)) {
                List<Dmaregion> dmaOneLevel = regionService.list(Wrappers.<Dmaregion>lambdaQuery().eq(Dmaregion::getPid, 0).select(Dmaregion::getId));
                if (StringUtil.isNotNull(dmaOneLevel) && dmaOneLevel.size() > 0) {
                    String ids = dmaOneLevel.stream().map(k -> k.getId().toString()).collect(Collectors.joining(","));
                    reagionList = regionService.getOneLevelByIdsList(ids, content);
                }
            } else {
                reagionList = regionService.getPartitionByIdList(id, content);
            }
            //父级ID为0的情况，则修改父级名称为
            if (reagionList.size() > 0) {
                for (Dmaregion d : reagionList) {
                    if (d.getPid().equals(0L)) {
                        d.setPName(topCompanyName);
                    }
                }
            }
            // 根据templateServiceType,templateFlag获取对应模板数据
            ExcelExportFileTypeEnum excelExportFileTypeEnum = ExcelExportFileTypeEnum.getExcelExportFileTypeEnum("partionServiceImpl", template);
            if (null == excelExportFileTypeEnum) {
                return null;
            }
            //将查询的结果转json字符串的格式，因为导出的时候只能传一个字符串
            String resultListToString = JSONArray.toJSONString(reagionList);
            // 从模型类型枚举根据templateServiceType获取策略对应模板数据
            List<Map<String, Object>> dataList = excelStrategyContext.getExportData("partionServiceImpl", template, resultListToString);
            ExcelUtil.export(dataList.get(0), excelExportFileTypeEnum, Constant.FILE_PATH_TEST_EXPORT_EXCEL, response);
            return null;
        } else {
            IPage<Dmaregion> reagionPage = null;
            //如果传入的是顶级ID=0；则需要先查询一级分区的ID，再返回
            if (id.equals(0L)) {
                List<Dmaregion> dmaOneLevel = regionService.list(Wrappers.<Dmaregion>lambdaQuery().eq(Dmaregion::getPid, 0).select(Dmaregion::getId));
                if (StringUtil.isNotNull(dmaOneLevel) && dmaOneLevel.size() > 0) {
                    String ids = dmaOneLevel.stream().map(k -> k.getId().toString()).collect(Collectors.joining(","));
                    reagionPage = regionService.getOneLevelByIds(page, ids, content);
                }
            } else {
                reagionPage = regionService.getPartitionById(page, id, content);
            }

            List<Dmaregion> reagionList = new ArrayList<>();
            if(reagionPage!=null){
                reagionList = reagionPage.getRecords();
            }

            //父级ID为0的情况，则修改父级名称为 成都兴蓉沱源水务
            if (reagionList.size() > 0) {
                for (Dmaregion d : reagionList) {
                    if (d.getPid().equals(0L)) {
                        d.setPName(topCompanyName);
                    }
                }
            }
            Map resultMap = new HashMap();
            resultMap.put("region", reagionPage);
            return resultMap;
        }
    }

    @Override
    public Map partitionNum() {
        //查询不同分区的个数
        List<Map> mapList = regionService.partitionNum();
        Map result = new HashMap();

        int size = mapList.size();
        //要求等级等你显示三级
        if (size > 3) {
            size = 3;
        }
        for (int i = 0; i < size; i++) {
            result.put(mapList.get(i).get("grade") + "级分区", mapList.get(i).get("num"));
        }
        return result;
    }

    /**
     * 返回所有等级
     * 用于综合展示的
     *
     * @return
     */
    @Override
    public Map partitionNumSynthe() {
        //查询不同分区的个数
        List<Map> mapList = regionService.partitionNum();
        Map result = new HashMap();
        int size = mapList.size();
        for (int i = 0; i < size; i++) {
            result.put(mapList.get(i).get("grade") + "级分区", mapList.get(i).get("num"));
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delPartition(String ids) {
        if (StringUtil.isEmpty(ids)) {
            throw new ToflyDeniedException("请选择分区");
        }

        //将ids字符串转数组，在由数组转集合，然后修改泛型为Long
        List<Long> idList = Arrays.asList(ids.split(",")).stream().map(k -> Long.parseLong(k.trim())).collect(Collectors.toList());
        idList.forEach(k -> {
            if (k.equals(0L)) {
                throw new ToflyDeniedException("不能删除顶级节点分区");
            }
        });
        //判断观察表有没有绑定DMA分区，如果有则不能删除
        List<Dmaandobser> dmaandobserList = dmaandobserService.list(Wrappers.<Dmaandobser>lambdaQuery().in(Dmaandobser::getDmaId, idList).select(Dmaandobser::getDmaId).groupBy(Dmaandobser::getDmaId));
        if (StringUtil.isNotNull(dmaandobserList) && dmaandobserList.size() > 0) {
            //查询分区
            List<Dmaregion> dmaregions = regionService.list(Wrappers.<Dmaregion>lambdaQuery().in(Dmaregion::getId, dmaandobserList.stream().map(Dmaandobser::getDmaId).collect(Collectors.toList())).select(Dmaregion::getDmaName));
            String dmaName = dmaregions.stream().map(Dmaregion::getDmaName).collect(Collectors.joining(","));
            throw new ToflyDeniedException("以下分区不能删除：" + dmaName + "；请重新选择");
        }
        //如果分区绑定了用户，则不能删除
        //查询分区guid与分区名称
        List<Dmaregion> dmaregionList = regionService.list(Wrappers.<Dmaregion>lambdaQuery()
                .in(Dmaregion::getId, idList).select(Dmaregion::getDmaGid, Dmaregion::getDmaName));
//        //查询分区是否有绑定的用户
//        List<Dmausertable> dmausertableList = regionService.getRegionBingClient(dmaregionList);
        //这里只能用for循环了，没法避免了
        StringBuilder isBing = new StringBuilder();
        dmaregionList.forEach(v -> {
            Integer count = dmausertableService.count(Wrappers.<Dmausertable>lambdaQuery().like(Dmausertable::getDmaIds, v.getDmaGid()));
            if (count > 0) {
                isBing.append(v.getDmaName() + ",");
            }
        });
        if (isBing.length() > 0) {
            throw new ToflyDeniedException("以下分区存在用户绑定不能删除：" + isBing);
        }

//        删除分区
        regionService.removeByIds(idList);
//        删除绑定的管线信息
        pipeService.remove(Wrappers.<Dmaregionupipe>lambdaQuery().in(Dmaregionupipe::getDmaId, idList));
//        删除绑定的观察表关系
        dmaandobserService.remove(Wrappers.<Dmaandobser>lambdaQuery().in(Dmaandobser::getDmaId, idList));

//        //自定义一个方法实现递归删除分区下面的所有
//        return delete(idList);
        return true;
    }


    public boolean delete(List<Long> idList) {
        //先去查该分区有没有子级分区
        List<Dmaregion> regionList = regionService.list(Wrappers.<Dmaregion>lambdaQuery().in(Dmaregion::getPid, idList).select(Dmaregion::getId));
        //删除分区
        regionService.removeByIds(idList);
        //删除绑定的管线信息
        pipeService.remove(Wrappers.<Dmaregionupipe>lambdaQuery().in(Dmaregionupipe::getDmaId, idList));
        //得到id集合
        List<Long> ids = regionList.stream().map(Dmaregion::getId).collect(Collectors.toList());
        //递归删除
        for (int i = 0; i < ids.size(); i++) {
            delete(ids);
        }

        return true;
    }

    /**
     * 根据分区级别生成分区编码
     *
     * @param level 分区级别
     * @param pid   父级id
     * @return string
     */
    public String insertDmaCode(Long pid, Integer level) {

        String result;
        //先获得dma分区当前等级分区的编码
        List<String> dmaCodeList = dmaregionService.list(Wrappers.<Dmaregion>lambdaQuery()
                        .select(Dmaregion::getDmaCode)
                        .eq(Dmaregion::getPid, pid)
                        .eq(Dmaregion::getPartitionLevel, level))
                .stream()
                .map(Dmaregion::getDmaCode)
                .collect(Collectors.toList());

        Dmaregion region = dmaregionService.getById(pid);

        int size = dmaCodeList.size();

        //达到最大新建数量是抛出
        if (size == MAX_NUM) {
            Dmaregion dma = null;
            if (pid != 0) {
                dma = region;
            }
            throw new ToflyDeniedException(dma == null ? topCompanyName : dma.getDmaName() + "分区已达最大允许新建数：" + MAX_NUM + ";无法新建该分区的子分区");
        }

        if (level == 1) {
            if (size == 0) {
                result = "DMA-101";
            } else {
                result = "DMA-1";
                result = getString(result, dmaCodeList, size);
            }
        } else {
            result = region.getDmaCode();
            if (size == 0) {
                result += "-" + level + "01";
            } else {
                result += "-" + level;
                result = getString(result, dmaCodeList, size);
            }
        }
        return result;
    }

    private String getString(String result, List<String> dmaCodeList, int size) {
        for (int i = 1; i <= size; i++) {
            String s = result + (i < 10 ? "0" + i : i);
            if (!dmaCodeList.get(i - 1).equals(s)) {
                result = s;
                break;
            }
        }
        return result;
    }

    /**
     * 生成随机CODE
     *
     * @return code
     */
    protected String createCode(Integer partitionLevel) {
        String prefix = DateTimeUtil.getCurrentDate(DateTimeUtil.NUMBER_FORMAT);
        String pre = prefix.substring(0, 8);
        //使用redis生成唯一流水号
        Long sequence = stringRedisTemplate.opsForValue().increment(Constant.DMA_CODE_BATCH_ROB_MAINTAIN_SEQUENCE + "_" + pre, 1);
        if (null != sequence && sequence == 1) {
            stringRedisTemplate.delete(stringRedisTemplate.keys(Constant.DMA_CODE_BATCH_ROB_MAINTAIN_SEQUENCE + "_" + "*"));
            sequence = stringRedisTemplate.opsForValue().increment(Constant.DMA_CODE_BATCH_ROB_MAINTAIN_SEQUENCE + "_" + pre, 1);
        }
        //批次后缀 取流水号最后5位 如果不足5位前面补0
        String suffix = String.format("%05d", sequence % 100000);
        return "DMA-" + partitionLevel + "-" + suffix;

    }

}
