package com.energy.manage.service.service.analysis.impl;

import com.energy.manage.common.po.analysis.AnalysisResultPo;
import com.energy.manage.common.po.autoanalysisconfigdetailoptionrecords.AutoAnalysisConfigDetailOptionRecordsPo;
import com.energy.manage.common.po.autoanalysisconfigrelations.AutoAnalysisConfigRelationsPo;
import com.energy.manage.service.constant.analysis.AnalysisConstants;
import com.energy.manage.service.domain.dto.analysis.AnalysisDto;
import com.energy.manage.service.domain.dto.analysis.AutoAnalysisConfigDetailDto;
import com.energy.manage.service.domain.vo.analysis.AnalysisTypeVo;
import com.energy.manage.service.domain.vo.analysis.AutoAnalysisConfigDetailVo;
import com.energy.manage.service.mappers.analysis.AnalysisResultMapper;
import com.energy.manage.service.mappers.analysis.AnalysisTypeMapper;
import com.energy.manage.service.mappers.autoanalysisconfigdetail.AutoAnalysisConfigDetailMapper;
import com.energy.manage.service.mappers.autoanalysisconfigdetailoptionrecords.AutoAnalysisConfigDetailOptionRecordsMapper;
import com.energy.manage.service.mappers.autoanalysisconfigrelations.AutoAnalysisConfigRelationsMapper;
import com.energy.manage.service.service.analysis.AnalysisService;
import com.energy.manage.service.service.analysis.AutoAnalysisService;
import com.energy.manage.service.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.energy.manage.service.constant.analysis.AnalysisConstants.AUTO_ANALYSIS_NAME;

/**
 * @author chy
 * @date 2025/3/31 15:43
 * @desc
 */
@Slf4j
@Service
public class AutoAnalysisServiceImpl implements AutoAnalysisService {

    @Autowired
    private AutoAnalysisConfigDetailMapper autoAnalysisConfigDetailMapper;

    @Autowired
    private AutoAnalysisConfigDetailOptionRecordsMapper optionRecordsMapper;

    @Autowired
    private AnalysisService analysisService;

    @Autowired
    private AnalysisResultMapper analysisResultMapper;

    @Autowired
    private AutoAnalysisConfigRelationsMapper relationsMapper;

    @Autowired
    private AnalysisTypeMapper analysisTypeMapper;

    /**
     * 自动分析
     */
    @Override
    public void autoAnalysis() {
        log.info("触发自动分析定时任务开始。");
        //查询所有风场启动中的自动分析配置
        List<AutoAnalysisConfigDetailVo> detailVos = autoAnalysisConfigDetailMapper.selectByCondition(new AutoAnalysisConfigDetailDto().setStartupState(AnalysisConstants.ON_CALL));
        if(CollectionUtils.isEmpty(detailVos)){
            log.info("当前无自动分析配置，不执行自动分析。");
            return;
        }
        detailVos.stream().forEachOrdered(item->{
            //保存操作结果与关联关系
            AutoAnalysisConfigRelationsPo relationsPo = saveAnalysisResult(item);
            if(relationsPo == null){
                log.info("任务id = {} 数据截止日期在当前时间之后，不执行自动分析。", item.getConfigUniqueId());
                return;
            }
            //调用分析
            analysis(relationsPo,item.getFieldCode());
        });
        log.info("触发自动分析定时任务结束");
    }

    /**
     * 保存操作结果与关联关系（判断最后一次分析到目前为止有没有改动过配置，如果改动过则重新跑）
     * @param vo
     */
    private AutoAnalysisConfigRelationsPo saveAnalysisResult(AutoAnalysisConfigDetailVo vo){
        String configUniqueId = vo.getConfigUniqueId();
        AutoAnalysisConfigRelationsPo relationsPo = relationsMapper.selectByConfigUniqueId(configUniqueId);
        //如果当前配置一次自动分析没有执行 则起始时间按照配置时间 否则按照最后一次分析endTime（前提是没有修改配置）
        Date startTime = relationsPo == null ? vo.getStartTime() : relationsPo.getEndTime();
        //获取最后一次分析创建时间
        Date relatonCreateTime = relationsPo == null ? null : relationsPo.getCreateTime();
        //如果修改配置，则查询出该配置最后一次修改记录，判断修改时间在最后一次执行分析之后且在当前时间之前
        AutoAnalysisConfigDetailOptionRecordsPo optionRecordsPo = optionRecordsMapper.selectEditByCreateTime(configUniqueId);
        //获取最后一次修改配置时间
        Date optionCreateTime = optionRecordsPo == null ? null : optionRecordsPo.getCreateTime();
        //如果修改配置时间在最后一次分析之后，则重新计算开始时间，按照配置开始时间重新跑
        startTime = optionCreateTime != null
                && optionCreateTime.after(startTime)
                && relatonCreateTime != null
                && optionCreateTime.after(relatonCreateTime) ?  vo.getStartTime() : startTime;
        //获取数据结束日期
        Date endTime = DateUtils.addDays(startTime, vo.getIntervalDays());
        //如果数据结束日期在当前时间之后则不需要执行分析
        if(endTime.after(new Date())){
            return null;
        }
        //创建并保存分析结果
        AnalysisResultPo analysisResultPo = createAnalysisResultPo(vo.getFieldCode(),startTime,endTime);
        analysisResultMapper.insertSelective(analysisResultPo);
        //创建并保存关联关系
        AutoAnalysisConfigRelationsPo saveRelationsPo = createRelationsPo(configUniqueId, analysisResultPo.getBatchCode(),
                startTime, endTime);
        relationsMapper.insertSelective(saveRelationsPo);
        return saveRelationsPo;
    }

    /**
     * 创建分析结果
     * @param fieldCode
     * @return
     */
    private AnalysisResultPo createAnalysisResultPo(String fieldCode ,Date startTime ,Date endTime){
        //创建分析名称
        String analysisName = AUTO_ANALYSIS_NAME + "(" + DateUtils.convertDate2StringYMD(startTime) + "--" + DateUtils.convertDate2StringYMD(endTime) + ")";
        return new AnalysisResultPo().setAnalysisName(analysisName)
                .setSketch(analysisName)
                .setBatchCode(analysisService.createWindFieldBatchCode(fieldCode))
                .setFieldCode(fieldCode)
                .setOnOffCall(AnalysisConstants.ON_CALL)
                .setAnalysisFlag(AnalysisConstants.ANALYSIS_AUTO);
    }

    /**
     * 创建关联关系
     * @param configUniqueId
     * @param batchCode
     * @param startTime
     * @param endTime
     * @return
     */
    private AutoAnalysisConfigRelationsPo createRelationsPo( String configUniqueId, String batchCode,Date startTime, Date endTime) {
        return new AutoAnalysisConfigRelationsPo().setConfigUniqueId(configUniqueId)
                .setBatchCode(batchCode)
                .setStartTime(startTime)
                .setEndTime(endTime);
    }

    /**
     * 调用分析
     * @param relationsPo
     * @param fieldCode
     */
    private void analysis(AutoAnalysisConfigRelationsPo relationsPo,String fieldCode){
        AnalysisDto analysisDto = new AnalysisDto();
        //获取所有的分钟级/秒级分析类型
        List<AnalysisTypeVo> analysisTypeVo = analysisTypeMapper.selectAllVo();
        //构建分析类型标识
        Set<String> configAnalysis = analysisTypeVo.stream().filter(item-> StringUtils.endsWithAny(item.getTypeFlag(), AnalysisConstants.MINUTE,AnalysisConstants.SECEND))
                .map(item->constructTypeFlag(item)).collect(Collectors.toSet());

        //创建分析dto
        analysisDto.setAutoOrManual(AnalysisConstants.AUTO_ANALYSIS)
                .setPowerFarmID(fieldCode)
                .setDataBatchNum(relationsPo.getBatchCode())
                .setConfigAnalysis(configAnalysis.stream().collect(Collectors.toList()))
                .setBeginTime(DateUtils.convertDate2StringYMD(relationsPo.getStartTime()))
                .setEndTime(DateUtils.convertDate2StringYMD(relationsPo.getEndTime()));
        //调用分析
        analysisService.analysis(analysisDto);
    }

    /**
     * 构建分析类型标识
     * @return
     */
    private String constructTypeFlag(AnalysisTypeVo vo){
        String[] flags = vo.getTypeFlag().split(AnalysisConstants.CHAR_ESCAPE_SEPARATOR);
        return vo.getTypeCode() + AnalysisConstants.CHAR_SEPARATOR + flags[flags.length-1];
    }
}
