package com.bcxin.backend.domain.screening.service.impl;

import com.bcxin.backend.core.exceptions.SaasBadException;
import com.bcxin.backend.domain.models.Result;
import com.bcxin.backend.domain.models.ScreeningDTO;
import com.bcxin.backend.domain.screening.factory.ScreeningFactory;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public abstract class BackgroundScreeningServiceAbstractImpl {
    private static Logger logger = LoggerFactory.getLogger(BackgroundScreeningServiceAbstractImpl.class);

    private final ScreeningFactory screeningFactory;
    @Autowired
    @Qualifier("primaryJdbcTemplate")
    protected JdbcTemplate jdbcTemplate;

    protected BackgroundScreeningServiceAbstractImpl(ScreeningFactory screeningFactory) {
        this.screeningFactory = screeningFactory;
    }

    private String jobSql =
            "SELECT tm.ID sId,bsr.pkId as pkId,bs.user_id userId,bs.idnum idCard, tm.domainid,tm.item_domain_id domain_id,tm.item_companyName companyName,tm.ITEM_entryDate entryTime,tm.ITEM_phone phone,tm.ITEM_securityName userName,bs.background_screening_status screening,IF((bs.last_background_screening_time is null)=1 AND bsr.pkId > 0,1,0) isFZ,bsr.QUESTIONTYPE questiontype " +
                    ",(SELECT ifnull(ts.ITEM_registerPoliceAddress,'') FROM tlk_setsupervise ts WHERE ts.item_domain_id = tm.ITEM_DOMAIN_ID limit 1)  as registerPoliceAddress " +
                    ",(SELECT ifnull(ts.ITEM_registerPoliceAddressID,'') FROM tlk_setsupervise ts WHERE ts.item_domain_id = tm.ITEM_DOMAIN_ID limit 1)  as registerPoliceAddressID " +
                    "FROM tlk_securityman tm " +
                    "INNER JOIN bg_screening_users bs ON LEFT(tm.ID,LENGTH(bs.user_id)) = bs.user_id AND bs.enabled=1 AND bs.idnum IN ${idnums} " +
                    "LEFT JOIN bg_screening_user_results bsr ON bsr.domain_id=tm.item_domain_id AND bsr.USERID = bs.user_id AND bsr.DOCUMENTID=bs.idnum AND bsr.Entry_Time=tm.ITEM_entryDate " +
                    "WHERE " +
                    "tm.ITEM_isInMyCompany= 1 ;";


    public abstract String numSql();

    public Boolean screening() {
        logger.info("-----------------------------------------------背景筛查程序开始执行--------------------------------------------------------------");
        logger.info("-----------------------------------------------组装人员信息开始执行--------------------------------------------------------------");

        try {
            Collection<BgUser> bgUsers = this.getPendingBgScreenUsers();
            logger.info("查询数据库，被筛人员条数：" + bgUsers.size());

            if (!CollectionUtils.isEmpty(bgUsers)) {
                //分页背筛，每30条一批
                Collection<BgUser> limitBgUsers = Collections.synchronizedList(new ArrayList<>());
                for (BgUser bgUser:bgUsers ) {
                    limitBgUsers.add(bgUser);
                    if(limitBgUsers.size()==30){
                        try {
                            check(limitBgUsers);
                        } catch (Exception e) {
                            logger.error("分页背景筛查check方法运行异常:" + e.getMessage());
                        }
                        limitBgUsers = Collections.synchronizedList(new ArrayList<>());
                    }
                }
                if(limitBgUsers.size()>0){
                    try {
                        check(limitBgUsers);
                    } catch (Exception e) {
                        logger.error("分页背景筛查check方法运行异常:" + e.getMessage());
                    }
                }

                return true;
            } else {
                logger.info("被筛人员列表为空");
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private Collection<BgUser> getPendingBgScreenUsers() {
        return jdbcTemplate.query(numSql(), BeanPropertyRowMapper.newInstance(BgUser.class));
    }

    private Collection<PersonInfor> getPendingPersonInfors(Collection<String> idnums) {
        String sqlStr = jobSql.replace("${idnums}",
                idnums.toString().replace("[", "('").replace("]", "')").replace(",", "','").replace(" ", ""));
        System.err.println("=======> getPendingPersonInfors:"+sqlStr);
        return jdbcTemplate.query(sqlStr, BeanPropertyRowMapper.newInstance(PersonInfor.class));
    }

    private Result<List<ScreeningDTO>> doExecute(Collection<String> idNums) {
        return screeningFactory.getBSPByType().screenings(idNums.toArray(new String[idNums.size()]));
    }

    @Transactional
    protected void check(Collection<BgUser> bgUsers) throws Exception {
        logger.info("-----------------------------------------------对比程序开始执行--------------------------------------------------------------");
        logger.info("-----------------------------------------------对比程序开始执行--------------------------------------------------------------");
        Collection<String> idnums = Collections.synchronizedList(new ArrayList<>());
        bgUsers.stream().forEach(bgUser -> {
            idnums.add(bgUser.getIdnum());
        });

        try {
            //根据身份证查询保安员记录
            Collection<PersonInfor> jobCollection = this.getPendingPersonInfors(idnums);
            if(jobCollection.size()==0){
                System.err.println("====> 背景筛查程：jobCollection=0,end!");
                return;
            }
            logger.info("查询数据库，被筛人员条数：" + jobCollection.size());
            Result<List<ScreeningDTO>> result = this.doExecute(idnums);

            if (Result.SUCCESS.equals(result.getRetType())) {
                if (result.getData() == null) {
                    throw new SaasBadException(String.format("BackgrounpScreening:Request interface message returns exception,ErrMsg:%s.", result.getMsg()));
                }
                //筛选要更新结果表数据
                List<String> updateBsu0 = Collections.synchronizedList(new ArrayList<>());
                List<String> updateBsu1 = Collections.synchronizedList(new ArrayList<>());
                //问题人员记录不存在的，用于新增记录
                List<PersonInfor> insertBsur = Collections.synchronizedList(new ArrayList<>());
                //有问题并且有记录的问题ID
                List<String> updateBsur = Collections.synchronizedList(new ArrayList<>());
                result.getData().stream().forEach(screening -> {
                    List<PersonInfor> perFilter = jobCollection.stream()
                            .filter(person -> (person.getIdCard().equals(screening.getIdnum())))
                            .collect(Collectors.toList());
                    if ("1".equals(screening.getIsProblem())) {//有问题
                        //筛选出身份证、问题类型一致的记录
                        List<PersonInfor> updateFilter = perFilter.stream().filter(person -> !StringUtils.isEmpty(person.getQuestiontype()) && person.getQuestiontype().equals(screening.getDetail())).collect(Collectors.toList());
                        if(updateFilter.size() == 0){
                            //筛选出身份证一致、但是无问题类型或问题类型不一致的记录
                            List<PersonInfor> insertFilter = perFilter.stream()
                                    .filter(person -> StringUtils.isEmpty(person.getQuestiontype()) || !person.getQuestiontype().equals(screening.getDetail())).collect(Collectors.toList());

                            //需要新增的问题设置问题类型
                            insertFilter.stream().forEach(personInfor -> {
                                personInfor.setQuestiontype(screening.getDetail());
                            });
                            ArrayList<PersonInfor> collect = insertFilter.stream().collect(Collectors.
                                    collectingAndThen(Collectors.toCollection(() ->
                                            new TreeSet<>(Comparator.comparing((PersonInfor temp) -> temp.getDomain_id() + ";" + temp.getEntryTime()))), ArrayList::new));

                            insertBsur.addAll(collect);
                        }
                        //需要修改的问题只记录主键
                        updateFilter.stream().forEach(personInfor -> {
                            /*if(personInfor.getIsFZ()=="1"){
                                personInfor.setQuestiontype(screening.getDetail());
                                insertBsur.add(personInfor);
                            }*/
                            updateBsur.add(personInfor.getPkId() + "");
                        });
                        updateBsu1.add(screening.getIdnum());
                    } else {
                        updateBsu0.add(screening.getIdnum());
                    }
                });

                //有问题，问题表不存在，新增问题记录
                if (insertBsur.size() > 0) {
                    //先区分犯罪类型  吸毒  在逃  重点
                    String DRUG = "吸毒";
                    String DRUG1 = "戒毒";
                    String ESCAPE = "在逃";
                    StringBuilder sb = new StringBuilder();
                    List<String> argList = Collections.synchronizedList(new ArrayList<>());
                    sb.append("INSERT INTO bg_screening_user_results (ID,TYPE,CREATED,lastmodified,firstcompareTime,COMPARETIME,DOMAINID," +
                            "QUESTIONTYPE,USERID,SECURITYNAME,DOCUMENTID,PHONE,COMPANYNAME," +
                            "DOMAIN_ID,REGISTERPOLICEADDRESS," +
                            "REGISTERPOLICEADDRESSID,POLICESTATUS,WORKSTATUS,COMPANYSTATUS,Entry_Time,CAPTURESTATUS) values");

                    insertBsur.stream().parallel().forEach(questionUser -> {
                        int qt = 3;//1在逃,2吸毒，3重点
                        String cst = null;
                        if (!ObjectUtils.isEmpty(questionUser.getQuestiontype()) && (questionUser.getQuestiontype().contains(DRUG)||questionUser.getQuestiontype().contains(DRUG1))) {
                            qt = 2;
                        } else if (!ObjectUtils.isEmpty(questionUser.getQuestiontype()) && questionUser.getQuestiontype().contains(ESCAPE)) {
                            qt = 1;
                            cst = "0";
                        }
                        String eTime = "'" + questionUser.getEntryTime() + "'";
                        if (StringUtils.isEmpty(questionUser.getEntryTime())) {
                            eTime = null;
                        }
                        String rpa = "'" + questionUser.getRegisterPoliceAddress() + "'";
                        if (StringUtils.isEmpty(questionUser.getRegisterPoliceAddress())) {
                            rpa = null;
                        }
                        String rpai = "'" + questionUser.getRegisterPoliceAddressID() + "'";
                        if (StringUtils.isEmpty(questionUser.getRegisterPoliceAddressID())) {
                            rpai = null;
                        }
                        String phone = "'" + questionUser.getPhone() + "'";
                        if (StringUtils.isEmpty(questionUser.getPhone())) {
                            phone = null;
                        }
                        String cn = "'" + questionUser.getCompanyName() + "'";
                        if (StringUtils.isEmpty(questionUser.getCompanyName())) {
                            cn = null;
                        }
                        String ui = "'" + questionUser.getUserId() + "'";
                        if (StringUtils.isEmpty(questionUser.getUserId())) {
                            ui = null;
                        }
                        String un = "'" + questionUser.getUserName() + "'";
                        if (StringUtils.isEmpty(questionUser.getUserName())) {
                            un = null;
                        }
                        String cid = "'" + questionUser.getDomain_id() + "'";
                        if (StringUtils.isEmpty(questionUser.getDomain_id())) {
                            cid = null;
                        }
                        String sql = "( UUID_SHORT() ,'" + qt + "', NOW(),NOW(), NOW(), NOW(),'"+questionUser.getDomainid()+"' , '" + questionUser.getQuestiontype() + "'," + ui + "," + un + ",'" + questionUser.getIdCard() +
                                "', " + phone + "," + cn + "," + cid +
                                ", " + rpa + "," + rpai + ",0,1,0," + eTime + "," + cst + " )";
                        argList.add(sql);
                    });
                    //argList.stream().distinct().collect(Collectors.toList())
                    sb.append(argList.stream().distinct().collect(Collectors.toList()).toString().replace("[", "").replace("]", ";"));
                    jdbcTemplate.update(sb.toString());
                }
                //问题表已存在记录更新背筛时间
                if (updateBsur.size() > 0) {
                    jdbcTemplate.update("UPDATE bg_screening_user_results SET `COMPARETIME`=NOW(), `lastmodified`=NOW() WHERE `pkId` in " + updateBsur.toString().replace("[", "('").replace("]", "')").replace(",", "','") + ";");
                }
                //背筛结果更新
                if (updateBsu1.size() > 0) {
                    String psql = updateBsu1.toString().replace("[", "('").replace("]", "')").replace(",", "','").replace(" ", "");
                    jdbcTemplate.update("UPDATE bg_screening_users SET `background_screening_status`='1', `last_compare_time`=NOW(), `last_background_screening_time`=NOW(), `last_modified_time`=NOW() WHERE `idnum` in " + psql + ";");
                }
                if (updateBsu0.size() > 0) {
                    String nopsql = updateBsu0.toString().replace("[", "('").replace("]", "')").replace(",", "','").replace(" ", "");
                    jdbcTemplate.update("UPDATE bg_screening_users SET `background_screening_status`='0', `last_compare_time`=NOW(), `last_background_screening_time`=NOW(), `last_modified_time`=NOW() WHERE `idnum` in " + nopsql + ";");
                }

            } else {
                throw new SaasBadException(String.format("BackgrounpScreening:Request interface failed,ErrMsg:%s.", result.getMsg()));
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("背景筛查check方法出现问题:" + e.getMessage());
        }
    }
}

@Data
class BgUser {
    private String idnum;
    private String user_id;
}

@Data
class PersonInfor {

    private String sId;
    private String pkId;
    private String userId;
    private String idCard;
    private String userName;
    private String phone;
    private String domainid;
    private String domain_id;
    private String companyName;
    private String screening;
    private String entryTime;
    private String questiontype;
    private String registerPoliceAddress;
    private String registerPoliceAddressID;

    private String isFZ;//是否复职人员

}


@Data
class QuestionUser {
    private String id;
    private String userName;
    private String idCard;
    private String phone;
    private String questiontype;
    private String date;
    private String domain_id;
    private String companyName;
    private String registerPoliceAddress;
    private String registerPoliceAddressID;
}


@Data
class OldQuestionUserInfo {
    private String itemComparetime;
    private String itemQuestiontype;
    private String itemDocumentid;
    private String itemDomain_id;
    private String itemCompanyname;
}