package net.northking.cctp.dw.bus;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.northking.cctp.common.cache.EntityNameCache;
import net.northking.cctp.common.cache.EntityNameCatalog;
import net.northking.cctp.common.exception.PlatformRuntimeException;
import net.northking.cctp.common.util.DateUtil;
import net.northking.cctp.dw.api.atu.service.*;
import net.northking.cctp.dw.constant.DWError;
import net.northking.cctp.dw.db.entity.*;
import net.northking.cctp.dw.dto.DwAtuPlanTaskSyncDto;
import net.northking.cctp.dw.dto.atu.MqSynchronizeTaskAddDto;
import net.northking.cctp.dw.feign.CltTestTeamDto;
import net.northking.cctp.dw.feign.PlatformFeignClient;
import net.northking.cctp.dw.feign.ProjectsFeignForScheduleClient;
import net.northking.cctp.dw.feign.UserInfoRsp;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

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

@Component
public class AtuDataListener {

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private DwAtuScriptInfoApiService dwAtuScriptInfoApiService;
    @Autowired
    private DwAtuScriptVersionApiService dwAtuScriptVersionApiService;
    @Autowired
    private DwReBusComponentApiService dwReBusComponentApiService;
    @Autowired
    private DwAtuCaseDesignApiService dwAtuCaseDesignApiService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private EntityNameCache entityNameCache;
    @Autowired
    private DwAtuPlanInfoApiService dwAtuPlanInfoApiService;
    @Autowired
    private DwAtuPlanBatchApiService dwAtuPlanBatchApiService;

    @Autowired
    private DwAtuPlanScriptLinkApiService dwAtuPlanScriptLinkApiService;
    @Autowired
    private DwAtuPlanEnvLinkApiService dwAtuPlanEnvLinkApiService;
    @Autowired
    private PlatformFeignClient feignClient;
    @Autowired
    private ProjectsFeignForScheduleClient projectsFeignClient;
    @Autowired
    private DwAtuPlanTaskApiService dwAtuPlanTaskApiService;


    private final Logger logger = LoggerFactory.getLogger(AtuDataListener.class);

    //监听脚本以及脚本版本信息
    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuScriptInfo.Insert.REQ")
    })
    public void syncAtuScriptInfo(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<MqSynchronizeTaskAddDto> mqSynchronizeTaskAddDtos = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                MqSynchronizeTaskAddDto mqSynchronizeTaskAddDto = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), MqSynchronizeTaskAddDto.class);
                mqSynchronizeTaskAddDtos.add(mqSynchronizeTaskAddDto);
            }
            //更新或新增脚本信息
            //新增脚本发布版本
            //根据脚本id是否存在筛选出是脚本版本还是脚本信息
            List<DwAtuScriptInfo> dwAtuScriptInfos = new ArrayList<>();
            DwAtuScriptInfo dwAtuScriptInfo = null;
            List<DwAtuScriptVersion> dwAtuScriptVersions = new ArrayList<>();
            DwAtuScriptVersion dwAtuScriptVersion = null;

            List<Object> ids = new ArrayList<>();
            List<DwAtuScriptVersion> dwAtuScriptVersionDeletes = new ArrayList<>();
            //区分出脚本版本和脚本信息
            for (MqSynchronizeTaskAddDto mqSynchronizeTaskAddDto : mqSynchronizeTaskAddDtos) {
                if (null != mqSynchronizeTaskAddDto.getId()) {
                    /*

                     */
                    dwAtuScriptInfo = new DwAtuScriptInfo();
                    BeanUtils.copyProperties(mqSynchronizeTaskAddDto, dwAtuScriptInfo);
                    String projectName = entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM, mqSynchronizeTaskAddDto.getProjectId());
                    dwAtuScriptInfo.setProjectName(projectName);
                    String scriptManager = entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, mqSynchronizeTaskAddDto.getPrincipalId());
                    dwAtuScriptInfo.setScriptManager(scriptManager);
                    if(StringUtils.isNotBlank(mqSynchronizeTaskAddDto.getPrincipalId())){
                        UserInfoRsp userInfoRsp = feignClient.getUserInfo(mqSynchronizeTaskAddDto.getPrincipalId());
                        dwAtuScriptInfo.setTestTeamManager(userInfoRsp.getTestTeamManager());
                        dwAtuScriptInfo.setTestTeam(userInfoRsp.getTestTeam());
                        dwAtuScriptInfo.setScriptManagerCompany(userInfoRsp.getScriptManagerCompany());
                        dwAtuScriptInfo.setScriptManagerOperCode(userInfoRsp.getScriptManagerOperCode());
                        dwAtuScriptInfo.setTestTeamId(userInfoRsp.getTestTeamId());
                        dwAtuScriptInfo.setScriptManagerId(mqSynchronizeTaskAddDto.getPrincipalId());
                    }
                    dwAtuScriptInfo.setScriptCode(mqSynchronizeTaskAddDto.getScriptCode());
                    dwAtuScriptInfos.add(dwAtuScriptInfo);

                    ids.add(mqSynchronizeTaskAddDto.getId());
                } else {
                    dwAtuScriptVersion = new DwAtuScriptVersion();
                    BeanUtils.copyProperties(mqSynchronizeTaskAddDto, dwAtuScriptVersion);
                    dwAtuScriptVersions.add(dwAtuScriptVersion);

                    DwAtuScriptVersion dwAtuScriptVersionDelete = new DwAtuScriptVersion();
                    dwAtuScriptVersionDelete.setScriptId(mqSynchronizeTaskAddDto.getScriptId());
                    dwAtuScriptVersionDelete.setVersionId(mqSynchronizeTaskAddDto.getVersionId());
                    dwAtuScriptVersionDeletes.add(dwAtuScriptVersionDelete);
                }
            }
            //根据更新时间获取相同id最新的更新记录
            List<Object> idList = ids.stream().distinct().collect(Collectors.toList());
            Map<String, List<DwAtuScriptInfo>> map = dwAtuScriptInfos.stream().collect(Collectors.groupingBy(DwAtuScriptInfo::getId));
            List<DwAtuScriptInfo> dwAtuScriptInfoList = new ArrayList<>();
            for (Object id : idList) {
                List<DwAtuScriptInfo> dwAtuScriptInfosTmp = map.get(id);
                List<DwAtuScriptInfo> collect = dwAtuScriptInfosTmp.stream().sorted(Comparator.comparing(DwAtuScriptInfo::getUpdatedTime).reversed()).collect(Collectors.toList());
                dwAtuScriptInfoList.add(collect.get(0));
            }
            //先根据id删除再新增
            if (ids.size() != 0) {
                transactionTemplate.execute(transactionStatus -> {

                    Integer count = dwAtuScriptInfoApiService.deleteBatch(idList);
                    List<String> idLists = dwAtuScriptInfoApiService.addBatch(dwAtuScriptInfoList);

                    return Boolean.TRUE;
                });
            }
            if (dwAtuScriptVersionDeletes.size() != 0) {
                transactionTemplate.execute(transactionStatus -> {

                    Integer count = dwAtuScriptVersionApiService.deleteByExamples(dwAtuScriptVersionDeletes);
                    List<String> idLists = dwAtuScriptVersionApiService.addBatch(dwAtuScriptVersions);

                    return Boolean.TRUE;
                });
            }
        } catch (Exception e) {
            logger.error("syncAtuScriptInfo", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步脚本信息失败"), e);
        }
    }

    //监听已发布业务组件信息
    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.ReBusComponent.Insert.REQ")
    })
    public void syncBusComponentInfo(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwReBusComponent> reBusComponents = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwReBusComponent busComponent = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwReBusComponent.class);
                reBusComponents.add(busComponent);
            }
            //新增或者更新已发布业务组件信息
            //先根据id删除
            List<Object> ids = reBusComponents.stream().map(DwReBusComponent::getId).collect(Collectors.toList());
            transactionTemplate.execute(transactionStatus -> {

                Integer count = dwReBusComponentApiService.deleteBatch(ids);
                //然后新增
                List<String> idList = dwReBusComponentApiService.addBatch(reBusComponents);

                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncBusComponentInfo", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步已发布业务组件信息失败"), e);
        }
    }


    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuPlanInfo.Insert.REQ")
    })
    public void syncAtuPlanInfo(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwAtuPlanInfo> dwAtuPlanInfoList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwAtuPlanInfo dwAtuPlanInfo = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwAtuPlanInfo.class);
                String projectName = entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM, dwAtuPlanInfo.getProjectId());
                String projectManager = null;
                if (StringUtils.isNotBlank(dwAtuPlanInfo.getCreatedBy())) {
                    CltTestTeamDto planTestTeam = feignClient.getPlanTeamInfo(dwAtuPlanInfo.getCreatedBy());
                    if (planTestTeam != null) {
                        dwAtuPlanInfo.setPlanTestTeam(planTestTeam.getName());
                        dwAtuPlanInfo.setPlanTeamId(planTestTeam.getId());
                    }
                    UserInfoRsp userInfoRsp = feignClient.getUserInfo(dwAtuPlanInfo.getCreatedBy());
                    if (userInfoRsp != null) {
                        dwAtuPlanInfo.setManagerOperCode(userInfoRsp.getScriptManagerOperCode());
                        dwAtuPlanInfo.setPlanManagerCompany(userInfoRsp.getScriptManagerCompany());
                    }
                }

                if (StringUtils.isNotBlank(projectManager)) {
                    CltTestTeamDto projectTestTeam = feignClient.getPlanTeamInfo(projectManager);
                    if (projectTestTeam != null) {
                        dwAtuPlanInfo.setProjectTeamId(projectTestTeam.getId());
                        dwAtuPlanInfo.setProjectTestTeam(projectTestTeam.getName());
                    }
                }
                String userName = entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, dwAtuPlanInfo.getCreatedBy());

                dwAtuPlanInfo.setCreator(userName);

                dwAtuPlanInfo.setProjectName(projectName);


                dwAtuPlanInfoList.add(dwAtuPlanInfo);

            }
            //根据更新时间筛选重复的主键选出最新的记录
            //新增或者更新自动化用例信息
            //先根据id删除
            List<Object> ids = dwAtuPlanInfoList.stream().map(DwAtuPlanInfo::getId).collect(Collectors.toList());
            transactionTemplate.execute(transactionStatus -> {
                Integer count = dwAtuPlanInfoApiService.deleteBatch(ids);
                List<String> idList = dwAtuPlanInfoApiService.addBatch(dwAtuPlanInfoList);
                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncAtuPlanInfo", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步执行计划信息失败"), e);
        }
    }


    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuPlanBatch.Insert.REQ")
    })
    public void syncAtuPlanBatch(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwAtuPlanBatch> dwAtuPlanInfoList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwAtuPlanBatch dwAtuPlanInfo = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwAtuPlanBatch.class);
                dwAtuPlanInfo.setUpdatedTime(new Date());
                String userName = entityNameCache.translateById(EntityNameCatalog.MONSTER_USER, dwAtuPlanInfo.getExecutedBy());
                if (StringUtils.isNotBlank(dwAtuPlanInfo.getExecutedBy())) {
                    UserInfoRsp userInfoRsp = feignClient.getUserInfo(dwAtuPlanInfo.getExecutedBy());
                    dwAtuPlanInfo.setManagerOperCode(userInfoRsp.getScriptManagerOperCode());
                    dwAtuPlanInfo.setManagerCompany(userInfoRsp.getScriptManagerCompany());
                    dwAtuPlanInfo.setTestTeamManager(userInfoRsp.getTestTeamManager());
                    dwAtuPlanInfo.setTestTeam(userInfoRsp.getTestTeam());
                    dwAtuPlanInfo.setTestTeamId(userInfoRsp.getTestTeamId());
                }
                dwAtuPlanInfo.setExecutedName(userName);
                dwAtuPlanInfoList.add(dwAtuPlanInfo);
            }
            //根据更新时间筛选重复的主键选出最新的记录
            //新增或者更新自动化用例信息
            //先根据id删除
            List<Object> ids = dwAtuPlanInfoList.stream().map(DwAtuPlanBatch::getId).collect(Collectors.toList());
            transactionTemplate.execute(transactionStatus -> {
                Integer count = dwAtuPlanBatchApiService.deleteBatch(ids);
                List<String> idList = dwAtuPlanBatchApiService.addBatch(dwAtuPlanInfoList);
                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncAtuPlanBatch", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步执行计划信息失败"), e);
        }
    }

    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuPlanScriptLink.Insert.REQ")
    })
    public void syncAtuPlanScriptLink(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwAtuPlanScriptLink> dwAtuPlanScriptLinkList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwAtuPlanScriptLink dwAtuPlanScriptLink = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwAtuPlanScriptLink.class);
                dwAtuPlanScriptLinkList.add(dwAtuPlanScriptLink);
            }
            //根据更新时间筛选重复的主键选出最新的记录
            //新增或者更新自动化用例信息
            //先根据id删除
            transactionTemplate.execute(transactionStatus -> {
                dwAtuPlanScriptLinkList.forEach(dwAtuPlanScriptLink -> {
                    Integer count = dwAtuPlanScriptLinkApiService.deleteByPlanIdAndScriptId(dwAtuPlanScriptLink.getPlanId(), dwAtuPlanScriptLink.getScriptId());
                });
                List<String> idList = dwAtuPlanScriptLinkApiService.addBatch(dwAtuPlanScriptLinkList);
                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncAtuPlanScriptLink", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步执行计划信息失败"), e);
        }
    }

    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuPlanEnvLink.Insert.REQ")
    })
    public void syncAtuPlanEnvLink(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwAtuPlanEnvLink> dwAtuPlanEnvLinkList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwAtuPlanEnvLink dwAtuPlanEnvLink = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwAtuPlanEnvLink.class);
                dwAtuPlanEnvLinkList.add(dwAtuPlanEnvLink);
            }
            //根据更新时间筛选重复的主键选出最新的记录
            //新增或者更新自动化用例信息
            //先根据id删除
            List<Object> ids = dwAtuPlanEnvLinkList.stream().map(DwAtuPlanEnvLink::getId).collect(Collectors.toList());
            transactionTemplate.execute(transactionStatus -> {
                dwAtuPlanEnvLinkList.forEach(dwAtuPlanEnvLink -> {
                    dwAtuPlanEnvLinkApiService.deleteByPlanIdAndEnvId(dwAtuPlanEnvLink.getPlanId(), dwAtuPlanEnvLink.getEnvId());
                });
                List<String> idList = dwAtuPlanEnvLinkApiService.addBatch(dwAtuPlanEnvLinkList);
                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncAtuPlanEnvLink", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步执行计划信息失败"), e);
        }
    }

    @RabbitListener(queuesToDeclare = {
            @Queue(value = "Dw.AtuPlanTask.Insert.REQ")
    })
    public void syncAtuPlanTask(Message message) {
        try {
            List list = objectMapper.readValue(message.getBody(), List.class);
            List<DwAtuPlanTask> dwAtuPlanTaskList = new ArrayList<>();
            for (int i = 0; i < list.size(); i++) {
                DwAtuPlanTaskSyncDto dwAtuPlanTaskSyncDto = JSONObject.parseObject(JSONObject.toJSON(list.get(i)).toString(), DwAtuPlanTaskSyncDto.class);
                DwAtuPlanTask dwAtuPlanTask = new DwAtuPlanTask();
                BeanUtils.copyProperties(dwAtuPlanTaskSyncDto, dwAtuPlanTask);
                dwAtuPlanTask.setStatus(Integer.parseInt(dwAtuPlanTaskSyncDto.getStatus()));
                Long startTime = dwAtuPlanTaskSyncDto.getStartTime();
                Long endTime = dwAtuPlanTaskSyncDto.getEndTime();
                if (startTime != null) {
                    String formateDateStr = DateFormatUtils.format(new Date(startTime), "yyyy-MM-dd HH:ss:mm");
                    Date startTimeDate = DateUtil.parse(formateDateStr, "yyyy-MM-dd HH:ss:mm");
                    dwAtuPlanTask.setStartTime(startTimeDate);
                }
                if (endTime != null) {
                    String formateDateStr = DateFormatUtils.format(new Date(endTime), "yyyy-MM-dd HH:ss:mm");
                    Date endTimeDate = DateUtil.parse(formateDateStr, "yyyy-MM-dd HH:ss:mm");
                    dwAtuPlanTask.setEndTime(endTimeDate);
                }
                dwAtuPlanTaskList.add(dwAtuPlanTask);
            }
            //根据更新时间筛选重复的主键选出最新的记录
            //新增或者更新自动化用例信息
            //先根据id删除
            List<Object> ids = dwAtuPlanTaskList.stream().map(DwAtuPlanTask::getId).collect(Collectors.toList());
            transactionTemplate.execute(transactionStatus -> {
                Integer count = dwAtuPlanTaskApiService.deleteBatch(ids);
                List<String> idList = dwAtuPlanTaskApiService.addBatch(dwAtuPlanTaskList);
                return Boolean.TRUE;
            });
        } catch (Exception e) {
            logger.error("syncAtuPlanEnvLink", e);
            throw new PlatformRuntimeException(DWError.valueOf("mq同步执行计划信息失败"), e);
        }
    }


}
