package com.scpyun.platform.jilinsscgsdp.utils;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.scpyun.base.core.utils.UUIDUtil;
import com.scpyun.base.db.service.CommonService;
import com.scpyun.platform.jilinsscgsdp.bean.entity.KeyPersonImp;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class FileDataListener extends AnalysisEventListener<KeyPersonImp> {
    /**
     * 日志
     */
    private static final Logger log = LoggerFactory.getLogger(FileDataListener.class);
    /**
     * 批量处理阈值，每读取100条数据处理一次
     */
    private static final int BATCH_COUNT = 200;
    /**
     * 缓存读取到的数据
     */
    private List<KeyPersonImp> cachedDataList = new ArrayList<>(BATCH_COUNT);
    /**
     * 成功插入的数据计数
     */
    private AtomicInteger insertCount = new AtomicInteger(0);
    /**
     * 成功更新的数据计数
     */
    private AtomicInteger updateCount = new AtomicInteger(0);
    /**
     * 解析失败的数据计数
     */
    private AtomicInteger errorCount = new AtomicInteger(0);

    //临时变量
    private Map<String, KeyPersonImp> personMap = new HashMap<>();
    private Map<String, String> cityMap = new HashMap<>();
    private Map<String, Map<String, String>> areaMap = new HashMap<>();
    private Map<String, Map<String, String>> streetMap = new HashMap<>();
    private Map<String, Map<String, String>> communityMap = new HashMap<>();
    private Map<String, String> mzMap = new HashMap<>();//民族信息

    //参数变量，登录人相关
    private Map<String, Object> paraMap;
    private String userCode = "";
    private String companyId = "";
    private String parentIds = "";
    private String grade = "";
    private String area_id = "";
    private String sysType = "";

    //所属位置
    private String cityId = "";
    private String areaId = "";
    private String streetId = "";
    private String communityId = "";

    private StringBuffer errMsg = new StringBuffer();

    /**
     * 服务参数
     */
    private CommonService commonService;
    private String namespace;
    private final String nameSpaceSys = "com.scpyun.platform.standard.jilinsscgsdp.sys.";
    private final String nameSpacePeople = "com.scpyun.platform.standard.jilinsscgsdp.peopleInfo.";

    // 如果监听器需要被Spring管理
    public FileDataListener(CommonService commonService, String namespace, Map<String, Object> map) {
        this.commonService = commonService;
        this.namespace = namespace;
        paraMap = map;
        sysType = String.valueOf(map.get("sysType"));//类型 2 3 6

        Map<String, Object> user = (Map<String, Object>) map.get("_user");
        Map<String, String> pos = DataScopeUtil.getPosition(user);
        grade =  pos.get("grade");
        area_id = pos.get("area_id");
        try {
            userCode = user.get("id").toString();
            companyId = user.get("company_id").toString();
            parentIds = user.get("parent_ids").toString();
        }catch (Exception e){}

        if("3".equals(grade)){//city
            cityId = companyId;
        }else if("4".equals(grade)){//area
            String[] ids = parentIds.split(",");
            cityId = ids[ids.length-1];
            areaId = area_id;
        }else if("5".equals(grade)){//street
            String[] ids = parentIds.split(",");
            cityId = ids[ids.length-2];
            areaId = ids[ids.length-1];
            streetId = area_id;
        }else if ("6".equals(grade)){//community
            String[] ids = parentIds.split(",");
            cityId = ids[ids.length-3];
            areaId = ids[ids.length-2];
            streetId = ids[ids.length-1];
            communityId = area_id;
        }

        initData();
    }
    //初始化数据
    private void initData() {
        String methodName = "getAllPersons_new";
        if(!"6".equals(sysType)){
            methodName = "getAllPersons";
        }

        //加载已有的用户
        Map<String, String> _map = new HashMap<>();
        _map.put("sysType", sysType);
        _map.put("parent_id", String.valueOf(paraMap.get("cityId")));
        List<KeyPersonImp> personList = commonService.findList(namespace + methodName, _map);
        for (int i = 0,il=personList.size(); i < il; i++) {
            KeyPersonImp obj =  personList.get(i);
            String cardNo = obj.getCardNo();
            personMap.put(cardNo, obj);
        }

        List<Map<String, Object>> mzlist = commonService.findList(nameSpacePeople + "findMZList", _map);
        for (int i = 0,il=mzlist.size(); i < il; i++) {
            Map<String, Object> obj = mzlist.get(i);
            mzMap.put(obj.get("mzname").toString(), obj.get("mzcode").toString());
        }

//        List<Map<String, Object>> cityList = commonService.findList(nameSpaceSys + "selectCityList", _map);
//        for (int i = 0,il=cityList.size(); i < il; i++) {
//            Map<String, Object> obj = cityList.get(i);
//            cityMap.put(String.valueOf(obj.get("name")), String.valueOf(obj.get("parent_id")));
//        }

        _map = null;

    }

    // 累积一批数据后处理，例如每100条入库一次
    @Override
    public void invoke(KeyPersonImp person, AnalysisContext context) {
        // 处理单行数据
        try {
//            log.info("解析到一条数据: {}", JSON.toJSONString(person));

            // 这里可以添加数据校验逻辑
            if (isValidProduct(person)) {
                cachedDataList.add(person);
            } else {
                errorCount.incrementAndGet(); // 失败计数增加
//                log.warn("数据校验失败: {}", JSON.toJSONString(person));
            }

            // 达到BATCH_COUNT时，执行一次批量插入，清空缓存[citation:4]
            if (cachedDataList.size() >= BATCH_COUNT) {
                saveData();
                cachedDataList.clear();
            }
        } catch (Exception e) {
            errorCount.incrementAndGet();
//            log.error("处理数据时发生异常: {}", e.getMessage());
            // 注意：抛出异常会停止读取，如不想停止，可捕获异常
        }
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 所有数据解析完成后的操作
        // 确保最后一批数据也被保存[citation:4]
        if (!cachedDataList.isEmpty()) {
            saveData();
            cachedDataList.clear();
        }

        // 输出最终统计结果
//        int total = insertCount.get() + updateCount.get() + errorCount.get();
//        log.info("所有数据解析完成！成功解析: {} 条，失败: {} 条，总计: {} 条",
//                successCount.get(), errorCount.get(), total);
    }
    /**
     * 保存数据到数据库[citation:4]
     */
    private void saveData() {
        if (cachedDataList.isEmpty()) {
            return;
        }

        List<KeyPersonImp> addList = new ArrayList<>();
        List<KeyPersonImp> updList = new ArrayList<>();

        //这里需要根据身份证号读取数据数据做对比，无数据进行插入，有数据进行更新，需要调整批量处理数量
        for (int i = 0,il=cachedDataList.size(); i < il; i++) {
            KeyPersonImp person =  cachedDataList.get(i);
            person.setSysType(sysType);
            String cardNo = person.getCardNo();

            if(personMap.containsKey(cardNo)){
                enc(person, false);//更新时不做所在位置更新处理
                updList.add(trans(person, personMap.get(cardNo)));
                updateCount.incrementAndGet();
            }else{
                String errMark = enc(person, true);//社区使用，核对有效社区即可
                if(errMark == null){
                    person.setId(IdUtil.simpleUUID());
                    person.setSysType(sysType);
                    person.setCreateUser(userCode);
                    addList.add(person);
                    insertCount.incrementAndGet();
                }else{
                    errMsg.append(",");
                    errMsg.append(errMark);
                }
            }
        }

        // 实际开发中，这里调用service或dao进行数据持久化
        if(addList.size()>0){
            String methodName = "keyPersonInsertBatch_new";
            if(!"6".equals(sysType)){
                methodName = "keyPersonInsertBatch";
            }
            Map<String, Object> _map = new HashMap<>();
            _map.put("list", addList);
            commonService.insert(namespace + methodName, _map);
            //关注情形
            insertHighData(addList, false);
        }
        if(updList.size()>0){
            String methodName = "keyPersonUpdateBatch_new";
            if(!"6".equals(sysType)){
                methodName = "keyPersonUpdateBatch";
            }
//            Map<String, Object> _map = new HashMap<>();
//            _map.put("list", updList);
//            commonService.update(namespace + methodName, _map);
            for (int i = 0,il=updList.size(); i < il; i++) {
                KeyPersonImp person = updList.get(i);
                commonService.update(namespace + methodName, person);
            }

            //关注情形
            insertHighData(updList, true);
        }

//        log.info("批量保存完成");

        addList = null;
        updList = null;
    }

    /**
     * 人员关注情形信息处理
     * @param list
     * @param delFlag
     */
    private void insertHighData(List<KeyPersonImp> list, Boolean delFlag) {
        Map<String, Object> _map = new HashMap<>();
        List<Map<String, Object>> highList = new ArrayList<>();
        for (int i = 0,il=list.size(); i < il; i++) {
            KeyPersonImp obj = list.get(i);
            List<String> tlist = new ArrayList<>();
            if(StringUtils.isNotEmpty(obj.getCriminalTendency())) {
                tlist.add("重新犯罪");
            }
            if(StringUtils.isNotEmpty(obj.getEvil())) {
                tlist.add("黑恶");
            }
            if(StringUtils.isNotEmpty(obj.getHeinousCrime())) {
                tlist.add("恶性犯罪");
            }
            if(StringUtils.isNotEmpty(obj.getCult())) {
                tlist.add("邪教");
            }
            if(StringUtils.isNotEmpty(obj.getThreeNoesPerson())) {
                tlist.add("三无人员");
            }
            for (int j = 0,jl=tlist.size(); j < jl; j++) {
                Map<String, Object> tmap = new HashMap<>();
                tmap.put("id", UUIDUtil.getUUID());
                tmap.put("keyPersonId", obj.getId());
                tmap.put("cardNo", obj.getCardNo());
                tmap.put("highly", tlist.get(j));
                tmap.put("userId", userCode);
                highList.add(tmap);
            }
        }

        if(delFlag) {
            String methodName = "deletekeyPersonHighlyByIds_new";
            if(!"6".equals(sysType)){
                methodName = "deletekeyPersonHighlyByIds";
            }

            List<String> cardList = list.stream().map(KeyPersonImp::getCardNo).collect(Collectors.toList());
            _map.clear();
            _map.put("list", cardList);
            commonService.delete(namespace + methodName, _map);
        }

        if(highList.size()>0){
            String methodName = "keyPersonHighlyInsertBatch_new";
            if(!"6".equals(sysType)){
                methodName = "keyPersonHighlyInsertBatch";
            }

            _map.clear();
            _map.put("list", highList);
            commonService.insert(namespace + methodName, _map);
        }
    }

    //excel解析内容转换及位置处理判断
    private String enc(KeyPersonImp person, Boolean judge) {
        if(person.getFolk()!=null && !person.getFolk().equals("")){
            String mz = null;
            for(String key : mzMap.keySet()){
                if(key.indexOf(person.getFolk())!=-1) {
                    mz = mzMap.get(key);
                    break;
                }
            }
            person.setFolk(mz);
        }
        person.setSex("女".equals(person.getSex().trim())?"2":"1");

        if(person.getInvolvingConflictsDisputes()!=null && ("1".equals(person.getInvolvingConflictsDisputes().trim())
                || "是".equals(person.getInvolvingConflictsDisputes().trim())
                || "有".equals(person.getInvolvingConflictsDisputes().trim()))) {
            person.setInvolvingConflictsDisputes("1");
            String level = person.getRiskLevel();
            if(level!=null) {
                if("1".equals(level)) {
                    person.setRiskLevel("1");
                }else if("2".equals(level)) {
                    person.setRiskLevel("2");
                }else if("3".equals(level)) {
                    person.setRiskLevel("3");
                }
            }
        }else{
            person.setInvolvingConflictsDisputes("2");
        }

        //需要做机构判断
        if(judge) {
            if("3".equals(grade)){//city
                person.setCityId(cityId);
                setArea(person);
                setStreet(person);
                setCommunity(person);
            }else if("4".equals(grade)){//area
                person.setCityId(cityId);
                person.setAreaId(areaId);
                setStreet(person);
                setCommunity(person);
            }else if("5".equals(grade)){//street
                person.setCityId(cityId);
                person.setAreaId(areaId);
                person.setStreetId(streetId);
                setCommunity(person);
            }else if ("6".equals(grade)){//community
                person.setCityId(cityId);
                person.setAreaId(areaId);
                person.setStreetId(streetId);
                if(person.getCommunityName()==null ||  person.getCommunityName().trim().length()==0) {
                    person.setCommunityId(communityId);
                }else{
                    setCommunity(person);
                }
            }else{//管理员
                person.setCityId("220100000000");
                setArea(person);
                setStreet(person);
                setCommunity(person);
            }

            if(person.getCommunityId()==null) {
                return person.getName();
            }
        }else{
            person.setCityId(null);
            person.setAreaId(null);
            person.setStreetId(null);
            person.setCommunityId(null);
        }

        return null;
    }

    private void setArea(KeyPersonImp person) {
        if(person.getCityId()!=null && !"".equals(person.getCityId().trim()) &&
        person.getAreaName()!=null && !"".equals(person.getAreaName().trim())){
            Map<String, String> _map = areaMap.get(person.getCityId());
            if(_map==null){
                _map = new HashMap<>();
                encMap(_map, person.getCityId());
                areaMap.put(person.getCityId(), _map);
            }

            for(String key : _map.keySet()){
                if(key.indexOf(person.getAreaName())!=-1){
                    person.setAreaId(_map.get(key));
                    break;
                }
            }
        }
    }
    private void setStreet(KeyPersonImp person) {
        if(person.getAreaId()!=null && !"".equals(person.getAreaId().trim()) &&
                person.getStreetName()!=null && !"".equals(person.getStreetName().trim())){
            Map<String, String> _map = streetMap.get(person.getAreaId());
            if(_map==null){
                _map = new HashMap<>();
                encMap(_map, person.getAreaId());
                streetMap.put(person.getAreaId(), _map);
            }

            for(String key : _map.keySet()){
                if(key.indexOf(person.getStreetName())!=-1){
                    person.setStreetId(_map.get(key));
                    break;
                }
            }
        }
    }
    private void setCommunity(KeyPersonImp person) {
        if(person.getStreetId()!=null && !"".equals(person.getStreetId().trim()) &&
                person.getCommunityName()!=null && !"".equals(person.getCommunityName().trim())){
            Map<String, String> _map = communityMap.get(person.getStreetId());
            if(_map==null){
                _map = new HashMap<>();
                encMap(_map, person.getStreetId());
                communityMap.put(person.getStreetId(), _map);
            }

            for(String key : _map.keySet()){
                if(key.indexOf(person.getCommunityName())!=-1){
                    person.setCommunityId(_map.get(key));
                    break;
                }
            }
        }
    }
    private void encMap(Map map, String parentId) {
        Map<String, Object> _map = new HashMap<>();
        _map.put("parent_id", parentId);
        List<Map<String, Object>> list = commonService.findList(nameSpaceSys + "selectCityList", _map);
        for (int i = 0,il=list.size(); i < il; i++) {
            Map<String, Object> obj = list.get(i);
            map.put(String.valueOf(obj.get("name")), String.valueOf(obj.get("parent_id")));
        }
    }

    //传入数据赋值给原数据，null不复制
    private KeyPersonImp trans(KeyPersonImp person, KeyPersonImp oldPerson) {
        BeanUtils.copyProperties(person, oldPerson, getNullPropertyNames(person));
        oldPerson.setUpdateUser(userCode);
        return oldPerson;
    }
    /**
     * 获取对象中为null的属性名数组
     * @param source 源对象
     * @return 为null的属性名数组
     */
    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<>();
        for (PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 数据校验方法
     */
    private boolean isValidProduct(KeyPersonImp person) {
        //身份证号、姓名、电话、性别
        return person.getCardNo() != null &&
                !person.getCardNo().trim().isEmpty() &&
                person.getName() != null &&
                !person.getName().trim().isEmpty() &&
                person.getSex() != null &&
                !person.getSex().trim().isEmpty() &&
                person.getPhone() != null &&
                !person.getPhone().trim().isEmpty();
    }

    /**
     * 返回结果
     * @return
     */
    public Map<String, Object> getResult() {
        String errInfo = null;
        if(errMsg.length() > 0) {
            errInfo = errMsg.substring(1);
        }
        Map<String, Object> rmap = new HashMap<>();
        rmap.put("insert", insertCount.get());
        rmap.put("update", updateCount.get());
        rmap.put("error", errorCount.get());
        rmap.put("errInfo", errInfo);
        return rmap;
    }



//    // 存储表头信息，key为列索引，value为表头内容
//    private Map<Integer, String> headMap = new HashMap<>();
//
//    @Override
//    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
//        // 此方法在读取到表头时调用，可以获取多级表头信息[citation:3]
//        headMap.putAll(headMap);
//        System.out.println("解析到的表头:" + headMap);
//    }
}
