package net.northking.cctp.dw.db.impl;

import com.alibaba.fastjson.JSONObject;
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.constant.DWError;
import net.northking.cctp.dw.db.dao.DwAtuPlanBatchDao;
import net.northking.cctp.dw.db.dao.DwAtuPlanInfoDao;
import net.northking.cctp.dw.db.dao.DwAtuScriptInfoDao;
import net.northking.cctp.dw.db.dao.DwReBusComponentDao;
import net.northking.cctp.dw.db.service.ProjectOverviewService;
import net.northking.cctp.dw.dto.*;
import net.northking.cctp.dw.feign.ProjectsFeignForScheduleClient;
import org.apache.commons.lang.time.DateFormatUtils;
import org.quartz.TriggerUtils;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@ConditionalOnMissingBean(name = "ProjectOverviewServiceImpl")
public class ProjectOverviewServiceImpl implements ProjectOverviewService {

    private static final Logger logger = LoggerFactory.getLogger(ProjectOverviewServiceImpl.class);
    @Autowired
    private DwAtuScriptInfoDao dwAtuScriptInfoDao;
    @Autowired
    private DwReBusComponentDao dwReBusComponentDao;
    @Autowired
    private DwAtuPlanInfoDao dwAtuPlanInfoDao;
    @Autowired
    private ProjectsFeignForScheduleClient projectsFeignForScheduleClient;
    @Autowired
    private EntityNameCache entityNameCache;
    @Autowired
    private DwAtuPlanBatchDao dwAtuPlanBatchDao;

    @Override
    public ProjectOverviewDto projectOverviewQuery(ProjectOverviewQueryDto projectOverviewQueryDto) {
        ProjectOverviewDto projectOverviewDto = new ProjectOverviewDto();
        logger.info("ProjectOverviewServiceImpl.projectOverviewQuery 入参：{}", JSONObject.toJSONString(projectOverviewQueryDto));
        // 构建一般脚本信息
        ProjectOverviewDto.NormalScriptInfoOverviewDto normalScriptInfoOverviewDto = buildNormalScriptInfoDto(projectOverviewQueryDto);
        projectOverviewDto.setNormalScriptInfoOverviewDto(normalScriptInfoOverviewDto);
        // 构建场景脚本信息
        ProjectOverviewDto.SenceScriptInfoOverviewDto senceScriptInfoOverviewDto = bulidSenceScriptInfo(projectOverviewQueryDto);
        projectOverviewDto.setSenceScriptInfoOverviewDto(senceScriptInfoOverviewDto);
        // 构建业务组建信息
        ProjectOverviewDto.ComponentInfoDto componentInfoDto = buildComponentInfo(projectOverviewQueryDto);
        projectOverviewDto.setComponentInfoDto(componentInfoDto);
        // 构建执行计划信息
        ProjectOverviewDto.PlanInfoDto planInfoDto = buildPlanInfo(projectOverviewQueryDto);
        projectOverviewDto.setPlanInfoDto(planInfoDto);
        return projectOverviewDto;
    }

    @Override
    public ChargeInfoDto chargeInfoQuery(ChargeInfoQueryDto chargeInfoQueryDto) {
        ChargeInfoDto chargeInfoDto = new ChargeInfoDto();
        Date today = new Date();
        String todayStr = DateFormatUtils.format(today, "yyyy-MM-dd");
        Date todayStart = null;
        Date todayEnd = null;
        try {
            todayStart = DateUtil.parse(todayStr + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
            todayEnd = DateUtil.parse(todayStr + " 23:59:59", "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            logger.error("日期转换异常",e);
        }
        // 查询一般脚本
        Integer chargeTodayScriptNum = dwAtuScriptInfoDao.getScriptNum(chargeInfoQueryDto.getUserId(), "1", todayStart,todayEnd);
        Integer chargeScriptNum = dwAtuScriptInfoDao.getScriptNum(chargeInfoQueryDto.getUserId(), "0", null,null);
        // 查询场景脚本
        Integer chargeTodaySenceNum = dwAtuScriptInfoDao.getSenceScriptNum("", chargeInfoQueryDto.getUserId(), "1", todayStart,todayEnd);
        Integer chargeSenceNum = dwAtuScriptInfoDao.getSenceScriptNum("", chargeInfoQueryDto.getUserId(), "0", null,null);
        // 查询组件
        Integer chargeTodayComponentNum = dwReBusComponentDao.getComponentNum("", chargeInfoQueryDto.getUserId(), "1", todayStart,todayEnd);
        Integer chargeComponentNum = dwReBusComponentDao.getComponentNum("", chargeInfoQueryDto.getUserId(), "0", null,null);
        // 查询计划
        Integer chargePlanNum = dwAtuPlanInfoDao.getPlanNum("", chargeInfoQueryDto.getUserId(), "0", null,null);
        Integer chargeTodayPlanNum = dwAtuPlanInfoDao.getPlanNum("", chargeInfoQueryDto.getUserId(), "1", todayStart,todayEnd);

        chargeInfoDto.setAllScriptNum(chargeScriptNum);
        chargeInfoDto.setTodayScriptNum(chargeTodayScriptNum);

        chargeInfoDto.setAllSenceNum(chargeSenceNum);
        chargeInfoDto.setTodaySenceNum(chargeTodaySenceNum);

        chargeInfoDto.setAllComponentNum(chargeComponentNum);
        chargeInfoDto.setTodayComponentNum(chargeTodayComponentNum);

        chargeInfoDto.setAllPlanNum(chargePlanNum);
        chargeInfoDto.setTodayPlanNum(chargeTodayPlanNum);
        return chargeInfoDto;
    }

    @Override
    public List<ModifyInfoDto> modifyInfoQuery(ModifyInfoQueryDto modifyInfoQueryDto) {
        List<String> projectIdList = projectsFeignForScheduleClient.getProject(modifyInfoQueryDto.getUserId());
        if (CollectionUtils.isEmpty(projectIdList)) {
            return new ArrayList<ModifyInfoDto>();
        }
        List<ModifyInfoDto> modifyInfoDtoList = dwAtuScriptInfoDao.getModifyInfo(modifyInfoQueryDto.getUserId(), projectIdList);
        if (!CollectionUtils.isEmpty(modifyInfoDtoList)) {
            modifyInfoDtoList.forEach(modifyInfoDto -> {
                modifyInfoDto.setProjectName(entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM, modifyInfoDto.getProjectId()));
            });
            return modifyInfoDtoList;
        }
        return modifyInfoDtoList;
    }

    @Override
    public List<FailPlanInfoDto> failPlanQuery(ModifyInfoQueryDto modifyInfoQueryDto) {
        List<String> projectIdList = projectsFeignForScheduleClient.getProject(modifyInfoQueryDto.getUserId());
        if (CollectionUtils.isEmpty(projectIdList)) {
            return new ArrayList<FailPlanInfoDto>();
        }
        // 查询有权限系统下的所有计划信息
        List<FailPlanInfoDto> tempFailPlanInfoDtoList = dwAtuPlanInfoDao.failPlanQuery(projectIdList,modifyInfoQueryDto.getUserId());
        // 查询计划执行结果
        if (CollectionUtils.isEmpty(tempFailPlanInfoDtoList)) {
            return new ArrayList<FailPlanInfoDto>();
        }
        Map<String, FailPlanInfoDto> planInfoMap = tempFailPlanInfoDtoList.stream().collect(Collectors.toMap(FailPlanInfoDto::getPlanId, failPlanInfoDto -> failPlanInfoDto));
        List<String> planIdList = tempFailPlanInfoDtoList.stream().map(FailPlanInfoDto::getPlanId).collect(Collectors.toList());
        List<FailPlanInfoDto> failPlanInfoDtoList = dwAtuPlanBatchDao.failPlanQuery(planIdList,"fail",modifyInfoQueryDto.getUserId());
        List<FailPlanInfoDto> successPlanInfoDtoList = dwAtuPlanBatchDao.failPlanQuery(planIdList,"success",null);
        if (CollectionUtils.isEmpty(failPlanInfoDtoList)) {
            return new ArrayList<FailPlanInfoDto>();
        }
        Map<String,FailPlanInfoDto> successMap = successPlanInfoDtoList.stream().collect(Collectors.toMap(FailPlanInfoDto::getPlanId,failPlanInfoDto -> failPlanInfoDto));
        Iterator<FailPlanInfoDto> infoDtoIterator = failPlanInfoDtoList.iterator();
        while (infoDtoIterator.hasNext()){
            FailPlanInfoDto next = infoDtoIterator.next();
            if (!CollectionUtils.isEmpty(successMap)
                    && successMap.containsKey(next.getPlanId())) {
                String failExecuteTime = next.getExecuteTime();
                String successExecuteTime = successMap.get(next.getPlanId()).getExecuteTime();
                try {
                    Date failDate = DateUtil.parse(failExecuteTime,"yyyy-MM-dd HH:mm:ss");
                    Date successDate = DateUtil.parse(successExecuteTime,"yyyy-MM-dd HH:mm:ss");
                    if (successDate.getTime() > failDate.getTime()) {
                        infoDtoIterator.remove();
                    }
                } catch (ParseException e) {
                    logger.error("日期转换异常",e);
                }
            }

        }
        if (failPlanInfoDtoList.size()>10) {
            failPlanInfoDtoList = failPlanInfoDtoList.subList(0,10);
        }
        failPlanInfoDtoList.forEach(failPlanInfoDto -> {
            failPlanInfoDto.setProjectName(entityNameCache.translateById(EntityNameCatalog.MONSTER_SYSTEM, planInfoMap.get(failPlanInfoDto.getPlanId()).getProjectId()));
            failPlanInfoDto.setPlanName(planInfoMap.get(failPlanInfoDto.getPlanId()).getPlanName());
        });
        return failPlanInfoDtoList;
    }

    @Override
    public AxesDto planQuery(PlanQueryDto planQueryDto) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date dateFrom = null;
        Date dateTo = null;
        try {
            dateFrom = dateFormat.parse(planQueryDto.getStartTime());
            dateTo = dateFormat.parse(planQueryDto.getEndTime());
        } catch (Exception e) {
            throw new PlatformRuntimeException(DWError.DATE_PARSE_ERROR, e);
        }
        List<PlanQueryRspDto> planQueryRspDtoList = dwAtuPlanInfoDao.planQuery();
        AxesDto axesDto = new AxesDto();
        axesDto.setXName("小时");
        axesDto.setYName("星期");
        SimpleDateFormat hourFormat = new SimpleDateFormat("HH");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTo);
        calendar.add(Calendar.DAY_OF_MONTH, 1);//结束时间改为结束当天的 23：59：00
        calendar.add(Calendar.SECOND, -1);
        dateTo = calendar.getTime();
        try {
            CronTriggerImpl cronTrigger = new CronTriggerImpl();
            if (!CollectionUtils.isEmpty(planQueryRspDtoList)) {
                for (PlanQueryRspDto planQueryRspDto : planQueryRspDtoList) {
                    cronTrigger.setCronExpression(planQueryRspDto.getCronExpr());
                    List<Date> triggerDates = TriggerUtils.computeFireTimesBetween(cronTrigger, null, dateFrom, dateTo);
                    for (Date triggerDate : triggerDates) {
                        calendar.setTime(triggerDate);
                        int weekIndex = calendar.get(Calendar.DAY_OF_WEEK);
                        String triggerHour = hourFormat.format(triggerDate);
                        String format = String.valueOf(Integer.valueOf(triggerHour));
                        axesDto.addValue(format, String.valueOf(weekIndex - 1));
                    }
                }
            }
        } catch (Exception e) {
            logger.error("获取测试计划执行热力图数据有误:" + e.getMessage());
            throw new PlatformRuntimeException(DWError.GET_PLAN_ERROR, e.getMessage());
        }
        return axesDto;
    }

    private ProjectOverviewDto.PlanInfoDto buildPlanInfo(ProjectOverviewQueryDto projectOverviewQueryDto) {
        ProjectOverviewDto.PlanInfoDto planInfoDto = new ProjectOverviewDto.PlanInfoDto();
        Integer planNum = dwAtuPlanInfoDao.getPlanNum(projectOverviewQueryDto.getProjectId(), "", "0", null,null);
        Integer chargePlanNum = dwAtuPlanInfoDao.getPlanNum(projectOverviewQueryDto.getProjectId(), projectOverviewQueryDto.getUserId(), "0", null,null);
        planInfoDto.setChargePlanNum(chargePlanNum);
        planInfoDto.setPlanNum(planNum);
        return planInfoDto;
    }

    private ProjectOverviewDto.ComponentInfoDto buildComponentInfo(ProjectOverviewQueryDto projectOverviewQueryDto) {
        ProjectOverviewDto.ComponentInfoDto componentInfoDto = new ProjectOverviewDto.ComponentInfoDto();
        Integer componentNum = dwReBusComponentDao.getComponentNum(projectOverviewQueryDto.getProjectId(), "", "0", null,null);
        Integer chargeComponentNum = dwReBusComponentDao.getComponentNum(projectOverviewQueryDto.getProjectId(), projectOverviewQueryDto.getUserId(), "0", null,null);
        componentInfoDto.setChargeCompentNum(chargeComponentNum);
        componentInfoDto.setComponentNum(componentNum);
        return componentInfoDto;
    }

    private ProjectOverviewDto.SenceScriptInfoOverviewDto bulidSenceScriptInfo(ProjectOverviewQueryDto projectOverviewQueryDto) {
        ProjectOverviewDto.SenceScriptInfoOverviewDto senceScriptInfoOverviewDto = new ProjectOverviewDto.SenceScriptInfoOverviewDto();
        Integer senceScriptNum = dwAtuScriptInfoDao.getSenceScriptNum(projectOverviewQueryDto.getProjectId(), "", "0", null,null);
        Integer chargeSenceScriptNum = dwAtuScriptInfoDao.getSenceScriptNum(projectOverviewQueryDto.getProjectId(), projectOverviewQueryDto.getUserId(), "0", null,null);
        senceScriptInfoOverviewDto.setScriptNum(senceScriptNum);
        senceScriptInfoOverviewDto.setChargeScriptNum(chargeSenceScriptNum);
        return senceScriptInfoOverviewDto;

    }

    private ProjectOverviewDto.NormalScriptInfoOverviewDto buildNormalScriptInfoDto(ProjectOverviewQueryDto projectOverviewQueryDto) {
        ProjectOverviewDto.NormalScriptInfoOverviewDto normalScriptInfoOverviewDto = null;
        // 查询系统下一般脚本数目
        List<ProjectScriptNumDto> projectScriptNumDtoList =
                dwAtuScriptInfoDao.projectOverviewQuery(projectOverviewQueryDto.getProjectId(), "");
        // 查询系统下登录账号负责的脚本数
        List<ProjectScriptNumDto> projectScriptChargeList =
                dwAtuScriptInfoDao.projectOverviewQuery(projectOverviewQueryDto.getProjectId(), projectOverviewQueryDto.getUserId());
        if (!CollectionUtils.isEmpty(projectScriptNumDtoList)) {
            normalScriptInfoOverviewDto = new ProjectOverviewDto.NormalScriptInfoOverviewDto();
            ProjectOverviewDto.NormalScriptInfoOverviewDto finalNormalScriptInfoOverviewDto = normalScriptInfoOverviewDto;
            projectScriptNumDtoList.forEach(projectScriptNumDto -> {
                if (projectScriptNumDto.getScriptTypeCode() == 0) {
                    finalNormalScriptInfoOverviewDto.setCustomScriptNum(projectScriptNumDto.getScriptNum());
                }
                if (projectScriptNumDto.getScriptTypeCode() == 1) {
                    finalNormalScriptInfoOverviewDto.setBsScriptNum(projectScriptNumDto.getScriptNum());
                }
                if (projectScriptNumDto.getScriptTypeCode() == 2) {
                    finalNormalScriptInfoOverviewDto.setCsScriptNum(projectScriptNumDto.getScriptNum());
                }
                if (projectScriptNumDto.getScriptTypeCode() == 3) {
                    finalNormalScriptInfoOverviewDto.setAndroidScriptNum(projectScriptNumDto.getScriptNum());
                }
                if (projectScriptNumDto.getScriptTypeCode() == 4) {
                    finalNormalScriptInfoOverviewDto.setIosScriptNum(projectScriptNumDto.getScriptNum());
                }
            });
            finalNormalScriptInfoOverviewDto.setChargeScriptNum(projectScriptChargeList.get(0).getScriptNum());
            return finalNormalScriptInfoOverviewDto;
        }
        return normalScriptInfoOverviewDto;
    }
}
