package com.boman.web.core.service.czrk;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.boman.common.core.exception.BaseException;
import com.boman.common.core.exception.CustomException;
import com.boman.common.core.utils.DateUtils;
import com.boman.common.core.utils.StringUtils;
import com.boman.common.core.utils.constant.HttpStatus;
import com.boman.common.core.utils.ip.IpUtils;
import com.boman.common.core.utils.number.NumberUtils;
import com.boman.common.core.utils.obj.ObjectUtils;
import com.boman.common.core.utils.sql.SqlUtil;
import com.boman.common.core.web.page.PageDomain;
import com.boman.common.core.web.page.TableSupport;
import com.boman.common.redis.service.RedisService;
import com.boman.common.security.service.TokenService;
import com.boman.domain.*;
import com.boman.domain.constant.CacheConstants;
import com.boman.domain.dto.AjaxResult;
import com.boman.domain.utils.ThreadPoolService;
import com.boman.system.api.RemoteDeptService;
import com.boman.system.api.RemoteDictDataService;
import com.boman.system.api.model.LoginUser;
import com.boman.web.core.domain.*;
import com.boman.web.core.mapper.*;
import com.boman.web.core.service.ip.IpTimesService;
import com.boman.web.core.utils.*;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.tomcat.util.buf.HexUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.boman.common.core.utils.StringUtils.isNotEmpty;
import static com.boman.common.core.utils.fieldTranslator.IdCardUtils.getSex;
import static com.boman.common.core.utils.obj.ObjectUtils.*;
import static com.boman.common.redis.RedisKey.*;
import static com.boman.web.core.utils.CzrkUtils.*;
import static com.boman.web.core.utils.IdCardUtils.getAge;
import static com.google.common.base.Strings.nullToEmpty;

/**
 * 常住人口Service业务层处理
 *
 * @author ruoyi
 * @date 2022-01-14
 */
@Service
@Slf4j
public class CzrkServiceImpl implements ICzrkService {

    private static JSONObject QIANSHANSHI = null, ZHEN = null, CUN = null, QIANSHANSHI_SINGEL = null, ECHARTS_LINE = null;

    @Autowired
    private CzrkMapper czrkMapper;
    @Resource
    private CzrkChangeMapper czrkChangeMapper;
    @Resource
    private RemoteDeptService remoteDeptService;
    @Resource
    private RedisService redisService;
    @Resource
    private ICzrkJzdzService czrkJzdzService;

    @Resource
    private GridInfoMapper gridInfoMapper;
    @Resource
    private IpTimesService ipTimesService;

    @Autowired
    private TokenService tokenService;

    @Resource
    private ThirdPartInfoMapper thirdPartInfoMapper;

    @Resource
    private RemoteDictDataService remoteDictDataService;
    @Resource
    private AccountingDataMapper accountingDataMapper;
    @Resource
    BirthRecordsMapper birthRecordsMapper;

    /**
     * 2022/3/24修复人员认领接口列表,逻辑:所有人都能看到所有没有确认,没有认领的人员
     *
     * @param czrk
     * @return java.util.List<com.boman.domain.Czrk>
     */
    @Override
    public List<Czrk> listByRlryHj(Czrk czrk) {
        //2022/3/24修复人员认领接口列表,等需要上线后开放
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}查询待认领人员列表，查询条件：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        //拆分搜索接口中年龄字段
        setAgeScope(czrk);
        startPage();
        List<Czrk> czrkNotRl = czrkMapper.selectCzrkByNotRl(czrk);
        CzrkUtils.packAddr(czrkNotRl);
        return czrkNotRl;
    }

    /**
     * 2022/3/24修复人员认领中常住人员接口列表,逻辑:所有人都能看到所有没有确认,没有认领的人员
     *
     * @param czrk
     * @return
     */
    @Override
    public List<Czrk> listByRlryCz(Czrk czrk) {
        //2022/3/24修复人员认领接口列表,等需要上线后开放
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}查询常住待认领人员列表，查询条件：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        //拆分搜索接口中年龄字段
        setAgeScope(czrk);
        startPage();
        List<Czrk> czrkNotRl = czrkMapper.selectCzrkByNotRlCz(czrk);
        CzrkUtils.packAddr(czrkNotRl);
        return czrkNotRl;
    }

    /**
     * 查询户籍人口信息
     * 2022/3/22重新修复的PC人员信息查看户籍人口接口
     */
    @Override
    public List<Czrk> listByCzrk(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}查询户籍人员列表，查询条件：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        setAgeScope(czrk);

        if(StringUtils.isNotEmpty(czrk.getKeyCategory())){
            List<String> keyCategoryList = Arrays.asList(czrk.getKeyCategory().trim().split(","));

            if(keyCategoryList!=null && keyCategoryList.size()>0){
                czrk.setKeyCategoryList(keyCategoryList);
            }
        }

        //获取到居住地的查询条件
        String provinceId = czrk.getProvinceIdXjd();
        String cityId = czrk.getCityIdXjd();
        String regionId = czrk.getRegionIdXjd();
        String villageTownsId = czrk.getVillageTownsIdXjd();
        String villageId = czrk.getVillageIdXjd();
        //设置查询列表权限
        setQueryRole(czrk, sysUser, Czrk.HJ);
        //如果查询参数有居住地址,进行连表查询
        if (StringUtils.isNotBlank(provinceId) || StringUtils.isNotBlank(cityId) || StringUtils.isNotBlank(regionId) || StringUtils.isNotBlank(villageTownsId) || StringUtils.isNotBlank(villageId)) {
            long startTimeSql = System.currentTimeMillis();
            startPage();
            List<Czrk> czrks = czrkMapper.listCzrkByJzdz(czrk);
            long endTimeSql = System.currentTimeMillis() - startTimeSql;
            log.info("执行查询人员信息中包含居住地址的sql语句时间:" + endTimeSql + "ms");
            CzrkUtils.packAddr(czrks);
            return czrks;
        }
        long startTimeSql = System.currentTimeMillis();
        //没有搜索居住地址的条件,进行单表查询
        startPage();
        List<Czrk> czrks = czrkMapper.listByCzrk(czrk);
        long endTimeSql = System.currentTimeMillis() - startTimeSql;
        log.info("执行查询sql语句时间:" + endTimeSql + "ms");
        CzrkUtils.packAddr(czrks);
        return czrks;
    }

    /**
     * 查询非正常人员列表(死亡,失踪)
     *
     * @param czrk
     * @return
     */
    @Override
    public List<Czrk> unusualList(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}查询非正常人员人员列表，查询条件：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        setAgeScope(czrk);
        //设置权限
        setQueryRole(czrk, sysUser, Czrk.HJ);
        long startTimeSql = System.currentTimeMillis();
        startPage();
        List<Czrk> czrks = czrkMapper.unusualList(czrk);
        long endTimeSql = System.currentTimeMillis() - startTimeSql;
        log.info("执行查询异常人员sql语句时间:" + endTimeSql + "ms");
        CzrkUtils.packAddr(czrks);
        return czrks;
    }

    /**
     * 查看家庭成员,获取居住地址,根据czrkId查询
     *
     * @param czrks
     * @return
     */
    private List<CzrkJzdz> getCzrkJzdzs(List<Czrk> czrks) {
        List<Long> czrkIdList = map(czrks, Czrk::getId);
        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.listByCzrkIds(czrkIdList);
        //List<CzrkJzdz> czrkJzdzList = czrkJzdzService.listByIdCard(idCardList);
        return czrkJzdzList;
    }

    @Override
    public List<Czrk> listByXz(Czrk czrk) {
        log.info("{}于{}查询新增常住人员列表，查询条件：{}"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        setDeptIdList(czrk);

        czrk.setStartTime(DateUtils.getTodayStartStr());
        czrk.setEndTime(DateUtils.getTodayEndStr());
        startPage();
        czrk.setRegionId("340882000000");
        List<Czrk> czrks = new ArrayList<>();
        if (czrk.getQueryType().equals(Czrk.HJ)) {
            czrks = czrkMapper.listByXz(czrk);
            if (isNotEmpty(czrks)) {
                // 居住地址
                List<CzrkJzdz> czrkJzdzList = getCzrkJzdzs(czrks);
                handleList(czrks, Czrk.HJ, czrkJzdzList);
            } else {
                czrks = new ArrayList<>();
            }

        } else {
            String regionId = "340882000000";
            String status = "Y";
            //居住信息
            List<CzrkJzdz> czrkJzdzList = czrkJzdzService.getCzrkJzdzByTime(DateUtils.getTodayStartStr(), DateUtils.getTodayEndStr(), regionId, status);

            if (isNotEmpty(czrkJzdzList)) {
                List<String> czrkIdCardList = map(czrkJzdzList, CzrkJzdz::getIdCard);
                //户籍信息
                czrks = czrkMapper.listByIdCard(czrkIdCardList);
                handleList(czrks, Czrk.CZ, czrkJzdzList);
            }

        }


        //packAddr(czrks);
        return czrks;
    }

    @Override
    public List<Czrk> listByJs(Czrk czrk) {
        log.info("{}于{}查询减少常住人员列表，查询条件：{}"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        setDeptIdList(czrk);

        czrk.setStartTime(DateUtils.getTodayStartStr());
        czrk.setEndTime(DateUtils.getTodayEndStr());
        startPage();
        czrk.setRegionId("340882000000");
        List<Czrk> czrks = new ArrayList<>();
        if (czrk.getQueryType().equals(Czrk.HJ)) {
            czrks = czrkMapper.listByJs(czrk);
            if (isNotEmpty(czrks)) {
                // 居住地址
                List<CzrkJzdz> czrkJzdzList = getCzrkJzdzs(czrks);

                handleList(czrks, Czrk.HJ, czrkJzdzList);
            } else {
                czrks = new ArrayList<>();
            }

        } else {
            String regionId = "340882000000";
            String status = "N";
            //居住信息
            List<CzrkJzdz> czrkJzdzList = czrkJzdzService.getCzrkJzdzByTime(DateUtils.getTodayStartStr(), DateUtils.getTodayEndStr(), regionId, status);

            if (isNotEmpty(czrkJzdzList)) {
                List<String> czrkIdCardList = map(czrkJzdzList, CzrkJzdz::getIdCard);
                //户籍信息
                czrks = czrkMapper.listByIdCard(czrkIdCardList);
                handleList(czrks, Czrk.CZ, czrkJzdzList);
            }
        }


        //packAddr(czrks);
        return czrks;
    }

    private void handleList(List<Czrk> czrks, String queryType, List<CzrkJzdz> czrkJzdzList) {
        for (Czrk crk : czrks) {
            // 户籍地
            String province = nullToEmpty(crk.getProvince()), city = nullToEmpty(crk.getCity()), region = nullToEmpty(crk.getRegion()), villageTowns = nullToEmpty(crk.getVillageTowns()), village = nullToEmpty(crk.getVillage()), villageGroup = nullToEmpty(crk.getVillagerGroup()), nowIn = nullToEmpty(crk.getNowIn());
            crk.setDomicileSelect(province + city + region + villageTowns + village + villageGroup);

            // 现居住地
            for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                if (!czrkJzdz.getIdCard().equals(crk.getIdCard())) continue;

                String provinceCz = nullToEmpty(czrkJzdz.getProvince()), cityCz = nullToEmpty(czrkJzdz.getCity()), regionCz = nullToEmpty(czrkJzdz.getRegion()), villageTownsCz = nullToEmpty(czrkJzdz.getTown()), villageCz = nullToEmpty(czrkJzdz.getVillage()), nowInCz = nullToEmpty(czrkJzdz.getNowIn());
                crk.setNowInSelect(provinceCz + cityCz + regionCz + villageTownsCz + villageCz);
                crk.setDomicile(nowInCz);
                break;
            }
        }
    }

    private void packAddr(JSONObject czrks) {
        if (isEmpty(czrks)) return;
        // 户籍地
        String province = nullToEmpty(czrks.getString("province")), city = nullToEmpty(czrks.getString("city")), region = nullToEmpty(czrks.getString("region")), villageTowns = nullToEmpty(czrks.getString("villageTowns")), village = nullToEmpty(czrks.getString("village")), villageGroup = nullToEmpty(czrks.getString("villageGroup")), nowIn = nullToEmpty(czrks.getString("nowIn"));
        province = province + city + region + villageTowns + village + villageGroup;
        if (StringUtils.isNotBlank(province)) {
            czrks.put("domicileSelect", province);
        }

/*        // 现居住地
        String provinceCz = nullToEmpty(czrks.getString("provinceIdXjd")), cityCz = nullToEmpty(czrks.getString("cityIdXjd")), regionCz = nullToEmpty(czrks.getString("regionXjd")), villageTownsCz = nullToEmpty(czrks.getString("villageTownsXjd")), villageCz = nullToEmpty(czrks.getString("villageXjd")), nowInCz = nullToEmpty(czrks.getString("nowIn"));
        czrks.put("nowInSelect",provinceCz + cityCz + regionCz + villageTownsCz + villageCz + nowInCz);*/

    }

    private void packCzrkJzdzAddr(List<CzrkJzdz> czrkJzdzList) {
        if (isEmpty(czrkJzdzList)) return;
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            // 户籍地
            String province = nullToEmpty(czrkJzdz.getProvince()), city = nullToEmpty(czrkJzdz.getCity()), region = nullToEmpty(czrkJzdz.getRegion()), villageTowns = nullToEmpty(czrkJzdz.getTown()), village = nullToEmpty(czrkJzdz.getVillage()), nowIn = nullToEmpty(czrkJzdz.getNowIn());
            czrkJzdz.setNowIn(province + city + region + villageTowns + village);
        }
    }

    private void startPage() {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.startPage(pageNum, pageSize, orderBy);
        }
    }


    private void setDeptIdList(Czrk czrk) {
        Long deptId = czrk.getDeptId();
        if (deptId == null) {
            deptId = AuthUtils.getLoginUser().getSysUser().getDeptId();
            //判断是否是管理员
            List<SysRole> roles = AuthUtils.getLoginUser().getSysUser().getRoles();
            if (isNotEmpty(roles)) {
                for (SysRole role : roles) {
                    String roleKey = role.getRoleKey();
                    if ("admin".equals(roleKey) || "city".equals(roleKey) || "yanshi".equals(roleKey)) {
                        return;
                    }
                }
            }
        }

        if (deptId != null) {
            List<SysDept> sysDepts = remoteDeptService.listChildrenDepts(deptId);
            if (isNotEmpty(sysDepts)) {
                czrk.setDeptIdList(map(sysDepts, SysDept::getId));
            }
        }
    }

    private List<Long> getDeptIdList(Long deptId) {
        if (deptId == null) {
            deptId = AuthUtils.getLoginUser().getSysUser().getDeptId();
            //判断是否是管理员
            List<SysRole> roles = AuthUtils.getLoginUser().getSysUser().getRoles();
            if (isNotEmpty(roles)) {
                for (SysRole role : roles) {
                    String roleKey = role.getRoleKey();
                    if ("admin".equals(roleKey) || "city".equals(roleKey)) {
                        return null;
                    }
                }
            }
        }

        if (deptId != null) {
            List<SysDept> sysDepts = remoteDeptService.listChildrenDepts(deptId);
            if (isNotEmpty(sysDepts)) {
                return map(sysDepts, SysDept::getId);
            }
        }

        return null;
    }

    /**
     * 查询常住人口
     *
     * @param id 常住人口主键
     * @return 常住人口
     */
    @Override
    public Czrk selectCzrkById(Long id) {
        log.info("{}于{}根据id：{}，获取信息"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), id);
        Czrk czrk = czrkMapper.selectCzrkById(id);
        /*if (czrk != null) {
            Long gridId = czrk.getGridId();
            if (gridId != null) {
                GridInfo gridInfo = gridInfoMapper.selectGridInfoById(gridId);
                if (gridInfo != null) {
                    String areaName = gridInfo.getAreaName();
                    czrk.setGridName(areaName);
                }
            }
        }*/
        return czrk;
    }


    /**
     * 新增常住人口
     *
     * @param czrk 常住人口
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public AjaxResult insertCzrk(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}新增户籍人口：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        List<CzrkJzdz> czrkJzdzList = czrk.getCzrkJzdzList();
        if (isEmpty(czrkJzdzList)) return AjaxResult.error("该人员常住地址未添加");
        //一开始就判断是否是户籍和所有居住地址是否都不在权限之下
        if (setInsertRole(czrk, sysUser)) {
            log.info("{}于{}新增户籍人口失败户籍地址和居住地址均不属于权限范围：{}"
                    , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
            return AjaxResult.error(HttpStatus.NOT_IMPLEMENTED, "当前填写的户籍地址和居住地址均不属于权限范围");
        }
        String houseType = czrk.getHouseType();
        String code = czrk.getCode();
        if ("是".equals(houseType) && StringUtils.isNotBlank(code)) {
            //去查询该户号的户主信息
            Czrk czrkCode = czrkMapper.selectCzrkByCode(code);
            if (czrkCode != null && StringUtils.isNotBlank(czrkCode.getIdCard())) {
                return AjaxResult.error("该户编号已存在户主,请勿重复添加户主");
            }
        }
        //用户账号
        String username = sysUser.getUserName();
        //用户姓名
        String nickName = sysUser.getNickName();
        //判断是否选择到了自己的权限所在乡镇,则判断为认领
        if (isNotEmpty(czrk.getVillageTowns()) && czrk.getVillageTowns().equals(sysUser.getDept().getAreaId())) {
            czrk.setRlrNike(nickName);
            czrk.setRlr(username);
            czrk.setIsRl("是");
            czrk.setRlTime(DateUtils.getNowDate());
        }

        // 当前登陆人的dept_id
        czrk.setDeptId(sysUser.getDeptId());
        int count = czrkMapper.countIdCard(czrk.getIdCard());
        if (count > 0) return AjaxResult.error(String.format("该人员[身份证号为: %s]已存在，请勿重复添加", czrk.getIdCard()));

        czrk.setCreateBy(username);
        count = czrkMapper.insertCzrk(czrk);
        if (count < 1) return AjaxResult.error("新增户籍信息失败");
        int sort = 0, childCount = 0;
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            czrkJzdz.setCzrkId(czrk.getId());
            czrkJzdz.setSort(++sort);
            czrkJzdz.setUserName(czrk.getUserName());
            czrkJzdz.setIdCard(czrk.getIdCard());
            czrkJzdz.setCreateBy(username);
            // 当前登陆人的所属最后一级的dept_id
            czrkJzdz.setDeptId(sysUser.getDeptId());
            childCount += czrkJzdzService.insertCzrkJzdz(czrkJzdz);

        }

        //人员信息新增成功
        if (childCount > 0) {
            addExtracted(czrk, czrkJzdzList);
        }
        return childCount > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    private void addExtracted(Czrk czrk, List<CzrkJzdz> czrkJzdzList) {
        //同步修改redis缓存数据
        //修改潜山市总数居
        //从redis取出潜山市数据
        JSONObject jsonObjects = redisService.getCacheObject(packRedisKey("1"));
        if (isEmpty(jsonObjects)) {
            return;
        }

        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();

        Timestamp s = Timestamp.valueOf(startTime);
        Timestamp e = Timestamp.valueOf(endTime);

        //判断新增的是否是潜山市人口（户籍判断）
        if (!ObjectUtils.isEmpty(czrk) && StringUtils.isNotEmpty(czrk.getRegionId()) && czrk.getRegionId().equals("340882000000")) {
            //总户籍人数
            jsonObjects.put("hjzrs", (Integer) jsonObjects.get("hjzrs") + 1);
            //户籍新增人数
            jsonObjects.put("hjxz", (Integer) jsonObjects.get("hjxz") + 1);
            if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                if ((Integer) jsonObjects.get("hjjs") > 0) {
                    jsonObjects.put("hjjs", (Integer) jsonObjects.get("hjjs") - 1);
                }
            }
            //根据人员的乡镇区划编号去部门表里查询dept_id
            List<SysDept> allDepts = remoteDeptService.selectByAreaId(czrk.getVillageTownsId());
            for (SysDept allDept : allDepts) {
                //修改镇数据
                //从redis取出镇数据
                JSONObject jsonObjectz = redisService.getCacheObject(packRedisKey("town:" + allDept.getId()));
                //镇总户籍人数
                jsonObjectz.put("hjzrs", (Integer) jsonObjectz.get("hjzrs") + 1);
                //镇户籍新增人数
                jsonObjectz.put("hjxz", (Integer) jsonObjectz.get("hjxz") + 1);

                if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                    if ((Integer) jsonObjectz.get("hjjs") > 0) {
                        jsonObjectz.put("hjjs", (Integer) jsonObjectz.get("hjjs") - 1);
                    }
                }

                //镇户籍人数占比
                jsonObjectz.put("hjbfb", NumberUtils.percent((Integer) jsonObjectz.get("hjzrs"), (Integer) jsonObjects.get("hjzrs")));
                setIntoRedis(packRedisKey("town:" + allDept.getId()), jsonObjectz);

                //修改市数据里的乡镇数据
                List<JSONObject> jsList = (List<JSONObject>) jsonObjects.get("townDatas");
                for (JSONObject stringObjectMap : jsList) {
                    if (allDept.getDeptName().equals(stringObjectMap.get("zhen"))) {
                        //镇总户籍人数
                        stringObjectMap.put("hjzrs", (Integer) stringObjectMap.get("hjzrs") + 1);
                        //镇户籍新增人数
                        stringObjectMap.put("hjxz", (Integer) stringObjectMap.get("hjxz") + 1);

                        if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                            if ((Integer) stringObjectMap.get("hjjs") > 0) {
                                stringObjectMap.put("hjjs", (Integer) stringObjectMap.get("hjjs") - 1);
                            }
                        }

                        //镇户籍人数占比
                        stringObjectMap.put("hjbfb", NumberUtils.percent((Integer) stringObjectMap.get("hjzrs"), (Integer) jsonObjects.get("hjzrs")));
                    }
                }
            }
            //setIntoRedis(packRedisKey(1L + ""), jsonObjects);

            //查找村数据
            //根据人员的村区划编号去部门表里查询dept_id
            if (StringUtils.isNotEmpty(czrk.getVillageId())) {
                List<SysDept> allDeptC = remoteDeptService.selectByAreaId(czrk.getVillageId());
                for (SysDept sysDept : allDeptC) {
                    JSONObject jsonObjectC = redisService.getCacheObject(packRedisKey("village:" + sysDept.getId()));
                    if (isEmpty(jsonObjectC)) {
                        continue;
                    }
                    //村总户籍人数
                    jsonObjectC.put("hjzrs", (Integer) jsonObjectC.get("hjzrs") + 1);
                    //村户籍新增人数
                    jsonObjectC.put("hjxz", (Integer) jsonObjectC.get("hjxz") + 1);

                    if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                        if ((Integer) jsonObjectC.get("hjjs") > 0) {
                            jsonObjectC.put("hjjs", (Integer) jsonObjectC.get("hjjs") - 1);
                        }
                    }

                    //村户籍人数占比
                    jsonObjectC.put("hjbfb", NumberUtils.percent((Integer) jsonObjectC.get("hjzrs"), (Integer) jsonObjects.get("hjzrs")));
                    setIntoRedis(packRedisKey("village:" + sysDept.getId()), jsonObjectC);
                }
            }

        }

        if (czrkJzdzList.size() > 0) {
            for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                if (StringUtils.isNotEmpty(czrkJzdz.getRegionId()) && StringUtils.isNotEmpty(czrkJzdz.getRegionId()) && czrkJzdz.getRegionId().equals("340882000000")) {
                    //总常驻人数
                    jsonObjects.put("czzrs", (Integer) jsonObjects.get("czzrs") + 1);
                    //常驻新增人数
                    jsonObjects.put("czxz", (Integer) jsonObjects.get("czxz") + 1);

                    //根据人员的乡镇区划编号去部门表里查询dept_id
                    List<SysDept> cAllDepts = remoteDeptService.selectByAreaId(czrkJzdz.getTownId());
                    for (SysDept allDept : cAllDepts) {
                        //修改镇数据
                        //从redis取出镇数据
                        JSONObject cJsonObjectz = redisService.getCacheObject(packRedisKey("town:" + allDept.getId()));
                        //镇总户籍人数
                        cJsonObjectz.put("czzrs", (Integer) cJsonObjectz.get("czzrs") + 1);
                        //镇户籍新增人数
                        cJsonObjectz.put("czxz", (Integer) cJsonObjectz.get("czxz") + 1);
                        //镇户籍人数占比
                        cJsonObjectz.put("czbfb", NumberUtils.percent((Integer) cJsonObjectz.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                        setIntoRedis(packRedisKey("town:" + allDept.getId()), cJsonObjectz);

                        //修改市数据里的乡镇数据
                        List<JSONObject> jsList = (List<JSONObject>) jsonObjects.get("townDatas");
                        for (JSONObject stringObjectMap : jsList) {
                            if (allDept.getDeptName().equals(stringObjectMap.get("zhen"))) {
                                //镇总户籍人数
                                stringObjectMap.put("czzrs", (Integer) stringObjectMap.get("czzrs") + 1);
                                //镇户籍新增人数
                                stringObjectMap.put("czxz", (Integer) stringObjectMap.get("czxz") + 1);
                                //镇户籍人数占比
                                stringObjectMap.put("czbfb", NumberUtils.percent((Integer) stringObjectMap.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                            }
                        }
                    }


                    //查找村数据
                    //根据人员的村区划编号去部门表里查询dept_id
                    if (StringUtils.isNotEmpty(czrk.getVillageId())) {
                        List<SysDept> cAllDeptC = remoteDeptService.selectByAreaId(czrkJzdz.getVillageId());
                        for (SysDept sysDept : cAllDeptC) {
                            JSONObject cJsonObjectC = redisService.getCacheObject(packRedisKey("village:" + sysDept.getId()));
                            if (isEmpty(cJsonObjectC)) {
                                continue;
                            }
                            //村总户籍人数
                            cJsonObjectC.put("czzrs", (Integer) cJsonObjectC.get("czzrs") + 1);
                            //村户籍新增人数
                            cJsonObjectC.put("czxz", (Integer) cJsonObjectC.get("czxz") + 1);
                            //村户籍人数占比
                            cJsonObjectC.put("czbfb", NumberUtils.percent((Integer) cJsonObjectC.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                            setIntoRedis(packRedisKey("village:" + sysDept.getId()), cJsonObjectC);
                        }
                        break;
                    }
                }
            }
        }

        //将潜山市数据存入redis
        setIntoRedis(packRedisKey(1L + ""), jsonObjects);

    }


    private void reduceExtracted(Czrk czrk, List<CzrkJzdz> czrkJzdzList) {
        //同步修改redis缓存数据
        //修改潜山市总数居
        //从redis取出潜山市数据
        JSONObject jsonObjects = redisService.getCacheObject(packRedisKey("1"));
        if (isEmpty(jsonObjects)) {
            return;
        }

        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();

        Timestamp s = Timestamp.valueOf(startTime);
        Timestamp e = Timestamp.valueOf(endTime);

        //判断新增的是否是潜山市人口（户籍判断）
        if (!ObjectUtils.isEmpty(czrk) && StringUtils.isNotEmpty(czrk.getRegionId()) && czrk.getRegionId().equals("340882000000")) {
            //总户籍人数
            jsonObjects.put("hjzrs", (Integer) jsonObjects.get("hjzrs") - 1);
            //户籍新增人数
            jsonObjects.put("hjjs", (Integer) jsonObjects.get("hjjs") + 1);

            if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                if ((Integer) jsonObjects.get("hjxz") > 0) {
                    jsonObjects.put("hjxz", (Integer) jsonObjects.get("hjxz") - 1);
                }
            }

            //根据人员的乡镇区划编号去部门表里查询dept_id
            List<SysDept> allDepts = remoteDeptService.selectByAreaId(czrk.getVillageTownsId());
            for (SysDept allDept : allDepts) {
                //修改镇数据
                //从redis取出镇数据
                JSONObject jsonObjectz = redisService.getCacheObject(packRedisKey("town:" + allDept.getId()));
                //镇总户籍人数
                jsonObjectz.put("hjzrs", (Integer) jsonObjectz.get("hjzrs") - 1);
                //镇户籍新增人数
                jsonObjectz.put("hjjs", (Integer) jsonObjectz.get("hjjs") + 1);
                if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                    if ((Integer) jsonObjectz.get("hjxz") > 0) {
                        jsonObjectz.put("hjxz", (Integer) jsonObjectz.get("hjxz") - 1);
                    }
                }
                //镇户籍人数占比
                jsonObjectz.put("hjbfb", NumberUtils.percent((Integer) jsonObjectz.get("hjzrs"), (Integer) jsonObjects.get("hjzrs")));
                setIntoRedis(packRedisKey("town:" + allDept.getId()), jsonObjectz);

                //修改市数据里的乡镇数据
                List<JSONObject> jsList = (List<JSONObject>) jsonObjects.get("townDatas");
                for (JSONObject stringObjectMap : jsList) {
                    if (allDept.getDeptName().equals(stringObjectMap.get("zhen"))) {
                        //镇总户籍人数
                        stringObjectMap.put("hjzrs", (Integer) stringObjectMap.get("hjzrs") - 1);
                        //镇户籍新增人数
                        stringObjectMap.put("hjjs", (Integer) stringObjectMap.get("hjjs") + 1);

                        if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                            if ((Integer) stringObjectMap.get("hjxz") > 0) {
                                stringObjectMap.put("hjxz", (Integer) stringObjectMap.get("hjxz") - 1);
                            }
                        }

                        //镇户籍人数占比
                        stringObjectMap.put("hjbfb", NumberUtils.percent((Integer) stringObjectMap.get("hjzrs"), (int) jsonObjects.get("hjzrs")));
                    }
                }
            }
            //setIntoRedis(packRedisKey(1L + ""), jsonObjects);

            //查找村数据
            //根据人员的村区划编号去部门表里查询dept_id
            if (StringUtils.isNotEmpty(czrk.getVillageId())) {
                List<SysDept> allDeptC = remoteDeptService.selectByAreaId(czrk.getVillageId());
                for (SysDept sysDept : allDeptC) {
                    JSONObject jsonObjectC = redisService.getCacheObject(packRedisKey("village:" + sysDept.getId()));
                    if (isEmpty(jsonObjectC)) {
                        continue;
                    }
                    //村总户籍人数
                    jsonObjectC.put("hjzrs", (Integer) jsonObjectC.get("hjzrs") - 1);
                    //村户籍新增人数
                    jsonObjectC.put("hjjs", (Integer) jsonObjectC.get("hjjs") + 1);

                    if (null != czrk.getUpdateTime() && s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                        if ((Integer) jsonObjectC.get("hjxz") > 0) {
                            jsonObjectC.put("hjxz", (Integer) jsonObjectC.get("hjxz") - 1);
                        }
                    }

                    //村户籍人数占比
                    jsonObjectC.put("hjbfb", NumberUtils.percent((Integer) jsonObjectC.get("hjzrs"), (Integer) jsonObjects.get("hjzrs")));
                    setIntoRedis(packRedisKey("village:" + sysDept.getId()), jsonObjectC);
                }
            }

        }

        if (czrkJzdzList.size() > 0) {
            for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                if (StringUtils.isNotEmpty(czrkJzdz.getRegionId()) && StringUtils.isNotEmpty(czrkJzdz.getRegionId()) && czrkJzdz.getRegionId().equals("340882000000")) {
                    //总常驻人数
                    jsonObjects.put("czzrs", (Integer) jsonObjects.get("czzrs") - 1);
                    //常驻新增人数
                    jsonObjects.put("czjs", (Integer) jsonObjects.get("czjs") + 1);

                    //根据人员的乡镇区划编号去部门表里查询dept_id
                    List<SysDept> cAllDepts = remoteDeptService.selectByAreaId(czrkJzdz.getTownId());
                    for (SysDept allDept : cAllDepts) {
                        //修改镇数据
                        //从redis取出镇数据
                        JSONObject cJsonObjectz = redisService.getCacheObject(packRedisKey("town:" + allDept.getId()));
                        //镇总户籍人数
                        cJsonObjectz.put("czzrs", (Integer) cJsonObjectz.get("czzrs") - 1);
                        //镇户籍新增人数
                        cJsonObjectz.put("czjs", (Integer) cJsonObjectz.get("czjs") + 1);
                        //镇户籍人数占比
                        cJsonObjectz.put("czbfb", NumberUtils.percent((Integer) cJsonObjectz.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                        setIntoRedis(packRedisKey("town:" + allDept.getId()), cJsonObjectz);

                        //修改市数据里的乡镇数据
                        List<JSONObject> jsList = (List<JSONObject>) jsonObjects.get("townDatas");
                        for (JSONObject stringObjectMap : jsList) {
                            if (allDept.getDeptName().equals(stringObjectMap.get("zhen"))) {
                                //镇总户籍人数
                                stringObjectMap.put("czzrs", (Integer) stringObjectMap.get("czzrs") - 1);
                                //镇户籍新增人数
                                stringObjectMap.put("czjs", (Integer) stringObjectMap.get("czjs") + 1);
                                //镇户籍人数占比
                                stringObjectMap.put("czbfb", NumberUtils.percent((Integer) stringObjectMap.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                            }
                        }
                    }


                    //查找村数据
                    //根据人员的村区划编号去部门表里查询dept_id
                    if (StringUtils.isNotEmpty(czrk.getVillageId())) {
                        List<SysDept> cAllDeptC = remoteDeptService.selectByAreaId(czrkJzdz.getVillageId());
                        for (SysDept sysDept : cAllDeptC) {
                            JSONObject cJsonObjectC = redisService.getCacheObject(packRedisKey("village:" + sysDept.getId()));
                            if (isEmpty(cJsonObjectC)) {
                                continue;
                            }
                            //村总户籍人数
                            cJsonObjectC.put("czzrs", (Integer) cJsonObjectC.get("czzrs") - 1);
                            //村户籍新增人数
                            cJsonObjectC.put("czjs", (Integer) cJsonObjectC.get("czjs") + 1);
                            //村户籍人数占比
                            cJsonObjectC.put("czbfb", NumberUtils.percent((Integer) cJsonObjectC.get("czzrs"), (Integer) jsonObjects.get("czzrs")));
                            setIntoRedis(packRedisKey("village:" + sysDept.getId()), cJsonObjectC);
                        }
                        break;
                    }

                }
            }
        }

        //将潜山市数据存入redis
        setIntoRedis(packRedisKey(1L + ""), jsonObjects);

    }

    /**
     * 修改户籍人口
     *
     * @param czrk 户籍人口
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateCzrk(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}修改户籍人口：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        List<CzrkJzdz> czrkJzdzList = czrk.getCzrkJzdzList();
        if (isEmpty(czrkJzdzList)) return AjaxResult.error("该人员常住地址未添加");
        //一开始就判断是否是户籍和所有居住地址是否都不在权限之下
        if (setInsertRole(czrk, sysUser)) {
            return AjaxResult.error(HttpStatus.NOT_IMPLEMENTED, "当前填写的户籍地址和居住地址均不属于权限范围");
        }
        //看是否是户主,且有户主号需要去查看该家庭是否有户主
        String houseType = czrk.getHouseType();
        String code = czrk.getCode();
        if ("是".equals(houseType) && StringUtils.isNotBlank(code)) {
            Czrk czrkCode = czrkMapper.selectCzrkByCode(code);
            if (czrkCode != null && !czrkCode.getIdCard().equals(czrk.getIdCard())) {
                return AjaxResult.error("该户编号已存在户主,请勿重复添加户主");
            }
        }
        // 获取当前的用户账号
        String username = sysUser.getUserName();
        //用户姓名
        String nickName = sysUser.getNickName();

        //判断是否确认
        String isConfirm = czrk.getIsConfirm();
        if (StringUtils.isNotBlank(isConfirm) && "Y".equals(isConfirm)) {
            czrk.setConfirmInfoUser(username);
            czrk.setConfirmInfoUserTime(DateUtils.getNowDate());
            czrk.setConfirmInfoNikeUser(nickName);
            //确认的都算认领
            czrk.setRlrNike(nickName);
            czrk.setRlr(username);
            czrk.setIsRl("是");
            czrk.setDeptId(sysUser.getDeptId());
            czrk.setRlTime(DateUtils.getNowDate());
        }
        czrk.setUpdateBy(username);
        int count = czrkMapper.updateCzrk(czrk);
        if (count <= 0) return AjaxResult.error();
        //往confirm_info_user表中差数据
        ConfirmInfoUser confirmInfoUser = new ConfirmInfoUser();
        confirmInfoUser.setCzrkId(czrk.getId());
        confirmInfoUser.setConfirmInfoUser(username);
        confirmInfoUser.setConfirmInfoNikeUser(nickName);
        czrkMapper.insertConfirmInfoUser(confirmInfoUser);


        czrkJzdzService.deleteByCzrkId(czrk.getId());
        int sort = 0, childCount = 0;
        //处理居住地址
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            czrkJzdz.setCzrkId(czrk.getId());
            czrkJzdz.setSort(++sort);
            czrkJzdz.setUserName(czrk.getUserName());
            czrkJzdz.setIdCard(czrk.getIdCard());
            czrkJzdz.setCreateBy(username);
            childCount += czrkJzdzService.insertCzrkJzdz(czrkJzdz);
        }

        return childCount == czrkJzdzList.size() ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 批量删除常住人口
     *
     * @param czrk 需要删除的常住人口主键和删除原因
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public int deleteCzrk(Czrk czrk) {
        log.info("{}于{}删除常住人口：{}"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        czrk.setUpdateBy(AuthUtils.getLoginUser().getSysUser().getUserName());
        if (isEmpty(czrk.getDeleteReason())) {
            log.error("删除原因不能为空, id={}", czrk.getId());
            return 0;
        }

        int delete = czrkMapper.deleteCzrk(czrk);
        Long czrkId = czrk.getId();
        CzrkJzdz czrkJzdz = new CzrkJzdz();
        czrkJzdz.setCzrkId(czrkId);
        czrkJzdz.setStatus("N");
        int update = czrkJzdzService.updateByCzrkId(czrkJzdz);
        return 1;
    }

    /**
     * 删除常住人口信息
     *
     * @param id 常住人口主键
     * @return 结果
     */
    @Override
    public int deleteCzrkById(Long id) {
        return czrkMapper.deleteCzrkById(id);
    }

    /**
     * 功能描述: 回收站的还原功能
     *
     * @param id id
     * @return int
     */
    @Override
    public int reduction(String id) {
        log.info("{}于{}使用回收站还原功能，id：{}"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), id);
        if (isEmpty(id)) return 0;

        return czrkMapper.reduction(id);
    }

    @Override
    public List<Czrk> family(String code) {
        log.info("{}于{}根据户号查找家庭中所有人员，户号：{}"
                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), code);
        if (isEmpty(code)) {
            return Collections.emptyList();
        }
        //查找当前所有家庭成员（户主在第一位）
        List<Czrk> czrks = czrkMapper.listByCode(code);
        // 居住地址
        List<CzrkJzdz> czrkJzdzList = getCzrkJzdzs(czrks);

        handleList(czrks, Czrk.HJ, czrkJzdzList);
        return czrks;
    }

    /***
     * 功能描述: 根据户主修改家庭成员的户籍与居住信息
     * @return com.boman.domain.dto.AjaxResult
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public AjaxResult synchronization(String code) {
//        log.info("{}于{}根据户号同步家庭中所有人员，户号：{}"
//                , AuthUtils.getLoginUser().getSysUser().getUserName(), DateUtils.dateTimeNow(), code);
//        if (isEmpty(code)) {
//            return "失败";
//        }

        //查找当前所有家庭成员（户主在第一位）
        List<Czrk> czrks = czrkMapper.listByCodeSynchronization(code);
        if (czrks.size() == 1) {
            return AjaxResult.success("无家庭成员");
        }
        //修改家庭成员信息（户籍地址）
        //修改户籍地址
        int hj = czrkMapper.updateHouseholdRegister(czrks.get(0));
        /*//修改居住地址
        List<String> idCardList = map(czrks, Czrk::getIdCard);
        //查找户主的居住地信息
        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.listByIdCard(idCardList);
        //取出户主信息
        CzrkJzdz hzCzrkJzdz = new CzrkJzdz();
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            if(czrks.get(0).getId().equals(czrkJzdz.getCzrkId())){
                hzCzrkJzdz = czrkJzdz;
                break;
            }
        }
        int jz = czrkJzdzService.updateHouseholdRegister(idCardList,hzCzrkJzdz);*/
        return AjaxResult.success("操作成功");
    }

    /**
     * 变更接口
     *
     * @param czrk
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult changeCzrk(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        if (sysUser == null) {
            return AjaxResult.error("未获取到当前登录人");
        }
        //判断一下id是否存在
        Long id = czrk.getId();
        if (id == null) {
            return AjaxResult.error("未获取到人员id");
        }
        //如果是迁出,则放到待认领中
        String status = czrk.getStatus();
        //根据id查询出这个人信息
        Czrk czrkQianchu = czrkMapper.selectCzrkById(id);
        czrkQianchu.setChangUser(sysUser.getUserName());
        czrkQianchu.setChangNikeUser(sysUser.getNickName());
        czrkQianchu.setChangUserTime(DateUtils.getNowDate());
        //先保存这个人的信息,当做历史记录
        czrkChangeMapper.insertCzrkChange(czrkQianchu);
        if (StringUtils.isNotBlank(status) && "2".equals(status)) {
            czrkQianchu.setIsRl("否");
            czrkQianchu.setRlr("");
            czrkQianchu.setRlrNike("");
            czrkQianchu.setIsConfirm("N");
            czrkQianchu.setConfirmInfoUser("");
            czrkQianchu.setChangNikeUser("");
            czrkQianchu.setConfirmInfoUserTime(null);
            czrkQianchu.setStatus(status);
            czrkMapper.updateCzrk(czrkQianchu);

            //迁出;
            reduceExtracted(czrkQianchu, new ArrayList<CzrkJzdz>());
            return AjaxResult.success();
        }
        //接下来则放入其他状态中
        String userName = sysUser.getUserName();
        czrk.setChangUser(userName);
        czrk.setChangUserTime(DateUtils.getNowDate());
        czrk.setChangNikeUser(sysUser.getNickName());
        //别的状态如果是户主,改成非户主
        czrk.setHouseType("否");
        czrkMapper.changeCzrk(czrk);

        //变更redis数据(正常(1)是新增，迁出(2)、失踪(3)、死亡(4)是减少)
        if (StringUtils.isNotBlank(status)) {
            if ("1".equals(status)) {
                addExtracted(czrkQianchu, new ArrayList<CzrkJzdz>());
            } else {
                reduceExtracted(czrkQianchu, new ArrayList<CzrkJzdz>());
            }
        }

        return AjaxResult.success();

    }

    /**
     * 查询历史变更信息
     *
     * @param czrk
     * @return
     */
    @Override
    public AjaxResult changeCzrkHistory(Czrk czrk) {
        List<Czrk> czrks = czrkChangeMapper.selectListByCzrkId(czrk);
        CzrkUtils.packAddr(czrks);
        return AjaxResult.success(czrks);
    }

    /**
     * 2022/3/24修改的根据czrkId查询该用户信息
     *
     * @param s
     * @return
     */
    @Override
    public List<Czrk> getAllCzrkRegionId(String s) {
        return czrkMapper.getAllCzrkRegionId(s);
    }

    @Override
    public List<Czrk> getAllCzrk(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        setQueryRole(czrk, sysUser, Czrk.HJ);
        setAgeScope(czrk);
        List<Czrk> czrkList = czrkMapper.getAllCzrk(czrk);

       /* List<Czrk> czrkListp = czrkList.stream().sorted(
                //以户籍号排序
                Comparator.comparing(Czrk::getCode, Comparator.reverseOrder())
                        //户主排序
                        .thenComparing(Czrk::getHouseType, Comparator.reverseOrder())

        ).collect(Collectors.toList());*/

        CzrkUtils.packAddr(czrkList);
        if (czrkList == null || czrkList.size() <= 0) {
            throw new BaseException("请下载属于本乡镇数据");
        }
        //packAddr(czrkList);
        return czrkList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importUser(List<ThirdPartInfo> thirdPartInfoList, String source) {
        if (StringUtils.isNull(thirdPartInfoList) || thirdPartInfoList.size() == 0) {
            throw new CustomException("导入数据不能为空！");
        }
        //获取上传死亡人员第三方数据remoteDictDataService
        String sourceName = remoteDictDataService.selectDictLabel("data_sources", source);
        //获取登录人员
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        try {
            for (ThirdPartInfo thirdPartInfo : thirdPartInfoList) {

                if (StringUtils.isNotEmpty(thirdPartInfo.getCremationTime())) {
                    Calendar calendar = new GregorianCalendar(1900, 0, -1);
                    Date date = calendar.getTime();
                    Date dd = DateUtils.addDays(date, Integer.valueOf(thirdPartInfo.getCremationTime()));
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                    thirdPartInfo.setCremationTime(format.format(dd));
                }

                //将ThirdPartInfo对象所有字段赋值
                //ThirdPartInfoUtils.setValue(thirdPartInfo);
                // 防止有空行，IdCard是必须要有的
                if (StringUtils.isEmpty(thirdPartInfo.getIdCard())) {
                    continue;
                }

                thirdPartInfo.setGender(IdCardUtils.getSex(thirdPartInfo.getIdCard()));
                //将信息存入ThirdPartInfo表
                thirdPartInfo.setSource(source);
                thirdPartInfo.setStatus("4");
                thirdPartInfo.setCreateBy(sysUser.getUserName());
                thirdPartInfo.setUpdateBy("第三方来源");
                thirdPartInfo.setIsDel("N");
                thirdPartInfo.setProvinceId("12");
                thirdPartInfo.setProvince("安徽省");
                thirdPartInfo.setCityId("340800000000");
                thirdPartInfo.setCity("安庆市");
                thirdPartInfo.setRegionId("340882000000");
                thirdPartInfo.setRegion("潜山市");
                thirdPartInfo.setVillageTownsId("");
                thirdPartInfo.setVillageTowns("");
                thirdPartInfo.setVillageId("");
                thirdPartInfo.setVillage("");
                //从redis中取出部门数据
                List<SysDept> allDepts = redisService.getCacheList(CacheConstants.DEPT_LIST);
                thirdPartInfo.setIsLocal("否");
                //去数据库根据人员身份证号查询人员
                Czrk czrkSjk = czrkMapper.getCzrkByIdCard(thirdPartInfo.getIdCard());
                if (ObjectUtils.isNotEmpty(czrkSjk)) {
                    //数据库存在该人员
                    czrkSjk.setStatus("4");
                    czrkSjk.setChangUser(sourceName);
                    czrkSjk.setChangNikeUser(sourceName);
                    czrkMapper.changeCzrk(czrkSjk);
                    thirdPartInfo.setIsLocal("是");
                    if (StringUtils.isNotEmpty(czrkSjk.getVillageTownsId())) {
                        thirdPartInfo.setVillageTownsId(czrkSjk.getVillageTownsId());
                    }
                    if (StringUtils.isNotEmpty(czrkSjk.getVillageTowns())) {
                        thirdPartInfo.setVillageTowns(czrkSjk.getVillageTowns());
                    }
                    if (StringUtils.isNotEmpty(czrkSjk.getVillageId())) {
                        thirdPartInfo.setVillageId(czrkSjk.getVillageId());
                    }
                    if (StringUtils.isNotEmpty(czrkSjk.getVillage())) {
                        thirdPartInfo.setVillage(czrkSjk.getVillage());
                    }
                } else {
                    //获取乡镇
                    //乡镇deptId
                    Long deptId = null;
                    if (isNotEmpty(thirdPartInfo.getTownship())) {
                        for (SysDept allDept : allDepts) {
                            if (allDept.getDeptName().equals(thirdPartInfo.getTownship() + "乡") || allDept.getDeptName().equals(thirdPartInfo.getTownship() + "镇")) {
                                thirdPartInfo.setVillageTownsId(allDept.getAreaId());
                                thirdPartInfo.setVillageTowns(allDept.getDeptName());
                                deptId = allDept.getId();
                                break;
                            }
                        }
                    }
                    //获取村
                    if (isEmpty(deptId) && isNotEmpty(thirdPartInfo.getVillageGroup()) && thirdPartInfo.getVillageGroup().contains("村")) {
                        String cun = thirdPartInfo.getVillageGroup().substring(0, thirdPartInfo.getVillageGroup().indexOf("村"));
                        for (SysDept allDept : allDepts) {
                            if (allDept.getParentId().equals(deptId) && allDept.getDeptName().contains(cun)) {
                                thirdPartInfo.setVillageId(allDept.getAreaId());
                                thirdPartInfo.setVillage(allDept.getDeptName());
                                break;
                            }
                        }
                    }
                }

            }
            thirdPartInfoMapper.insertThirdPartInfoList(thirdPartInfoList);

            return "导入成功";
        } catch (Exception e) {
            e.printStackTrace();
            return "导入失败";
        }

    }

    @Override
    public List<ThirdPartInfo> listDie(ThirdPartInfo thirdPartInfo) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}查询非正常人员人员列表，查询条件：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(thirdPartInfo));
        //设置权限
        setQueryRoleDie(thirdPartInfo, sysUser);
        long startTimeSql = System.currentTimeMillis();
        startPage();
        List<ThirdPartInfo> thirdPartInfoList = thirdPartInfoMapper.queryList(thirdPartInfo);
        long endTimeSql = System.currentTimeMillis() - startTimeSql;
        log.info("执行查询死亡人员sql语句时间:" + endTimeSql + "ms");
        return thirdPartInfoList;
    }

    @Override
    public AjaxResult delecteDie(String idCard) {
        int i = thirdPartInfoMapper.delecteDie(idCard);
        return i > 0 ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
    }

    @Override
    public AjaxResult findXsInfo(String id, String idCard) {
        Czrk czrk = new Czrk();
        czrk.setIdCard(idCard);
        Czrk hjInfo = czrkMapper.findHjInfo(czrk);
        if (hjInfo == null) {
            return AjaxResult.error("新生儿父亲或母亲不在人员信息库，请先添加父亲或母亲信息。");
        }
        //根据id查询新生儿信息
        BirthRecords birthRecords = birthRecordsMapper.getBirthRecordsInfo(id);
        hjInfo.setUserName(birthRecords.getXsexm());
        hjInfo.setIdCard(birthRecords.getSfzjhm());
        hjInfo.setHouseType("否");
        hjInfo.setYhzgx("");
        hjInfo.setWorkUnit("");
        //根据身份证提取出生日和性别,年龄
        String sex = getSex(birthRecords.getSfzjhm());
        Integer age = getAge(birthRecords.getSfzjhm());
        String birthday = IdCardUtils.getBirthday(idCard);
        hjInfo.setAge(age);
        hjInfo.setGender(sex);
        hjInfo.setBirthday(birthday);

        return AjaxResult.success("成功", hjInfo);
    }

    @Override
    public AjaxResult addBabyCzrk(Czrk czrk) {
        AjaxResult ajaxResult = insertCzrk(czrk);
        if ((int) ajaxResult.get("code") == 200) {
            //修改新生儿表状态（身份证号）
            birthRecordsMapper.updataBirthRecordsInfo(czrk.getIdCard());
        }
        return ajaxResult;
    }

    @Override
    public AjaxResult vaccineStatistics(String code,String lenth) {

        JSONObject results = new JSONObject(16);

        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        SysDept dept = sysUser.getDept();

        if(StringUtils.isEmpty(code)){
            //判断账号权限
            List<String> roleKeySets = map(sysUser.getRoles(), SysRole::getRoleKey);
            if (roleKeySets.contains("province") || roleKeySets.contains("city") || roleKeySets.contains("region") || roleKeySets.contains("admin") || roleKeySets.contains("yanshi")) {

                JSONObject jsonObject = redisService.getCacheObject("1");
                if (isNotEmpty(jsonObject)) {

                    results = jsonObject;

                }else{
                    List<SysDept> allDepts = remoteDeptService.listChildrenDepts(1L);
                    //查找户籍人口总数
                    List<Czrk> czrkList = czrkMapper.getAllCzrkRegionId("340882000000");

                    //所有乡镇集合
                    List<SysDept> townsDepts = new ArrayList<>(16);

                    for (SysDept allDept : allDepts) {
                        if (isEmpty(allDept.getParentId())) {
                            continue;
                        }
                        if (allDept.getParentId() == (1L)) {
                            townsDepts.add(allDept);
                        }
                    }

                    // 以各个镇为单位单独处理 townsDepts
                    ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                    for (SysDept townsDept : townsDepts) {
                        JSONObject townsResult = new JSONObject(16);
                        townStsvaccine(townsResult, townsDept, czrkList);
                        towsDataList.add(townsResult);
                    }

                    results.put("townDatas", towsDataList);
                    results.put("type", "1");
                }




            } else if (roleKeySets.contains("villageTowns")) {

                JSONObject jsonObject = redisService.getCacheObject(dept.getAreaId());
                if (isNotEmpty(jsonObject)) {

                    results = jsonObject;

                }else{

                    // 镇领导，只能查看本镇下人员
                    //获取本镇下所有乡村
                    List<SysDept> allDepts = remoteDeptService.listChildrenDepts(dept.getId());
                    List<SysDept> cunDepts = new ArrayList<>(16);
                    for (SysDept dep : allDepts) {
                        if (isEmpty(dep.getParentId())) continue;
                        if (dept.getId().equals(dep.getParentId())) {
                            cunDepts.add(dep);
                        }
                    }
                    //获取本镇所有人员
                    List<Czrk> czrkList = czrkMapper.getAllCzrkVillageTownsId(dept.getAreaId());


                    // 以各个镇为单位单独处理 townsDepts
                    ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                    for (SysDept townsDept : cunDepts) {
                        JSONObject townsResult = new JSONObject(16);
                        townStsvaccineCun(townsResult, townsDept, czrkList);
                        towsDataList.add(townsResult);
                    }

                    results.put("townDatas", towsDataList);
                    results.put("type", "2");
                }


            } else if (roleKeySets.contains("village")) {

                JSONObject jsonObject = redisService.getCacheObject(dept.getAreaId());
                if (isNotEmpty(jsonObject)) {

                    results = jsonObject;

                }else{
                    ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                    JSONObject townsResult = new JSONObject(16);
                    // 村领导
                    //获取本村所有人员
                    List<Czrk> czrkList = czrkMapper.getAllCzrkVillageId(dept.getAreaId());

                    //潜山市户籍人口总数
                    int hjzrs = czrkList.size();

                    //潜山市 潜山市接种疫苗人数
                    int hjymjz = 0;

                    //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                    for (Czrk czrk : czrkList) {
                        if (!"1".equals(czrk.getStatus())) {
                            hjzrs--;
                        }
                        if("Y".equals(czrk.getIsNucleicAcid())){
                            hjymjz++;
                        }

                    }
                    //镇总人数
                    townsResult.put("hjzrs", hjzrs);
                    //镇接种疫苗人数
                    townsResult.put("hjymjz", hjymjz);
                    //镇接种百分比
                    townsResult.put("hjbfb", NumberUtils.percent(hjymjz, hjzrs));

                    townsResult.put("name", dept.getDeptName());
                    towsDataList.add(townsResult);
                    results.put("townDatas", towsDataList);
                    results.put("type", "3");
                }
            }
        }else{

            JSONObject jsonObject = redisService.getCacheObject(code);
            if (isNotEmpty(jsonObject)) {

                results = jsonObject;

            }else{
                if(lenth.equals("1")){
                    // 镇领导，只能查看本镇下人员
                    //获取本镇下所有乡村
                    List<SysDept> allDept = remoteDeptService.listChildrenDepts(1L);
                    Long deptId = null;
                    for (SysDept sysDept : allDept) {
                        if(sysDept.getAreaId().equals(code)){
                            deptId = sysDept.getId();
                            break;
                        }
                    }

                    List<SysDept> depts = remoteDeptService.listChildrenDepts(deptId);

                    List<SysDept> cunDepts = new ArrayList<>(16);
                    for (SysDept dep : depts) {
                        if (isEmpty(dep.getParentId())) continue;
                        if (deptId.equals(dep.getParentId())) {
                            cunDepts.add(dep);
                        }
                    }


                    //获取本镇所有人员
                    List<Czrk> czrkList = czrkMapper.getAllCzrkVillageTownsId(code);

                    // 以各个镇为单位单独处理 townsDepts
                    ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                    for (SysDept townsDept : cunDepts) {
                        JSONObject townsResult = new JSONObject(16);
                        townStsvaccineCun(townsResult, townsDept, czrkList);
                        towsDataList.add(townsResult);
                    }

                    results.put("townDatas", towsDataList);
                    results.put("type", "2");
                }else{
                    ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                    JSONObject townsResult = new JSONObject(16);
                    String name = "";
                    // 村领导
                    //获取本村所有人员
                    List<Czrk> czrkList = czrkMapper.getAllCzrkVillageId(code);

                    //潜山市户籍人口总数
                    int hjzrs = czrkList.size();

                    //潜山市 潜山市接种疫苗人数
                    int hjymjz = 0;

                    //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                    for (Czrk czrk : czrkList) {
                        if (!"1".equals(czrk.getStatus())) {
                            hjzrs--;
                        }
                        if("Y".equals(czrk.getIsNucleicAcid())){
                            hjymjz++;
                        }

                        if(StringUtils.isEmpty(name) && StringUtils.isEmpty(czrk.getVillage())){
                            name = czrk.getVillage();
                        }

                    }
                    //镇总人数
                    townsResult.put("hjzrs", hjzrs);
                    //镇接种疫苗人数
                    townsResult.put("hjymjz", hjymjz);
                    //镇接种百分比
                    townsResult.put("hjbfb", NumberUtils.percent(hjymjz, hjzrs));

                    townsResult.put("name", name);

                    towsDataList.add(townsResult);
                    results.put("townDatas", towsDataList);
                    results.put("type", "3");
                }
            }

        }

        return AjaxResult.success("成功",results);
    }

    @Override
    public List<Czrk> exportQianShan() {
        List<Czrk> czrkList = czrkMapper.getAllCzrkNoTown();

        CzrkUtils.packAddr(czrkList);
        if (czrkList == null || czrkList.size() <= 0) {
            throw new BaseException("请下载属于本乡镇数据");
        }

        return czrkList;
    }

    @Override
    public List<Czrk> getAllCzrkHjVillage(Czrk czrk) {

        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        setQueryRole(czrk, sysUser, Czrk.HJ);


        List<Czrk> czrkList = czrkMapper.getAllCzrkHjVillage(czrk);
        CzrkUtils.packAddr(czrkList);

        return czrkList;
    }

    /**
     * 一键未认领(把未填写到村级别的户籍用户设置为未认领,根据不同镇来操作)
     * @return
     */
    @Override
    public int setNoRl() {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}一键设置未认领表"
                , sysUser.getUserName(), DateUtils.dateTimeNow() );
        Czrk czrk = new Czrk();
        CzrkUtils.setQueryRole(czrk,sysUser, Czrk.HJ);
        return  czrkMapper.setNoRl(czrk);
    }


    private void townStsvaccine(JSONObject result, SysDept sysDept, List<Czrk> czrkList) {
        String deptName = sysDept.getDeptName();
        String areaId = sysDept.getAreaId();

        if (czrkList == null) {
            czrkList = new ArrayList<>();
        }

        //该镇户籍人口总数
        int hjzrs = 0;

        //该镇 接种人员数据
        int hjymjz = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (Czrk czrk : czrkList) {
            if (StringUtils.isNotEmpty(czrk.getVillageTownsId()) && String.valueOf(czrk.getVillageTownsId()).equals(areaId)) {
                if ("1".equals(czrk.getStatus())) {
                    hjzrs++;
                }

                if("Y".equals(czrk.getIsNucleicAcid())){
                    hjymjz++;
                }
            }
        }
        result.put("hjzrs", hjzrs);
        result.put("hjymjz", hjymjz);
        result.put("hjbfb", NumberUtils.percent(hjymjz, hjzrs));
        result.put("name", deptName);
    }

    private void townStsvaccineCun(JSONObject result, SysDept sysDept, List<Czrk> czrkList) {
        Long deptId = sysDept.getId();
        String deptName = sysDept.getDeptName();
        String areaId = sysDept.getAreaId();


        if (czrkList == null) {
            czrkList = new ArrayList<>();
        }

        //该村户籍人口总数
        int hjzrs = 0;

        //该村接种人员数据
        int hjymjz = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (Czrk czrk : czrkList) {
            if (StringUtils.isNotEmpty(czrk.getVillageId()) && String.valueOf(czrk.getVillageId()).equals(areaId)) {
                if ("1".equals(czrk.getStatus())) {
                    hjzrs++;
                }

                if("Y".equals(czrk.getIsNucleicAcid())){
                    hjymjz++;
                }
            }
        }
        result.put("hjzrs", hjzrs);
        result.put("hjymjz", hjymjz);
        result.put("hjbfb", NumberUtils.percent(hjymjz, hjzrs));
        result.put("name", deptName);
    }
    @Override
    public Czrk getById(Long id) {
        if (isEmpty(id)) {
            return null;
        }

        Czrk czrk = czrkMapper.selectCzrkById(id);
        if (null == czrk) {
            return null;
        }

        //获取网格id
        /*Long gridId = czrk.getGridId();
        if (gridId != null) {
            GridInfo gridInfo = gridInfoMapper.selectGridInfoById(gridId);
            if (gridInfo != null) {
                String areaName = gridInfo.getAreaName();
                czrk.setGridName(areaName);
            }
        }*/

        // 拿到户主的姓名和身份证号
        Czrk hzCzrk = czrkMapper.getHzByCode(czrk.getCode());
        if (hzCzrk != null) {
            czrk.setHzName(hzCzrk.getUserName());
            czrk.setHzIdCard(hzCzrk.getIdCard());
        }

        //查询改用户居住地址信息
        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.listByCzrkId(czrk.getId());
        czrk.setCzrkJzdzList(czrkJzdzList);
        // 重新计算年龄
        String birthday = czrk.getBirthday();
        if (StringUtils.isNotBlank(birthday)) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            int age = czrk.getAge();
            try {
                age = DateUtils.getAge(sdf.parse(birthday));
            } catch (Exception e) {
                e.printStackTrace();
            }
            czrk.setAge(age);
        }
        return czrk;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public AjaxResult addRlry(Czrk czrk) {
        List<CzrkJzdz> czrkJzdzList = czrk.getCzrkJzdzList();
        if (isEmpty(czrkJzdzList)) return AjaxResult.error("该人员常住地址未添加");
        //一开始就判断是否是户籍和所有居住地址都不在对应辖区
        String region = czrk.getRegion();
        if (StringUtils.isNotBlank(region) && !"潜山市".equals(region)) {
            boolean flag = true;
            for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                String regionJzdz = czrkJzdz.getRegion();
                if (StringUtils.isNotBlank(regionJzdz) && "潜山市".equals(regionJzdz)) {
                    flag = false;
                }
            }
            if (flag) {
                return AjaxResult.error(HttpStatus.NOT_IMPLEMENTED, "当前填写的户籍地址和居住地址均不属于对应辖区");
            }
        }

        // 看是否是户主,且有户主号需要去查看该家庭是否有户主
        String houseType = czrk.getHouseType();
        String code = czrk.getCode();
        if ("是".equals(houseType) && StringUtils.isNotBlank(code)) {
            Czrk czrk1 = czrkMapper.selectCzrkByCode(code);
            if (czrk1 != null && StringUtils.isNotBlank(czrk1.getIdCard())) {
                return AjaxResult.error("该户编号已存在户主,请勿重复添加户主");
            }
        }
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        String username = sysUser.getUserName();
        //用户姓名
        String nickName = sysUser.getNickName();
        if (isNotEmpty(czrk.getVillageTowns())) {
            czrk.setRlrNike(nickName);
            czrk.setRlr(username);
            czrk.setIsRl("是");
            czrk.setRlTime(new Date(System.currentTimeMillis()));
        } else {
            czrk.setIsRl("否");
            czrk.setRlTime(null);
        }

        // 当前登陆人的dept_id
        czrk.setDeptId(sysUser.getDeptId());
        int count = czrkMapper.countIdCard(czrk.getIdCard());
        if (count > 0) return AjaxResult.error(String.format("该人员[身份证号为: %s]已存在，请勿重复添加", czrk.getIdCard()));

        czrk.setCreateBy(username);
        czrk.setUpdateBy(username);

        count = czrkMapper.insertCzrk(czrk);
        if (count < 1) return AjaxResult.error("新增户籍信息失败");
        int sort = 0, childCount = 0;
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            czrkJzdz.setCzrkId(czrk.getId());
            czrkJzdz.setSort(++sort);
            czrkJzdz.setUserName(czrk.getUserName());
            czrkJzdz.setIdCard(czrk.getIdCard());
            czrkJzdz.setCreateBy(username);
            czrkJzdz.setUpdateBy(username);
            // 当前登陆人的所属最后一级的dept_id
            czrkJzdz.setDeptId(sysUser.getDeptId());
            childCount += czrkJzdzService.insertCzrkJzdz(czrkJzdz);

        }
        return childCount > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 功能描述: 人员认领菜单中认领接口
     *
     * @param czrk
     * @return
     */
    @Override
    public AjaxResult editRlry(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}人员认领：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        List<CzrkJzdz> czrkJzdzList = czrk.getCzrkJzdzList();
        if (isEmpty(czrkJzdzList)) return AjaxResult.error("该人员常住地址未添加");
        //一开始就判断是否是户籍和所有居住地址是否都不在权限之下
        if (setInsertRole(czrk, sysUser)) {
            return AjaxResult.error(HttpStatus.NOT_IMPLEMENTED, "当前填写的户籍地址和居住地址均不属于权限范围,请先修改后认领");
        }
        //看是否是户主,且有户主号需要去查看该家庭是否有户主
        String houseType = czrk.getHouseType();
        String code = czrk.getCode();
        if ("是".equals(houseType) && StringUtils.isNotBlank(code)) {
            Czrk czrkCode = czrkMapper.selectCzrkByCode(code);
            if (czrkCode != null && !czrkCode.getIdCard().equals(czrk.getIdCard())) {
                return AjaxResult.error("该户编号已存在户主,请勿重复添加户主");
            }
        }
        // 获取当前的用户手机号
        String username = sysUser.getUserName();
        //用户姓名
        String nickName = sysUser.getNickName();
        czrk.setRlrNike(nickName);
        czrk.setRlr(username);
        czrk.setIsRl("是");
        czrk.setDeptId(sysUser.getDeptId());
        czrk.setRlTime(DateUtils.getNowDate());
        czrk.setStatus("1");
        int count = czrkMapper.updateCzrk(czrk);
        if (count <= 0) return AjaxResult.error();
        czrkJzdzService.deleteByCzrkId(czrk.getId());
        int sort = 0, childCount = 0;
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            czrkJzdz.setCzrkId(czrk.getId());
            czrkJzdz.setSort(++sort);
            czrkJzdz.setUserName(czrk.getUserName());
            czrkJzdz.setIdCard(czrk.getIdCard());
            czrkJzdz.setCreateBy(username);
            childCount += czrkJzdzService.insertCzrkJzdz(czrkJzdz);
        }

        if (czrkJzdzList.size() > 0) {
            addExtracted(czrk, czrkJzdzList);
        }

        return childCount == czrkJzdzList.size() ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * 2022/3/25修改小程序接口统计认领人员
     *
     * @param czrk
     * @return
     */
    @Override
    public JSONObject stsByApplet(Czrk czrk) {
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        log.info("{}于{}人员认领：{}"
                , sysUser.getUserName(), DateUtils.dateTimeNow(), JSON.toJSONString(czrk));
        String queryType = czrk.getQueryType();
        long total = 0, yrl = 0, wrl = 0;
        //搜索常住人口全部未认领人员需要在设置权限之前
        long startTimeSql = System.currentTimeMillis();
        wrl = czrkMapper.stsByWrl(czrk);
        long endTimeSql = System.currentTimeMillis() - startTimeSql;
        log.info("执行查询未认领sql语句时间:" + endTimeSql + "ms");

        //设置查询权限
        setQueryRole(czrk, sysUser, queryType);
        if (Czrk.HJ.equals(queryType)) {
            //获取到居住地的查询条件
            String provinceId = czrk.getProvinceIdXjd();
            String cityId = czrk.getCityIdXjd();
            String regionId = czrk.getRegionIdXjd();
            String villageTownsId = czrk.getVillageTownsIdXjd();
            String villageId = czrk.getVillageIdXjd();
            //如果查询参数有居住地址,进行连表查询
            if (StringUtils.isNotBlank(provinceId) || StringUtils.isNotBlank(cityId) || StringUtils.isNotBlank(regionId) || StringUtils.isNotBlank(villageTownsId) || StringUtils.isNotBlank(villageId)) {
                long startTimeSql1 = System.currentTimeMillis();
                total = czrkMapper.selectCzrkJzdzCount(czrk);
                long endTimeSql1 = System.currentTimeMillis() - startTimeSql1;
                log.info("sts执行查询所有带居住条件户籍人员sql语句时间:" + endTimeSql1 + "ms");
                czrk.setIsRl("是");
                long startTimeSql2 = System.currentTimeMillis();
                yrl = czrkMapper.selectCzrkJzdzCount(czrk);
                long endTimeSql2 = System.currentTimeMillis() - startTimeSql2;
                log.info("sts执行查询所有带居住条件户籍人员已认领的sql语句时间:" + endTimeSql2 + "ms");
            } else {
                //没有搜索居住地址的条件,进行单表查询
                long startTimeSql1 = System.currentTimeMillis();
                total = czrkMapper.selectCzrkCount(czrk);
                long endTimeSql1 = System.currentTimeMillis() - startTimeSql1;
                log.info("sts执行查询所有户籍人员sql语句时间:" + endTimeSql1 + "ms");
                czrk.setIsRl("是");
                long startTimeSql2 = System.currentTimeMillis();
                yrl = czrkMapper.selectCzrkCount(czrk);
                long endTimeSql2 = System.currentTimeMillis() - startTimeSql2;
                log.info("sts执行查询所有户籍人员已认领的sql语句时间:" + endTimeSql2 + "ms");
            }
        } else {
            //常住人口全部人员
            total = czrkMapper.stsByAll(czrk);
            //常住人口已认领
            yrl = czrkMapper.stsByYrl(czrk);
        }
        JSONObject result = new JSONObject(3);
        result.put("yrl", yrl);
        result.put("wrl", wrl);
        result.put("total", total);
        return result;
    }

    /**
     * 功能描述: 当前单位：镇，村：7个，组：300个，常住人口：5000人，新增 2人  减少 2人
     *
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject stsByCzrk() {
        JSONObject result = new JSONObject(16);
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();

        Long deptId = sysUser.getDeptId(); // 当前登陆人的deptId
        result.put("dqdw", sysUser.getDept().getDeptName());  // 当前单位

        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();

        // 市领导
        List<String> roleKeySets = map(sysUser.getRoles(), SysRole::getRoleKey);
        if (roleKeySets.contains("province") || roleKeySets.contains("city") || roleKeySets.contains("region") || roleKeySets.contains("admin") || roleKeySets.contains("yanshi")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey(deptId + ""));
            if (isNotEmpty(jsonObject)) {
                QIANSHANSHI_SINGEL = jsonObject;
                return jsonObject;
            }

            /*ThreadPoolService.execute(() -> {
                System.out.println("我进来了");
                //Long areaId = 340882000000L;
                //todo 固定写了潜山市
                List<SysDept> allDepts = remoteDeptService.listChildrenDepts(deptId);
                List<SysDept> townsDepts = new ArrayList<>(16);
                for (SysDept allDept : allDepts) {
                    if (isEmpty(allDept.getParentId())) continue;
                    //todo 固定判断是潜山市
                    if (allDept.getParentId().equals(deptId)) {
                        townsDepts.add(allDept);
                    }
                }
                result.put("zhen", townsDepts.size()); // 镇

                List<SysDept> cunDepts = new ArrayList<>(16);
                for (SysDept townsDept : townsDepts) {
                    for (SysDept allDept : allDepts) {
                        if (isEmpty(allDept.getParentId())) continue;
                        if (townsDept.getId().equals(allDept.getParentId())) {
                            cunDepts.add(allDept);
                        }
                    }
                }
                result.put("cun", isEmpty(cunDepts) ? 0 : cunDepts.size()); //村
//
                List<SysDept> zuDept = new ArrayList<>(16);
                for (SysDept cunDept : cunDepts) {
                    for (SysDept allDept : allDepts) {
                        if (cunDept.getId().equals(allDept.getParentId())) {
                            zuDept.add(allDept);
                        }
                    }
                }

                result.put("zu", isEmpty(zuDept) ? 0 : zuDept.size()); // 组

                List<Long> deptIdList = new ArrayList<>();

                // ======== 新增部门判断开始========
                //todo  新增的部分
                //判断是否是管理员
                List<SysRole> roles = AuthUtils.getLoginUser().getSysUser().getRoles();
                boolean flag = true;
                if (isNotEmpty(roles)) {
                    for (SysRole role : roles) {
                        String roleKey = role.getRoleKey();
                        if ("admin".equals(roleKey) || "city".equals(roleKey) || "yanshi".equals(roleKey)) {
                            flag = false;
                        }
                    }
                }
                if (deptId != null && flag){
                    //设置查询列表权限
                    List<SysDept> sysDepts = remoteDeptService.listChildrenDepts(deptId);
                    if (isNotEmpty(sysDepts)) {
                        deptIdList = map(sysDepts, SysDept::getId);
                    }
                }

                // ======== 新增部门判断结束========

                int zrs = czrkMapper.countAll(); // 总人数
                int hjzrs = czrkMapper.countHj1(deptIdList); // 该镇户籍人口总数
                result.put("hjzrs", hjzrs);
                int hjxz = czrkMapper.countByHjXz1(startTime, endTime, deptIdList); // 该镇 户籍人口今日新增
                result.put("hjxz", hjxz);
                int hjjs = czrkMapper.countByHjJs1(startTime, endTime, deptIdList); // 该镇 户籍人口今日减少
                result.put("hjjs", hjjs);
                result.put("hjbfb", NumberUtils.percent(hjzrs, zrs));

                int czzrs = czrkMapper.countCz1(deptIdList);  // 该镇常住人口总数
                result.put("czzrs", czzrs);
                int czxz = czrkMapper.countByCzXz1(startTime, endTime, deptIdList); // 该镇 常住人口今日新增
                int czjs = czrkMapper.countByCzJs1(startTime, endTime, deptIdList); // 该镇 常住人口今日减少
                result.put("czxz", czxz);
                result.put("czjs", czjs);
                result.put("czbfb", NumberUtils.percent(czzrs, zrs));
                setIntoRedis(packRedisKey("single:" + deptId), result);
                QIANSHANSHI_SINGEL = result;
                System.out.println("我出去了");
            });

            return QIANSHANSHI_SINGEL;*/
        } else if (roleKeySets.contains("villageTowns")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey("town:" + deptId));
            if (isNotEmpty(jsonObject)) {
                return jsonObject;
            }

            //townSts(result, deptId, sysUser.getDept().getDeptName(), true);
//            redisService.setCacheObject(packRedisKey("town:" + deptId), result, 1L, TimeUnit.DAYS);
            //setIntoRedis(packRedisKey("town:" + deptId), result);
        } else if (roleKeySets.contains("village")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey("village:" + deptId));
            if (isNotEmpty(jsonObject)) {
                CUN = jsonObject;
                return jsonObject;
            }
        }

        //System.out.println("我最后出去了");
        return result;
    }

    /**
     * 功能描述: 项目首页统计信息，
     * 当前单位：镇，村：7个，组：300个，常住人口：5000人，新增 2人  减少 2人
     *
     * @return com.boman.domain.dto.AjaxResult
     */
    @Override
    public JSONObject stsByCzrkHomePage() {
        JSONObject result = new JSONObject(16);
        // 当前登陆人的deptId
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        String deptName = sysUser.getDept().getDeptName();
        result.put("dqdw", deptName); // 当前单位

        List<String> roleKeySets = map(sysUser.getRoles(), SysRole::getRoleKey);

        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();

        Timestamp s = Timestamp.valueOf(startTime);
        Timestamp e = Timestamp.valueOf(endTime);
        Long deptId = sysUser.getDeptId();

        // 市领导 todo 此处不应该写死
        if (roleKeySets.contains("province") || roleKeySets.contains("city") || roleKeySets.contains("region") || roleKeySets.contains("admin") || roleKeySets.contains("yanshi")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey(deptId + ""));
            if (isNotEmpty(jsonObject)) {
                QIANSHANSHI = jsonObject;
                return jsonObject;
            }

            ThreadPoolService.execute(() -> {
                //潜山市
                List<SysDept> allDepts = remoteDeptService.listChildrenDepts(1L);
                List<SysDept> townsDepts = new ArrayList<>(16);
                for (SysDept allDept : allDepts) {
                    if (isEmpty(allDept.getParentId())) continue;
                    if (allDept.getParentId() == (1L)) {
                        townsDepts.add(allDept);
                    }
                }
                result.put("zhen", townsDepts.size()); // 镇的数量

                List<SysDept> cunDepts = new ArrayList<>(16);
                for (SysDept townsDept : townsDepts) {
                    for (SysDept allDept : allDepts) {
                        if (isEmpty(allDept.getParentId())) continue;
                        if (townsDept.getId().equals(allDept.getParentId())) {
                            cunDepts.add(allDept);
                        }
                    }
                }
                result.put("cun", isEmpty(cunDepts) ? 0 : cunDepts.size());

                //查找潜山市户籍人口总数
                List<Czrk> czrkList = czrkMapper.getAllCzrkRegionId("340882000000");
                if (czrkList == null) {
                    czrkList = new ArrayList<>();
                }
                //潜山市户籍人口总数
                int hjzrs = czrkList.size();

                //潜山市 户籍人口今日新增
                int hjxz = 0;
                //潜山市 户籍人口今日减少
                int hjjs = 0;

                //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                for (Czrk czrk : czrkList) {
                    if (!"1".equals(czrk.getStatus())) {
                        hjzrs--;
                    }
                    //判断是否是在今天操作的人员信息
                    if (s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                        if (!"1".equals(czrk.getStatus())) {
                            hjjs++;
                        } else {
                            hjxz++;
                        }
                    }
                }
                //潜山市总人数
                result.put("hjzrs", hjzrs);
                //潜山市新增
                result.put("hjxz", hjxz);
                //潜山市减少
                result.put("hjjs", hjjs);
                result.put("hjbfb", NumberUtils.percent(hjzrs, hjzrs));


                //查找潜山市常驻人口信息
                List<CzrkJzdz> czrkJzdzList = czrkJzdzService.selectCzrkJzdzListByRegionId("340882000000");
                if (czrkJzdzList == null) {
                    czrkJzdzList = new ArrayList<>();
                }
                //潜山市居住人口总数
                int czzrs = czrkJzdzList.size();

                //潜山市居住人口今日新增
                int czxz = 0;
                //潜山市居住人口今日减少
                int czjs = 0;

                //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                    if ("N".equals(czrkJzdz.getStatus())) {
                        czzrs--;
                    }
                    //判断是否是在今天操作的人员信息
                    if (s.before(czrkJzdz.getUpdateTime()) && czrkJzdz.getUpdateTime().before(e)) {
                        if ("N".equals(czrkJzdz.getStatus())) {
                            czjs++;
                        } else {
                            czxz++;
                        }
                    }
                }
                //潜山市总人数
                result.put("czzrs", czzrs);
                //潜山市新增
                result.put("czxz", czxz);
                //潜山市减少
                result.put("czjs", czjs);
                result.put("czbfb", NumberUtils.percent(czzrs, czzrs));

                /*List<Long> deptIdList = null;
                int zrs = czrkMapper.countAll(); // 总人数
                int hjzrs = czrkMapper.countHj1(deptIdList); // 该镇户籍人口总数
                result.put("hjzrs", hjzrs);
                int hjxz = czrkMapper.countByHjXz1(startTime, endTime, deptIdList); // 该镇 户籍人口今日新增
                result.put("hjxz", hjxz);
                int hjjs = czrkMapper.countByHjJs1(startTime, endTime, deptIdList); // 该镇 户籍人口今日减少
                result.put("hjjs", hjjs);
                result.put("hjbfb", NumberUtils.percent(hjzrs, zrs));

                int czzrs = czrkMapper.countCz1(deptIdList);  // 该镇常住人口总数
                result.put("czzrs", czzrs);
                int czxz = czrkMapper.countByCzXz1(startTime, endTime, deptIdList); // 该镇 常住人口今日新增
                int czjs = czrkMapper.countByCzJs1(startTime, endTime, deptIdList); // 该镇 常住人口今日减少
                result.put("czxz", czxz);
                result.put("czjs", czjs);
                result.put("czbfb", NumberUtils.percent(czzrs, zrs));*/

                // 以各个镇为单位单独处理 townsDepts
                ArrayList<JSONObject> towsDataList = new ArrayList<>(20);
                for (SysDept townsDept : townsDepts) {
                    JSONObject townsResult = new JSONObject(16);
                    ///townSts(townsResult, townsDept.getId(), townsDept.getDeptName(), false);
                    townSts(townsResult, townsDept, czrkList, czrkJzdzList, hjzrs, czzrs);
                    towsDataList.add(townsResult);
                }

                result.put("townDatas", towsDataList);
//                redisService.setCacheObject(packRedisKey(deptId + ""), result, 1L, TimeUnit.DAYS);
                setIntoRedis(packRedisKey(deptId + ""), result);
                QIANSHANSHI = result;
            });

            return QIANSHANSHI;
        } else if (roleKeySets.contains("villageTowns")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey("town:" + deptId));
            if (isNotEmpty(jsonObject)) {
                ZHEN = jsonObject;
                return jsonObject;
            }

            ThreadPoolService.execute(() -> {

                //查找潜山市户籍人口总数
                List<Czrk> czrkList = czrkMapper.getAllCzrkRegionId("340882000000");
                if (czrkList == null) {
                    czrkList = new ArrayList<>();
                }
                //潜山市户籍人口总数
                int hjzrs = czrkList.size();
                //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                for (Czrk czrk : czrkList) {
                    if ("Y".equals(czrk.getIsDel())) {
                        hjzrs--;
                    }
                }
                //查找潜山市常驻人口信息
                List<CzrkJzdz> czrkJzdzList = czrkJzdzService.selectCzrkJzdzListByRegionId("340882000000");
                if (czrkJzdzList == null) {
                    czrkJzdzList = new ArrayList<>();
                }
                //潜山市居住人口总数
                int czzrs = czrkJzdzList.size();
                //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
                for (CzrkJzdz czrkJzdz : czrkJzdzList) {
                    if ("N".equals(czrkJzdz.getStatus())) {
                        czzrs--;
                    }
                }


                townSts(result, sysUser.getDept(), czrkList, czrkJzdzList, hjzrs, czzrs);
//                redisService.setCacheObject(packRedisKey("town:" + deptId), result, 1L, TimeUnit.DAYS);
                setIntoRedis(packRedisKey("town:" + deptId), result);
            });

            return ZHEN;
        } else if (roleKeySets.contains("village")) {
            JSONObject jsonObject = redisService.getCacheObject(packRedisKey("village:" + deptId));
            if (isNotEmpty(jsonObject)) {
                CUN = jsonObject;
                return jsonObject;
            }

            ThreadPoolService.execute(() -> {
                String areaId = sysUser.getDept().getAreaId();


                List<SysDept> depts = remoteDeptService.listChildrenDepts(deptId);
                result.put("dqdw", deptName);

                List<Long> deptIdList = map(depts, SysDept::getId);
                int zrs = czrkMapper.countAll(); // 总人数
                int hjzrs = czrkMapper.countHj1(deptIdList); // 该镇户籍人口总数
                result.put("hjzrs", hjzrs);
                int hjxz = czrkMapper.countByHjXz1(startTime, endTime, deptIdList); // 该镇 户籍人口今日新增
                result.put("hjxz", hjxz);
                int hjjs = czrkMapper.countByHjJs1(startTime, endTime, deptIdList); // 该镇 户籍人口今日减少
                result.put("hjjs", hjjs);
                result.put("hjbfb", NumberUtils.percent(hjzrs, zrs));

                int czzrs = czrkMapper.countCz1(deptIdList);  // 该镇常住人口总数
                result.put("czzrs", czzrs);
                int czxz = czrkMapper.countByCzXz1(startTime, endTime, deptIdList); // 该镇 常住人口今日新增
                int czjs = czrkMapper.countByCzJs1(startTime, endTime, deptIdList); // 该镇 常住人口今日减少
                result.put("czxz", czxz);
                result.put("czjs", czjs);
                result.put("czbfb", NumberUtils.percent(czzrs, zrs));
                setIntoRedis(packRedisKey("village:" + deptId), result);
            });

            return CUN;
        }

        return result;
    }

    private void townSts(JSONObject result, SysDept sysDept, List<Czrk> czrkList, List<CzrkJzdz> czrkJzdzList, int shjzrs, int sczzrs) {
        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();
        Timestamp s = Timestamp.valueOf(startTime);
        Timestamp e = Timestamp.valueOf(endTime);
        Long deptId = sysDept.getId();
        String deptName = sysDept.getDeptName();
        String areaId = sysDept.getAreaId();
        // 乡镇以下的所有部门
        List<SysDept> depts = remoteDeptService.listChildrenDepts(deptId);
        List<SysDept> cunDepts = new ArrayList<>(16);
        for (SysDept dept : depts) {
            if (isEmpty(dept.getParentId())) continue;
            if (deptId.equals(dept.getParentId())) {
                cunDepts.add(dept);
            }
        }
        result.put("cun", isEmpty(cunDepts) ? 0 : cunDepts.size());

        List<SysDept> zuDept = new ArrayList<>(16);
        for (SysDept cunDept : cunDepts) {
            for (SysDept dept : depts) {
                if (cunDept.getId().equals(dept.getParentId())) {
                    zuDept.add(dept);
                }
            }
        }

        result.put("zu", isEmpty(zuDept) ? 0 : zuDept.size());

        /** **/
        /*int zrs = 0; // 总人数
        if (BooleanUtils.isTrue(percent)) {
            zrs = czrkMapper.countAll();
        }*/

        if (czrkList == null) {
            czrkList = new ArrayList<>();
        }
        //该镇户籍人口总数
        int hjzrs = 0;

        //该镇 户籍人口今日新增
        int hjxz = 0;
        //该镇 户籍人口今日减少
        int hjjs = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (Czrk czrk : czrkList) {
            if (StringUtils.isNotEmpty(czrk.getVillageTownsId()) && String.valueOf(czrk.getVillageTownsId()).equals(areaId)) {
                if ("1".equals(czrk.getStatus())) {
                    hjzrs++;
                }
                //判断是否是在今天操作的人员信息
                if (s.before(czrk.getUpdateTime()) && czrk.getUpdateTime().before(e)) {
                    if (!"1".equals(czrk.getStatus())) {
                        hjjs++;
                    } else {
                        hjxz++;
                    }
                }
            }
        }
        result.put("hjzrs", hjzrs);
        result.put("hjxz", hjxz);
        result.put("hjjs", hjjs);
        result.put("hjbfb", NumberUtils.percent(hjzrs, shjzrs));


        if (czrkJzdzList == null) {
            czrkJzdzList = new ArrayList<>();
        }
        //该镇户籍人口总数
        int czzrs = 0;

        //该镇 户籍人口今日新增
        int czxz = 0;
        //该镇 户籍人口今日减少
        int czjs = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            if (StringUtils.isNotEmpty(czrkJzdz.getTownId()) && czrkJzdz.getTownId().equals(areaId)) {
                if ("Y".equals(czrkJzdz.getStatus())) {
                    czzrs++;
                }
                //判断是否是在今天操作的人员信息
                if (s.before(czrkJzdz.getUpdateTime()) && czrkJzdz.getUpdateTime().before(e)) {
                    if ("N".equals(czrkJzdz.getStatus())) {
                        czjs++;
                    } else {
                        czxz++;
                    }
                }
            }

        }
        result.put("czzrs", czzrs);
        result.put("czxz", czxz);
        result.put("czjs", czjs);
        result.put("czbfb", NumberUtils.percent(czzrs, sczzrs));

        /*int czzrs = czrkMapper.countCz1(deptIdList);  // 该镇常住人口总数
        result.put("czzrs", czzrs);
        int czxz = czrkMapper.countByCzXz1(startTime, endTime, deptIdList); // 该镇 常住人口今日新增
        int czjs = czrkMapper.countByCzJs1(startTime, endTime, deptIdList); // 该镇 常住人口今日减少
        result.put("czxz", czxz);
        result.put("czjs", czjs);
        result.put("czbfb", NumberUtils.percent(czzrs, zrs));*/

        result.put("zhen", deptName);
        /** **/


        // 常住人口信息
//        int type = 4; // 乡镇
//        int czzrs = czrkMapper.countCzrk(type, areaId); // 常住人口
//        result.put("czzrs", czzrs);
//
//        int zrs = 0;
//        // 常住人口占总人口的百分比
//        if (BooleanUtils.isTrue(percent)) {
//             // 查全部
//            zrs = czrkMapper.countCzrk(type, areaId);
//            String czbfb = NumberUtils.percent(czzrs, zrs);
//            result.put("czbfb", czbfb);
//        }
//
////        type = 4;
//        int czxz = czrkMapper.countByCzXz(startTime, endTime, type, areaId);
//        int czjs = czrkMapper.countByCzJs(startTime, endTime, type, areaId);
//        result.put("czxz", czxz);
//        result.put("czjs", czjs);
//
//        result.put("zhen", deptName);
//
//        // 户籍人口信息
//        int hjxz = czrkMapper.countByHjXz(startTime, endTime, type, areaId); // 新增
//        int hjjs = czrkMapper.countByHjJs(startTime, endTime, type, areaId);// 减少
//        result.put("hjxz", hjxz);
//        result.put("hjjs", hjjs);
//
//        // 户籍总人数
//        int hjzrs = czrkMapper.countHj(startTime, endTime, type, areaId);
////                int hjzrs= isEmpty(hjzrsList) ? 0 : hjzrsList.size();
//        result.put("hjzrs", hjzrs);
//        String hjbfb = NumberUtils.percent(hjzrs, zrs);
//        result.put("hjbfb", hjbfb);
    }

    /*private void townSts(JSONObject result, Long deptId, String deptName, boolean percent) {
        String startTime = DateUtils.getTodayStartStr();
        String endTime = DateUtils.getTodayEndStr();
        Timestamp s = Timestamp.valueOf(startTime);
        Timestamp e = Timestamp.valueOf(endTime);
        // 乡镇以下的所有部门
        List<SysDept> depts = remoteDeptService.listChildrenDepts(deptId);
        List<SysDept> cunDepts = new ArrayList<>(16);
        for (SysDept dept : depts) {
            if (isEmpty(dept.getParentId())) continue;
            if (deptId.equals(dept.getParentId())) {
                cunDepts.add(dept);
            }
        }
        result.put("cun", isEmpty(cunDepts) ? 0 : cunDepts.size());

        List<SysDept> zuDept = new ArrayList<>(16);
        for (SysDept cunDept : cunDepts) {
            for (SysDept dept : depts) {
                if (cunDept.getId().equals(dept.getParentId())) {
                    zuDept.add(dept);
                }
            }
        }

        result.put("zu", isEmpty(zuDept) ? 0 : zuDept.size());

        *//** **//*
        int zrs = 0; // 总人数
        if (BooleanUtils.isTrue(percent)) {
            zrs = czrkMapper.countAll();
        }

        List<Long> deptIdList = map(depts, SysDept::getId);
        //查询当前乡镇下的户籍总人数
        List<Czrk> czrkList = czrkMapper.selectCzrkListByDeptId(deptIdList);
        if (czrkList == null) {
            czrkList = new ArrayList<>();
        }
        //该镇户籍人口总数
        int hjzrs = czrkList.size();

        //该镇 户籍人口今日新增
        int hjxz = 0;
        //该镇 户籍人口今日减少
        int hjjs = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (Czrk czrk : czrkList) {
            if ("Y".equals(czrk.getIsDel())) {
                hjzrs--;
            }
            //判断是否是在今天操作的人员信息
            if (s.before(czrk.getCreateTime()) && czrk.getCreateTime().before(e)) {
                if ("Y".equals(czrk.getIsDel())) {
                    hjjs++;
                } else {
                    hjxz++;
                }
            }
        }
        result.put("hjzrs", czrkList.size());
        result.put("hjxz", hjxz);
        result.put("hjjs", hjjs);
        result.put("hjbfb", NumberUtils.percent(hjzrs, zrs));

        *//*List<Long> deptIdList = map(depts, SysDept::getId);
        int hjzrs = czrkMapper.countHj1(deptIdList); // 该镇户籍人口总数
        result.put("hjzrs", hjzrs);
        int hjxz = czrkMapper.countByHjXz1(startTime, endTime, deptIdList); // 该镇 户籍人口今日新增
        result.put("hjxz", hjxz);
        int hjjs = czrkMapper.countByHjJs1(startTime, endTime, deptIdList); // 该镇 户籍人口今日减少
        result.put("hjjs", hjjs);
        result.put("hjbfb", NumberUtils.percent(hjzrs, zrs));*//*


        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.selectCzrkJzdzListByDeptId(deptIdList);
        if (czrkJzdzList == null) {
            czrkJzdzList = new ArrayList<>();
        }
        //该镇户籍人口总数
        int czzrs = czrkJzdzList.size();

        //该镇 户籍人口今日新增
        int czxz = 0;
        //该镇 户籍人口今日减少
        int czjs = 0;

        //循环所有人判断当前总人数，该镇 户籍人口今日新增，该镇 户籍人口今日减少
        for (CzrkJzdz czrkJzdz : czrkJzdzList) {
            if ("Y".equals(czrkJzdz.getStatus())) {
                czzrs--;
            }
            //判断是否是在今天操作的人员信息
            if (s.before(czrkJzdz.getCreateTime()) && czrkJzdz.getCreateTime().before(e)) {
                if ("Y".equals(czrkJzdz.getStatus())) {
                    czjs++;
                } else {
                    czxz++;
                }
            }
        }
        result.put("czzrs", czzrs);
        result.put("czxz", czxz);
        result.put("czjs", czjs);
        result.put("czbfb", NumberUtils.percent(czzrs, zrs));

        *//*int czzrs = czrkMapper.countCz1(deptIdList);  // 该镇常住人口总数
        result.put("czzrs", czzrs);
        int czxz = czrkMapper.countByCzXz1(startTime, endTime, deptIdList); // 该镇 常住人口今日新增
        int czjs = czrkMapper.countByCzJs1(startTime, endTime, deptIdList); // 该镇 常住人口今日减少
        result.put("czxz", czxz);
        result.put("czjs", czjs);
        result.put("czbfb", NumberUtils.percent(czzrs, zrs));*//*

        result.put("zhen", deptName);
        */

    /**
     *
     **//*


        // 常住人口信息
//        int type = 4; // 乡镇
//        int czzrs = czrkMapper.countCzrk(type, areaId); // 常住人口
//        result.put("czzrs", czzrs);
//
//        int zrs = 0;
//        // 常住人口占总人口的百分比
//        if (BooleanUtils.isTrue(percent)) {
//             // 查全部
//            zrs = czrkMapper.countCzrk(type, areaId);
//            String czbfb = NumberUtils.percent(czzrs, zrs);
//            result.put("czbfb", czbfb);
//        }
//
////        type = 4;
//        int czxz = czrkMapper.countByCzXz(startTime, endTime, type, areaId);
//        int czjs = czrkMapper.countByCzJs(startTime, endTime, type, areaId);
//        result.put("czxz", czxz);
//        result.put("czjs", czjs);
//
//        result.put("zhen", deptName);
//
//        // 户籍人口信息
//        int hjxz = czrkMapper.countByHjXz(startTime, endTime, type, areaId); // 新增
//        int hjjs = czrkMapper.countByHjJs(startTime, endTime, type, areaId);// 减少
//        result.put("hjxz", hjxz);
//        result.put("hjjs", hjjs);
//
//        // 户籍总人数
//        int hjzrs = czrkMapper.countHj(startTime, endTime, type, areaId);
////                int hjzrs= isEmpty(hjzrsList) ? 0 : hjzrsList.size();
//        result.put("hjzrs", hjzrs);
//        String hjbfb = NumberUtils.percent(hjzrs, zrs);
//        result.put("hjbfb", hjbfb);
    }*/
    @Override
    public JSONObject hjczLine() {
        JSONObject resultData = new JSONObject(5);
        // 统计范围 从今天往前推7天
        java.util.Date startTimeDate = DateUtils.getNowDate();
        java.util.Date endTimeDate = DateUtils.addDays(startTimeDate, -7);
        String endTime = DateUtils.dateTime1(startTimeDate);
        String startTime = DateUtils.dateTime1(endTimeDate);
        SysUser sysUser = AuthUtils.getLoginUser().getSysUser();
        Long deptId = sysUser.getDeptId();

        List<java.util.Date> dateList = DateUtils.getWeek(startTimeDate);
        JSONObject jsonObject = redisService.getCacheObject("hjczLine" + deptId);
        if (isNotEmpty(jsonObject)) {
            ECHARTS_LINE = jsonObject;
            return jsonObject;
        }

        ThreadPoolService.execute(() -> {
            List<Long> deptIdList = null;
            // 市领导 todo 此处不应该写死
            List<String> roleKeySets = map(sysUser.getRoles(), SysRole::getRoleKey);
            if (roleKeySets.contains("city") || roleKeySets.contains("admin") || roleKeySets.contains("yanshi")) {
                //ignore
            } else if (roleKeySets.contains("sys:town")) {
                List<SysDept> depts = remoteDeptService.listChildrenDepts(deptId);
                deptIdList = map(depts, SysDept::getId);
            }

            // 常住人口信息
            List<Czrk> czxzs = czrkMapper.listByCzXz1(startTime, endTime, deptIdList);
            List<Czrk> czjss = czrkMapper.listByCzJs1(startTime, endTime, deptIdList);

            // 户籍人口信息
            List<Czrk> hjxzs = czrkMapper.listByHjXz1(startTime, endTime, deptIdList); // 新增
            List<Czrk> hjjss = czrkMapper.listByHjJs1(startTime, endTime, deptIdList);// 减少

            List<JSONObject> result = new ArrayList<>();
            for (java.util.Date week : dateList) {
                java.util.Date tomorrow = DateUtils.addDays(week, 1);
                int czxz = 0, czjs = 0, hjxz = 0, hjjs = 0;
                JSONObject temp = new JSONObject();
                for (Czrk czrkxz : czxzs) {
                    Timestamp createTime = czrkxz.getCreateTime();
                    if (createTime.after(week) && createTime.before(tomorrow)) {
                        czxz++;
                    }
                }

                for (Czrk czrkjs : czjss) {
                    Timestamp updateTime = czrkjs.getUpdateTime();
                    if (updateTime != null) {
                        if (updateTime.after(week) && updateTime.before(tomorrow)) {
                            czjs++;
                        }
                    }
                }

                for (Czrk hjrkxz : hjxzs) {
                    Timestamp createTime = hjrkxz.getCreateTime();
                    if (createTime.after(week) && createTime.before(tomorrow)) {
                        czxz++;
                    }
                }

                for (Czrk hjrkjs : hjjss) {
                    Timestamp updateTime = hjrkjs.getUpdateTime();
                    if (updateTime != null) {
                        if (updateTime.after(week) && updateTime.before(tomorrow)) {
                            czjs++;
                        }
                    }
                }

                temp.put("czxz", czxz);
                temp.put("czjs", czjs);
                temp.put("hjxz", hjxz);
                temp.put("hjjs", hjjs);
                temp.put("time", DateUtils.setHmsZero(week));
                result.add(temp);
            }

            // 处理成图表格式
            List<String> xData = new ArrayList<>(7);
            List<Integer> czxz = new ArrayList<>(7);
            List<Integer> czjs = new ArrayList<>(7);
            List<Integer> hjxz = new ArrayList<>(7);
            List<Integer> hjjs = new ArrayList<>(7);
            for (JSONObject json : result) {
                xData.add(json.getString("time"));
                czxz.add(json.getInteger("czxz"));
                czjs.add(json.getInteger("czjs"));
                hjxz.add(json.getInteger("hjxz"));
                hjjs.add(json.getInteger("hjjs"));
            }


            resultData.put("time", xData);
            resultData.put("czxz", czxz);
            resultData.put("czjs", czjs);
            resultData.put("hjxz", hjxz);
            resultData.put("hjjs", hjjs);
            ECHARTS_LINE = resultData;
            redisService.setCacheObject("hjczLine:" + deptId, resultData);
        });

        return ECHARTS_LINE;
    }

    /**
     * 根据身份证号查询用户信息
     *
     * @param czrk
     * @return
     */
    @Override
    public Czrk findHjInfo(Czrk czrk) {
        Czrk hjInfo = czrkMapper.findHjInfo(czrk);
        if (hjInfo == null) {
            String idCard = czrk.getIdCard();
            if (StringUtils.isNotBlank(idCard)) {
                //根据身份证提取出生日和性别,年龄
                String sex = getSex(idCard);
                Integer age = getAge(idCard);
                String birthday = IdCardUtils.getBirthday(idCard);
                czrk.setAge(age);
                czrk.setGender(sex);
                czrk.setBirthday(birthday);
                return czrk;
            }
        }
        return hjInfo;
    }

    @Override
    public AjaxResult getInfo(String appKey, String appSecret, String idCard) {
        checkAuth(appKey, appSecret);
        checkIdCard(idCard);


        String ipAddr = IpUtils.getIpAddr(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
//        log.info("调用ip:{}", ip);
//        JSONObject jsonObject = ipTimesService.getByIp(ip);
        JSONObject jsonObject = ipTimesService.countByUsername(appKey, appSecret);
        if (jsonObject == null || jsonObject.size() == 0) {
            log.error("appKey:{}, appSecret:{}, idCard:{}", appKey, appSecret, idCard);
            return AjaxResult.error("appKey or appSecret is error");
        }

        String isStrong = jsonObject.getString("is_strong");
        String ip = jsonObject.getString("ip");

        //是否是强校验
        if ("Y".equals(isStrong)) {
            if (!ipAddr.equals(ip)) {
                log.error("appKey:{}, appSecret:{}, ip:{}, idCard:{}", appKey, appSecret, ipAddr, idCard);
                return AjaxResult.error("appKey or appSecret or ip is error");
            }
        }
        String today = DateUtils.getDate();
        String redisKey = IP_TIMES + jsonObject.getString("ip") + ":" + today;
        Integer cacheTimes = redisService.getCacheObject(redisKey);
        if (cacheTimes == null) cacheTimes = 0;
        int times = jsonObject.getIntValue("times");
        if (++cacheTimes > times) {
            log.error("ip:{}, 时间:{}, 访问超次数, 已经查询了 {} 次", ip, today, cacheTimes);
            return AjaxResult.error("今日访问次数已用尽，请明日再试");
        }

        JSONObject czrk = czrkMapper.getColumnNamesByIdCard(jsonObject.getString("column_names"), idCard);
        if (czrk == null) {
            log.error("ip:{}, 时间:{}, 根据idCard:{}, 未查询到信息, 已经查询了 {} 次", ip, today, idCard, cacheTimes);
            return AjaxResult.error("根据身份证号码未查询到信息");
        }

        long time = DateUtils.getTodayEnd().getTime(), time1 = DateUtils.getNowDate().getTime();
        redisService.setCacheObject(redisKey, cacheTimes, ((time - time1) / 1000), TimeUnit.SECONDS);
        packAddr(czrk);

        CzrkJzdz czrkJzdz = new CzrkJzdz();
        czrkJzdz.setCzrkId(czrk.getLong("id"));
        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.selectCzrkJzdzList(czrkJzdz);
        packCzrkJzdzAddr(czrkJzdzList);
        czrk.put("czrkJzdzList", czrkJzdzList);
        log.info("appKey:{}, appSecret:{}, idCard:{}， 查询到信息，czrk：{}", appKey, appSecret, idCard, JSON.toJSONString(czrk));
        return AjaxResult.success(czrk);
    }

    /**
     * RSE加密请求
     * 用RSE加密 ase的key(因为res加密有长度限制,ase没有,ase只有一个秘钥,所以使用rse来加密ase)
     * 公钥对ase进行加密
     * 私钥对签名进行加密
     * 加密前的ase对请求参数进行加密
     * ase用appid的前16位
     * appid = uuid32
     *
     * @param jsonRequest
     * @return
     */
    @Override
    public AjaxResult getInfoJson(JsonRequest jsonRequest) {
        //获取这个用户的appId
        String appId = jsonRequest.getAppId();
        if (StringUtils.isBlank(appId)) {
            return AjaxResult.error("缺少appId参数");
        }
        //拿着appid去查询对应的密钥对
        JSONObject ipTimes = ipTimesService.selectByAppId(appId);
        if (ipTimes == null || ipTimes.size() == 0) {
            return AjaxResult.error("该appId不存在");
        }
        String publicKey = ipTimes.getString("app_key");
        String privateKey = ipTimes.getString("app_secret");
        Map<String, Object> paramMap = RSAUtil.bean2Map(jsonRequest);
        paramMap.remove("sign");
        //参数排序
        Map<String, Object> sortedMap = RSAUtil.sort(paramMap);
        //拼接参数：key1Value1key2Value2,对参数进行16进制转换
        String urlParams = RSAUtil.groupStringParam(sortedMap);
        byte[] bytes = urlParams.getBytes();
        String value = HexUtils.toHexString(bytes);
        //签名验证
        boolean verify = RSAUtil.verify(HexUtils.fromHexString(value), publicKey, jsonRequest.getSign());
        if (!verify) {
            throw new RuntimeException("签名验证失败");
        }
        //私钥解密，获取aseKey
        String aseKey = RSAUtil.decryptByPrivateKey(HexUtils.fromHexString(jsonRequest.getAseKey()), privateKey);
        String requestBody = "";
        if (!StringUtils.isEmpty(jsonRequest.getBody())) {
            // 解密请求报文
            try {
                //vi值为18
                requestBody = AESUtil.decrypt(jsonRequest.getBody(), aseKey, appId.substring(16));
            } catch (Exception e) {
                throw new RuntimeException("请求参数解密异常");
            }
            System.out.println("业务参数解密结果：" + requestBody);
        }
        //获取请求的id
        String ipAddr = IpUtils.getIpAddr(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
        String isStrong = ipTimes.getString("is_strong");
        String ip = ipTimes.getString("ip");
        //是否是强校验
        if ("Y".equals(isStrong)) {
            if (!ipAddr.equals(ip)) {
                return AjaxResult.error("ip不正确");
            }
        }
        String today = DateUtils.getDate();
        String redisKey = APPID_TIMES + appId + ":" + today;
        Integer cacheTimes = redisService.getCacheObject(redisKey);
        if (cacheTimes == null) cacheTimes = 0;
        int times = ipTimes.getIntValue("times");
        if (++cacheTimes > times) {
            log.error("ip:{}, 时间:{}, 访问超次数, 已经查询了 {} 次", ip, today, cacheTimes);
            return AjaxResult.error("今日访问次数已用尽，请明日再试");
        }

        JSONObject jsonObject = JSONObject.parseObject(requestBody);
        String idCard = jsonObject.getString("idCard");
        JSONObject czrk = czrkMapper.getColumnNamesByIdCard(ipTimes.getString("column_names"), idCard);
        if (czrk == null) {
            log.error("ip:{}, 时间:{}, 根据idCard:{}, 未查询到信息, 已经查询了 {} 次", ip, today, idCard, cacheTimes);
            return AjaxResult.error("根据身份证号码未查询到信息");
        }

        long time = DateUtils.getTodayEnd().getTime(), time1 = DateUtils.getNowDate().getTime();
        redisService.setCacheObject(redisKey, cacheTimes, ((time - time1) / 1000), TimeUnit.SECONDS);
        packAddr(czrk);

        CzrkJzdz czrkJzdz = new CzrkJzdz();
        czrkJzdz.setCzrkId(czrk.getLong("id"));
        List<CzrkJzdz> czrkJzdzList = czrkJzdzService.selectCzrkJzdzList(czrkJzdz);
        packCzrkJzdzAddr(czrkJzdzList);
        czrk.put("czrkJzdzList", czrkJzdzList);
        log.info("appKey:{}, appSecret:{}, idCard:{}， 查询到信息，czrk：{}", publicKey, privateKey, idCard, JSON.toJSONString(czrk));
        return AjaxResult.success(czrk);
    }

    /**
     * 一键确认家庭成员
     *
     * @param ids
     * @return
     */
    @Override
    public AjaxResult confirmInfoByIds(Long[] ids) {
        LoginUser loginUser = tokenService.getLoginUser();
        // 获取当前的用户名称
        String username = loginUser.getUsername();
        String nickName = loginUser.getSysUser().getNickName();
        if (StringUtils.isBlank(username)) {
            return AjaxResult.error("未查询到确认人员名称");
        }
        if (ids.length > 0) {
            for (Long id : ids) {
                ConfirmInfoUser confirmInfoUser = new ConfirmInfoUser();
                confirmInfoUser.setConfirmInfoUser(username);
                confirmInfoUser.setCzrkId(id);
                confirmInfoUser.setConfirmInfoNikeUser(nickName);
                czrkMapper.insertConfirmInfoUser(confirmInfoUser);
                Czrk czrk = czrkMapper.selectCzrkById(id);
                czrk.setIsConfirm("Y");
                czrk.setConfirmInfoUser(username);
                czrk.setConfirmInfoUserTime(DateUtils.getNowDate());
                czrk.setConfirmInfoNikeUser(nickName);
                czrkMapper.updateCzrk(czrk);
            }
            return AjaxResult.success();
        }
        return AjaxResult.error("没有获取到主键");
    }


    private String packRedisKey(String deptId) {
        return STS_CZRK_ + deptId + ":" + DateUtils.getDate();
    }

    private void setIntoRedis(String key, Object result) {
        redisService.setCacheObject(key, result, 1L, TimeUnit.DAYS);
    }

    private void checkAuth(String appKey, String appSecret) {
        if (isEmpty(appKey) || isEmpty(appSecret)) {
            throw new RuntimeException("appKey or appSecret must not be empty");
        }
    }

    private void checkIdCard(String idCard) {
        if (isEmpty(idCard)) {
            throw new RuntimeException("idCard must not be empty");
        }
    }
}
