package com.hzya.frame.sys.contrastTask.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.hzya.frame.sys.app.dao.ISysAppMapper;
import com.hzya.frame.sys.app.entity.SysApp;
import com.hzya.frame.sys.contrastTask.entity.ReturnContrastDataDto;
import com.hzya.frame.sys.contrastTask.entity.ReturnContrastDto;
import com.hzya.frame.sys.contrastTask.entity.SaveBatchConTrastEntity;
import com.hzya.frame.sys.contrastTask.entity.SysContrastTaskEntity;
import com.hzya.frame.sys.contrastTask.dao.ISysContrastTaskDao;
import com.hzya.frame.sys.contrastTask.service.ISysContrastTaskService;
import com.hzya.frame.sys.customerControl.entity.CustomerControlEntity;
import com.hzya.frame.sys.orgControl.entity.OrgControlEntity;
import com.hzya.frame.sys.personnelControl.entity.PersonnelControlEntity;
import com.hzya.frame.sys.projectControl.entity.ProjectControlEntity;
import com.hzya.frame.sys.service.IExcApiService;
import com.hzya.frame.sys.supplierControl.entity.SupplierControlEntity;
import com.hzya.frame.sys.template.dao.ITemplateMapper;
import com.hzya.frame.sys.template.entity.Template;
import com.hzya.frame.uuid.UUIDUtils;
import com.hzya.frame.web.entity.BaseResult;
import com.hzya.frame.web.entity.JsonResultEntity;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;

import com.hzya.frame.basedao.service.impl.BaseService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 对照任务表(SysContrastTask)表服务实现类
 *
 * @author makejava
 * @since 2023-08-08 16:34:01
 */
@Service("sysContrastTaskService")
public class SysContrastTaskServiceImpl extends BaseService<SysContrastTaskEntity, String> implements ISysContrastTaskService {

    private ISysContrastTaskDao sysContrastTaskDao;
    @Resource
    private IExcApiService excApiService;

    @Resource
    private ISysAppMapper sysAppMapper;
    @Resource
    protected ITemplateMapper templateMapper;//模版表

    @Autowired
    public void setSysContrastTaskDao(ISysContrastTaskDao dao) {
        this.sysContrastTaskDao = dao;
        this.dao = dao;
    }

    /**
     * @param sysContrastTaskEntity
     * @return void
     * @Author lvleigang
     * @Description 执行对照任务
     * @Date 10:49 上午 2023/8/9
     **/
    @Override
    public void doContrastTask(SysContrastTaskEntity sysContrastTaskEntity) {
        //获取左接口数据，如果左接口数据不存在不执行
        logger.info(Thread.currentThread().getName() + "对照任务执行开始：" + sysContrastTaskEntity.toString());
        //1、修改任务执行状态
        updateContrastTask("2", "执行中", sysContrastTaskEntity);
        //2、清空原对比表数据
        //获取对应的服务
        //判断服务是否存在
        Template template = new Template();
        template.setServiceName(sysContrastTaskEntity.getServiceName());
        template.setSts("Y");
        List<Template> templateList = templateMapper.entity_list_base(template);
        if (templateList == null || templateList.size() != 1) {
            updateContrastTask("4", "执行失败:未查询到服务或查询到多个", sysContrastTaskEntity);
            return;
        }
        template = templateList.get(0);
        if(template.getTableName() == null || !useArraysBinarySearch(template.getTableName())){
            updateContrastTask("4", "执行失败:对照服务不正确", sysContrastTaskEntity);
            return;
        }
        truncateTable(template.getTableName());
        //获取左接口数据，如果左接口数据不存在不执行
        try {
            JSONObject leftData = excApiService.execute(sysContrastTaskEntity.getLeftApiId());
            if (leftData == null || leftData.getString("flag") == null || !leftData.getBoolean("flag")) {
                updateContrastTask("4", "执行失败:获取左接口数据错误", sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:获取左接口数据错误:" + leftData.getString("msg"));
                return;
            }
            ReturnContrastDto leftEntity = getData("msg", leftData, ReturnContrastDto.class);
            if (!leftEntity.getFlag() && leftEntity.getStatus() != null && !"200".equals(leftEntity.getStatus())) {
                updateContrastTask("4", "执行失败:获取左接口数据错误: " + leftEntity.getMsg(), sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:获取左接口数据错误:" + leftEntity.getMsg());
                return;
            }
            List<ReturnContrastDataDto> leftContrast = leftEntity.getAttribute();
            if (leftContrast == null || leftContrast.size() == 0) {
                updateContrastTask("3", "执行完成:左接口没有数据", sysContrastTaskEntity);
                return;
            }
            //判断是否有空值
            if (checkIsNull(leftContrast, sysContrastTaskEntity.getMatchMode())) {
                updateContrastTask("4", "执行失败:获取左接口数据错误: 唯一值存在空值" , sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:获取左接口数据错误:唯一值存在空值");
                return;
            }
            JSONObject rightData = excApiService.execute(sysContrastTaskEntity.getRightApiId());
            if (rightData == null || rightData.getString("flag") == null || !rightData.getBoolean("flag")) {
                updateContrastTask("4", "执行失败:获取右接口数据错误", sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:获取右接口数据错误:" + rightData.getString("msg"));
                return;
            }
            ReturnContrastDto rightEntity = getData("msg", rightData, ReturnContrastDto.class);
            if (!rightEntity.getFlag() && rightEntity.getStatus() != null && !"200".equals(rightEntity.getStatus())) {
                updateContrastTask("4", "执行失败:获取右接口数据错误: " + rightEntity.getMsg(), sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:获取右接口数据错误:" + rightEntity.getMsg());
                return;
            }


            Map<Object, Long> mapGroup = null;

            //1、按名称 2、按编码
            if ("1".equals(sysContrastTaskEntity.getMatchMode())) {
                mapGroup = leftContrast.stream().collect(Collectors.groupingBy(entity -> entity.getName(), Collectors.counting()));
            } else {
                mapGroup = leftContrast.stream().collect(Collectors.groupingBy(entity -> entity.getCode(), Collectors.counting()));
            }
            if (mapGroup.size() != leftContrast.size()) {
                updateContrastTask("4", "执行失败:左接口数据唯一值存在重复: ", sysContrastTaskEntity);
                logger.error(Thread.currentThread().getName() + "执行失败:左接口数据唯一值存在重复");
                return;
            }
            mapGroup.clear();

            List<ReturnContrastDataDto> rightContrast = rightEntity.getAttribute();

            List saveContrastList = contrastListData(leftContrast, rightContrast, template.getTableName(), sysContrastTaskEntity.getMatchMode());
            //保存数据
            //批量保存
            if(saveContrastData(saveContrastList,template.getTableName(),sysContrastTaskEntity)){
                //修改状态
                updateContrastTask("3", "执行完成", sysContrastTaskEntity);
            }else {
                truncateTable(template.getTableName());
                updateContrastTask("4", "执行失败:保存数据失败", sysContrastTaskEntity);
            }
        } catch (Exception e) {
            updateContrastTask("4", "执行失败:获取左接口数据错误", sysContrastTaskEntity);
            truncateTable(template.getTableName());
            logger.error(Thread.currentThread().getName() + "执行失败:获取左接口数据错误:" + e.getMessage());
            return;
        }
        logger.info(Thread.currentThread().getName() + "对照任务执行结束：" + sysContrastTaskEntity.toString());
    }

    /**
     * @Author lvleigang
     * @Description  保存数据 TODO
     * @Date 9:02 上午 2023/8/10
     * @param saveContrastList
     * @param tableName
     * @return boolean
     **/
    private boolean saveContrastData(List saveContrastList, String tableName, SysContrastTaskEntity entity) {
        int count = 20;
        if(saveContrastList != null && saveContrastList.size() > 0){
            SaveBatchConTrastEntity saveBatchConTrastEntity = new SaveBatchConTrastEntity();
            saveBatchConTrastEntity.setTableName(tableName);
            saveBatchConTrastEntity.setUserId(entity.getCreateUserId());

            SysApp leftApp = sysAppMapper.entity_get(entity.getLeftAppId());
            if(leftApp == null || leftApp.getId() == null || "".equals(leftApp.getId())){
                return false;
            }
            saveBatchConTrastEntity.setLeft_app_id(leftApp.getId());
            saveBatchConTrastEntity.setLeft_app_name(leftApp.getName());
            saveBatchConTrastEntity.setLeft_app_code(leftApp.getCode());
            saveBatchConTrastEntity.setLeft_api_id(entity.getLeftApiId());

            SysApp rightApp = sysAppMapper.entity_get(entity.getRightAppId());
            if(rightApp == null || rightApp.getId() == null || "".equals(rightApp.getId())){
                return false;
            }
            saveBatchConTrastEntity.setRight_app_id(rightApp.getId());
            saveBatchConTrastEntity.setRight_app_name(rightApp.getName());
            saveBatchConTrastEntity.setRight_app_code(rightApp.getCode());
            saveBatchConTrastEntity.setRight_api_id(entity.getRightApiId());

            List saveList = new ArrayList();
            for (int i = 0; i < saveContrastList.size(); i++) {
                saveList.add(saveContrastList.get(i));
                if(saveList.size() >= count){
                    saveBatchConTrastEntity.setDetailData(saveList);
                    //保存数据
                    sysContrastTaskDao.saveBatchContrast(saveBatchConTrastEntity);
                    saveList.clear();
                }
            }
        }
        return true;
    }



    /**
     * @param leftContrast
     * @param matchMode
     * @return boolean
     * @Author lvleigang
     * @Description 判断是否有空值
     * @Date 8:45 上午 2023/8/10
     **/
    private boolean checkIsNull(List<ReturnContrastDataDto> leftContrast, String matchMode) {
        boolean flag = false;
        //1、按名称 2、按编码
        if ("1".equals(matchMode)) {
            for (int i = 0; i < leftContrast.size(); i++) {
                if (leftContrast.get(i).getName() == null || "".equals(leftContrast.get(i).getName())) {
                    return true;
                }
            }
        } else {
            for (int i = 0; i < leftContrast.size(); i++) {
                if (leftContrast.get(i).getCode() == null || "".equals(leftContrast.get(i).getCode())) {
                    return true;
                }
            }
        }
        return flag;
    }

    /**
     * @param leftContrast  左数据
     * @param rightContrast 右数据
     * @param tableName     对象
     * @param matchMode     对比方式
     * @return java.util.List<com.hzya.frame.sys.contrastTask.entity.SaveContrast>
     * @Author lvleigang
     * @Description 对比列表数据 循环左右接口，返回所有左接口数据 TODO
     * @Date 4:40 下午 2023/8/9
     **/
    private List contrastListData(List<ReturnContrastDataDto> leftContrast, List<ReturnContrastDataDto> rightContrast, String tableName, String matchMode) {
        List returnList = new ArrayList();
        //1、按名称 2、按编码
        if ("1".equals(matchMode)) {
            Object entity = null;
            //循环左接口
            for (int i = 0; i < leftContrast.size(); i++) {
                ReturnContrastDataDto rightContrastData = null;
                entity = getCorrespondenceEntity(leftContrast.get(i),tableName,i);
                if(entity == null){
                    continue;
                }
                //循环右接口
                for (int i1 = 0; i1 < rightContrast.size(); i1++) {
                    //判断左右接口是否一样,一样 判断是否已经设置值，如果没有说明第一个，如果有说明重复，清空且跳出循环
                    if(rightContrast.get(i1).getName() != null && leftContrast.get(i).getName().equals(rightContrast.get(i1).getName())){
                        if(rightContrastData == null){
                            rightContrastData = rightContrast.get(i1);
                        }else {
                            rightContrastData = null;
                            break;
                        }
                    }
                }
                //如果不为空说明只有一个值，如果为空说明未匹配到或者匹配到两个及以上
                if(rightContrastData != null){
                    setRightValue(entity,rightContrastData,tableName);
                }
                returnList.add(entity);
            }
        } else {
            Object entity = null;
            //循环左接口
            for (int i = 0; i < leftContrast.size(); i++) {
                ReturnContrastDataDto rightContrastData = null;
                entity = getCorrespondenceEntity(leftContrast.get(i),tableName,i);
                if(entity == null){
                    continue;
                }
                //循环右接口
                for (int i1 = 0; i1 < rightContrast.size(); i1++) {
                    //判断左右接口是否一样,一样 判断是否已经设置值，如果没有说明第一个，如果有说明重复，清空且跳出循环
                    if(rightContrast.get(i1).getCode() != null && leftContrast.get(i).getCode().equals(rightContrast.get(i1).getCode())){
                        if(rightContrastData == null){
                            rightContrastData = rightContrast.get(i1);
                        }else {
                            rightContrastData = null;
                            break;
                        }
                    }
                }
                //如果不为空说明只有一个值，如果为空说明未匹配到或者匹配到两个及以上
                if(rightContrastData != null){
                    setRightValue(entity,rightContrastData,tableName);
                }
                returnList.add(entity);
            }

        }
        return returnList;
    }

    private void setRightValue(Object entity, ReturnContrastDataDto rightContrastData, String tableName) {
        if("sys_customer_control".equals(tableName)){
            CustomerControlEntity entity1 = (CustomerControlEntity)entity;
            entity1.setRight_id(rightContrastData.getId());
            entity1.setRight_code(rightContrastData.getCode());
            entity1.setRight_name(rightContrastData.getName());
            entity1.setRight_tin(rightContrastData.getTin());
        }else if("sys_supplier_control".equals(tableName)){
            SupplierControlEntity entity1 =  new SupplierControlEntity();
            entity1.setRight_id(rightContrastData.getId());
            entity1.setRight_code(rightContrastData.getCode());
            entity1.setRight_name(rightContrastData.getName());
            entity1.setRight_tin(rightContrastData.getTin());
        }else if("sys_personnel_control".equals(tableName)){
            PersonnelControlEntity entity1 =  new PersonnelControlEntity();
            entity1.setRight_id(rightContrastData.getId());
            entity1.setRight_code(rightContrastData.getCode());
            entity1.setRight_name(rightContrastData.getName());
            entity1.setRight_tel(rightContrastData.getTel());
            entity1.setRight_ic(rightContrastData.getIc());
        }else if("sys_org_control".equals(tableName)){
            OrgControlEntity entity1 =  new OrgControlEntity();
            entity1.setRight_id(rightContrastData.getId());
            entity1.setRight_code(rightContrastData.getCode());
            entity1.setRight_name(rightContrastData.getName());
        }else if("sys_project_control".equals(tableName)){
            ProjectControlEntity entity1 =  new ProjectControlEntity();
            entity1.setRight_id(rightContrastData.getId());
            entity1.setRight_code(rightContrastData.getCode());
            entity1.setRight_name(rightContrastData.getName());
        }
    }
    public static boolean useArraysBinarySearch(String targetValue) {
        String[] arr = new String[] {  "sys_customer_control",  "sys_supplier_control", "sys_personnel_control", "sys_org_control", "sys_project_control"};
        return ArrayUtils.contains(arr, targetValue);
    }
    private Object getCorrespondenceEntity(ReturnContrastDataDto returnContrastDataDto ,String tableName,int i) {
        if("sys_customer_control".equals(tableName)){

            CustomerControlEntity entity = new CustomerControlEntity();
            entity.setId(UUIDUtils.getUUID());
            entity.setSorts(i+1L);
            entity.setLeft_id(returnContrastDataDto.getId());
            entity.setLeft_code(returnContrastDataDto.getCode());
            entity.setLeft_name(returnContrastDataDto.getName());
            entity.setLeft_tin(returnContrastDataDto.getTin());
            return entity;
        }else if("sys_supplier_control".equals(tableName)){
            SupplierControlEntity entity =  new SupplierControlEntity();
            entity.setId(UUIDUtils.getUUID());
            entity.setSorts(i+1L);
            entity.setLeft_id(returnContrastDataDto.getId());
            entity.setLeft_code(returnContrastDataDto.getCode());
            entity.setLeft_name(returnContrastDataDto.getName());
            entity.setLeft_tin(returnContrastDataDto.getTin());
            return entity;
        }else if("sys_personnel_control".equals(tableName)){
            PersonnelControlEntity entity =  new PersonnelControlEntity();
            entity.setId(UUIDUtils.getUUID());
            entity.setSorts(i+1L);
            entity.setLeft_id(returnContrastDataDto.getId());
            entity.setLeft_code(returnContrastDataDto.getCode());
            entity.setLeft_name(returnContrastDataDto.getName());
            entity.setLeft_tel(returnContrastDataDto.getTel());
            entity.setLeft_ic(returnContrastDataDto.getIc());
            return entity;
        }else if("sys_org_control".equals(tableName)){
            OrgControlEntity entity =  new OrgControlEntity();
            entity.setId(UUIDUtils.getUUID());
            entity.setSorts(i+1L);
            entity.setLeft_id(returnContrastDataDto.getId());
            entity.setLeft_code(returnContrastDataDto.getCode());
            entity.setLeft_name(returnContrastDataDto.getName());
            return entity;
        }else if("sys_project_control".equals(tableName)){
            ProjectControlEntity entity =  new ProjectControlEntity();
            entity.setId(UUIDUtils.getUUID());
            entity.setSorts(i+1L);
            entity.setLeft_id(returnContrastDataDto.getId());
            entity.setLeft_code(returnContrastDataDto.getCode());
            entity.setLeft_name(returnContrastDataDto.getName());
            return entity;
        }
        return null;
    }


    private void truncateTable(String tableName) {
        if (tableName != null && !"".equals(tableName)) {
            sysContrastTaskDao.truncateTable(tableName);
        }
    }

    private void updateContrastTask(String taskStatus, String taskMsg, SysContrastTaskEntity sysContrastTaskEntity) {
        if (sysContrastTaskEntity != null && sysContrastTaskEntity.getId() != null) {
            //1、修改任务执行状态
            sysContrastTaskEntity.setTaskStatus(taskStatus);
            sysContrastTaskEntity.setTaskMsg(taskMsg);
            sysContrastTaskDao.update(sysContrastTaskEntity);
        }

    }



    /**
     * @param object
     * @return com.hzya.frame.web.entity.JsonResultEntity
     * @Author lvleigang
     * @Description 对照
     * @Date 1:33 下午 2023/7/12
     **/
    @Override
    public JsonResultEntity controlData(JSONObject object) {
        JSONObject jsonObject = getData("jsonStr", object,JSONObject.class);
        List<JSONObject> jsonObjectList = new ArrayList<>();

        if("1".equals(jsonObject.getString("types"))){
            //借方
            if(jsonObject.getString("control").equals("customer")){
                jsonObjectList.add(setdata("1","1","杭州用安借方1","hzya1314",null,null,jsonObject.getString("control")));
                jsonObjectList.add(setdata("1","2","杭州用安借方2","hzya1314",null,null,jsonObject.getString("control")));
                String sql = "SELECT id AS id,field0002 AS CODE,field0003 AS NAME,field0011 AS tin FROM formmain_0015 GROUP BY field0002 LIMIT 0,1000";
                jsonObjectList.addAll(sysContrastTaskDao.dosql(sql));
            }

        }else {
            //贷方
            if(jsonObject.getString("control").equals("customer")){
                jsonObjectList.add(setdata("1","1","杭州用安贷方1","hzya1314",null,null,jsonObject.getString("control")));
                jsonObjectList.add(setdata("1","1","杭州用安贷方2","hzya1314",null,null,jsonObject.getString("control")));
                String sql = "SELECT id AS id,field0002 AS CODE,field0003 AS NAME,field0011 AS tin FROM formmain_0015 GROUP BY field0002 LIMIT 0,1000";
                jsonObjectList.addAll(sysContrastTaskDao.dosql(sql));
            }
        }
        return BaseResult.getSuccessMessageEntity("数据",jsonObjectList);
    }

    /**
     * @Author lvleigang
     * @Description  设置值
     * @Date 2:59 下午 2023/8/10
     * @param id
     * @param code
     * @param name
     * @param tin
     * @param tel
     * @param ic
     * @param control
     * @return com.alibaba.fastjson.JSONObject
     **/
    private JSONObject setdata(String id, String code, String name, String tin, String tel, String ic, String control) {
        JSONObject object = new JSONObject();
        object.put("id",id);
        object.put("code",code);
        object.put("name",name);
        if(control.equals("customer")){
            object.put("tin",tin);
        }
        if(control.equals("supplier")){
            object.put("tin",tin);
        }
        if(control.equals("personnel")){
            object.put("tel",tel);
            object.put("ic",ic);
        }
        return object;
    }
}
