package com.huatek.busi.service.impl.gis;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.huatek.busi.common.BusiConstant;
import com.huatek.busi.common.SiteConstants;
import com.huatek.busi.entity.*;
import com.huatek.busi.service.*;
import com.huatek.busi.service.gis.*;
import com.huatek.busi.service.impl.gis.gisAssessment.*;
import com.huatek.busi.service.impl.gis.gisAssessment.GisAssessmentCalculate;
import com.huatek.busi.service.param.BusiParamGisService;
import com.huatek.busi.service.substation.SubstationMicGisService;
import com.huatek.busi.service.transformer.TransformerPdStatisticsService;
import com.huatek.busi.task.transformer.TransformerDateOnlineService;
import com.huatek.busi.task.transformer.TransfromerCreateUtil;
import com.huatek.busi.util.*;
import com.huatek.busi.vo.*;
import com.huatek.frame.base.util.BeanUtils;
import com.huatek.frame.base.util.Constants;
import com.huatek.torch.util.uuid.Uuid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Component
@Service(interfaceClass = GisAssessService.class)
@Transactional(rollbackFor = Exception.class)
public class GisAutoAssessServiceImpl implements GisAssessService {

    @Reference(check = false)
    ICalculateStepService calculateStepService;

    @Autowired
    private BusiParamGisService busiParamGisService;

    @Autowired
    private GisMechanicalPropertiesService gisMechanicalPropertiesService;

    @Autowired
    private BusiOfflineGisBrandService busiOfflineGisBrandService;

    @Autowired
    private BusiOfflineGisRepairService busiOfflineGisRepairService;

    @Autowired
    private IecBreakerParamService iecBreakerParamService;

    @Autowired
    private SubstationMicGisService substationMicGisService;

    @Autowired
    private RptGisMonitorSf6ChartsService rptGisMonitorSf6ChartsService;

    @Autowired
    private TransformerPdStatisticsService transformerPdStatisticsService;

    @Autowired
    private GisAssessmentResultService gisAssessmentResultService;

    @Autowired
    private GisAssessmentResultDataService gisAssessmentResultDataService;

    @Reference(check = false)
    ILabReportMarkStatisticService labReportMarkStatisticService;

    @Value("${dataoutput.base.path}")
    private String basePath2;

    public static GisFormulaCal gisFormulaCalInstance = GisFormulaCal.getInstance();

    @Autowired
    private BusiSiteTreeService busiSiteTreeService;

    @Autowired
    private TransformerDateOnlineService transformerDateOnlineService;

    @Reference(check = false)
    BusiSemiAutomaticEvaluateDataService busiSemiAutomaticEvaluateDataService;

    @Reference(check = false)
    BusiSemiAutomaticEvaluateConfigService busiSemiAutomaticEvaluateConfigService;

    @Override
    public void assessmentForGis(List<BusiTreeNodeVo> list) {

        Boolean semiAutomaticMark = isSemiAuto();

        for (BusiTreeNodeVo vo : list) {
            // Gis评估结果
            GisAssessmentResult gisAssessmentResult = new GisAssessmentResult();
            // 通过systemCode查找 GIS标牌信息
            BusiOfflineGisBrandVo busiOfflineGisBrandVo = busiOfflineGisBrandService.findBusiOfflineGISBrand(vo.getSiteId(), vo.getId());
            if (ObjectUtil.isEmpty(busiOfflineGisBrandVo)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-标牌数据-数据为空", vo.getId(), vo.getName());
                continue;
            }
            String gisId = busiOfflineGisBrandVo.getId();
            String gisName = busiOfflineGisBrandVo.getGisName();
            String mainEquipmentId = busiOfflineGisBrandVo.getMainEquipmentId();
            // 组织文件名
            DateTimeFormatter dateTimeFormater2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDate localDate = LocalDate.now();
            String date = dateTimeFormater2.format(localDate);
            String fileName = gisName + "_" + date + ".xml";
            log.info("--->> GIS名称：{}, id：{}", gisName, gisId);

            // 获取最新的gis评测数据
            List<IecBreakerParam> iecBreakerParams;
            GisAssessmentResultData gisAssessmentResultData = gisAssessmentResultDataService.findGisAssessmentResultDataByGisId(gisId);
            if (ObjectUtil.isEmpty(gisAssessmentResultData)) {
                // GIS断开数据
                iecBreakerParams = iecBreakerParamService.findIecBreakerParam(vo.getSiteId(), vo.getId());
            } else {
                //获取前一天的断开数据
                iecBreakerParams = iecBreakerParamService.findIecBreakerParamNow(vo.getSiteId(), vo.getId(), localDate.plusDays(-1));
            }

            // 获取Gis的权重系数维护表
            Map<String, BusiParamTransformerVo> busiParamGisMap = new HashMap<>();
            String number = null;
            List<BusiParamTransformerVo> busiParamGisVo = busiParamGisService.findBusiParamGisWeights(vo.getSiteId(), vo.getId());
            if (!busiParamGisVo.isEmpty()) {
                busiParamGisMap = GisAssessUtilsNew.busiParamGisList2Map(busiParamGisVo);
                number = busiParamGisVo.get(0).getNumber().toString();
            }

            int step = 0;
            CalculateStep calculateStep = new CalculateStep();
            calculateStep.setId(Uuid.getUUID());
            calculateStep.setSiteId(vo.getSiteId());
            calculateStep.setEquipmentType(SiteConstants.GIS);
            calculateStep.setMainEquipmentId(mainEquipmentId);
            calculateStep.setExecuteMode(Integer.valueOf(Constants.DEFAULT_YES));
            calculateStep.setCreateTime(LocalDateTime.now());
            calculateStep.setNumber(number);

            // 机械特性数据
            GisMechanicalPropertiesVo gisMechanical = gisMechanicalPropertiesService.lastGisMechanicalProperties(vo.getSiteId(), vo.getId());
            if (ObjectUtil.isEmpty(gisMechanical)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-机械特性-数据为空", vo.getId(), vo.getName());
                continue;
            }
            // sf6压力，微水数据
            List<RptGisMonitorSf6Charts> rptGisMonitorSf6Chartses = rptGisMonitorSf6ChartsService.findRptGisMonitorSf6Chartses(vo.getSiteId(), vo.getId());
            if (CollectionUtil.isEmpty(rptGisMonitorSf6Chartses)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-sf6压力，微水数据-数据为空", vo.getId(), vo.getName());
                continue;
            }
            // 局放量，局放次数数据
            TransformerPdStatistics transformerGisPdStatistics = transformerPdStatisticsService.findTransformerGisPdStatistics(vo.getSiteId(), vo.getId());
            if (ObjectUtil.isEmpty(transformerGisPdStatistics)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-局放量，局放次数数据-数据为空", vo.getId(), vo.getName());
                continue;
            }
            // 离线报告数据
            List<LabReportMarkStatistic> labReportMarkStatisticList = labReportMarkStatisticService.findAllManualAssessmentData(vo.getId());
            if (CollectionUtil.isEmpty(labReportMarkStatisticList)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-离线报告数据-数据为空", vo.getId(), vo.getName());
                continue;
            }
            // 温度湿度统计数据
            SubstationMicGisVo substationMicGis = substationMicGisService.findSubstationMicGis(vo.getSiteId(), vo.getId());
            if (ObjectUtil.isEmpty(substationMicGis)) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-温度湿度统计数据-数据为空", vo.getId(), vo.getName());
                continue;
            }
            //检修数据
            List<BusiOfflineGisRepairVo> gisRepair = new ArrayList<>();
            gisRepair = busiOfflineGisRepairService.findBusiOfflineGisRepair(vo.getSiteId(), vo.getId());
//            if (CollectionUtil.isEmpty(gisRepair)) {
//                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-检修数据-数据为空", vo.getId(), vo.getName());
//                continue;
//            }
            // 离线报告数据
            Map<String, String> gisDataMap = GisAssessmentCalculate.getAllData(labReportMarkStatisticList);

            // 半自动评估时使用录入数据(断开电流、断开次数)
            BusiSemiAutomaticEvaluateDataVo latestSemiAutomaticEvaluateData = null;
            if(semiAutomaticMark){
                latestSemiAutomaticEvaluateData = busiSemiAutomaticEvaluateDataService.getLatest(BusiConstant.EqType.EQ_TYPE2,mainEquipmentId, vo.getSiteId());
                if (latestSemiAutomaticEvaluateData == null) {
                    log.error("--->> GIS:[{}],未录入半自动评测数据", gisName);
                    transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, "GIS评测-未录入半自动评测数据", vo.getId(), vo.getName());
                    continue;
                }
            }

            /*************************************开断磨损计算**************************************/
            Map<String, String> kdmsResult;
            if(semiAutomaticMark){
                kdmsResult = GisKDMSCalculate.calculateSemiAutoKDMS(busiParamGisMap, busiOfflineGisBrandVo, gisAssessmentResultData, step,latestSemiAutomaticEvaluateData);
            }else{
                kdmsResult = GisKDMSCalculate.calculateAutoKDMS(busiParamGisMap, busiOfflineGisBrandVo, iecBreakerParams, gisAssessmentResultData, step);
            }
            if (kdmsResult.get("warnMsg") != null) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, kdmsResult.get("warnMsg"), vo.getId(), vo.getName());
                continue;
            }
            step = Integer.parseInt(kdmsResult.get("step"));

            /*************************************运行数据计算**************************************/
            Map<String, String> yxsjResult = GisYXSJCalculate.calculateAutoYXSJ(busiParamGisMap, gisMechanical, step);
            if (yxsjResult.get("warnMsg") != null) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, yxsjResult.get("warnMsg"), vo.getId(), vo.getName());
                continue;
            }
            step = Integer.parseInt(yxsjResult.get("step"));

            /*************************************运行数据-电气试验计算**************************************/
            // 使用离线数据
            Map<String, String> yxsjdqsyResult = GisYXSJDQSYCalculate.calculateYXSJDQSY(busiParamGisMap, gisDataMap, step, "2");
            if (yxsjdqsyResult.get("warnMsg") != null) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, yxsjdqsyResult.get("warnMsg"), vo.getId(), vo.getName());
                continue;
            }
            step = Integer.parseInt(yxsjdqsyResult.get("step"));

            /*************************************绝缘介质-SF6在线数据计算**************************************/
            Map<String, String> sf6Result = GisSf6Calculate.calculateAutoSf6(busiParamGisMap, rptGisMonitorSf6Chartses, transformerGisPdStatistics, step);
            if (sf6Result.get("warnMsg") != null) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, sf6Result.get("warnMsg"), vo.getId(), vo.getName());
                continue;
            }
            step = Integer.parseInt(sf6Result.get("step"));

            /*************************************运行参数计算**************************************/
            Map<String, String> yxcsResult = GisYXCSCalculate.calculateAutoYXCS(busiParamGisMap, substationMicGis, gisRepair, gisDataMap, busiOfflineGisBrandVo, step);
            if (yxcsResult.get("warnMsg") != null) {
                transformerDateOnlineService.warringEvaluating(SiteConstants.GIS, BusiConstant.GzType.GZ_TYPE25, yxcsResult.get("warnMsg"), vo.getId(), vo.getName());
                continue;
            }
            step = Integer.parseInt(yxcsResult.get("step"));


            String score = "100";
            if (busiParamGisVo.size() > 11) {
                score = Math.round(Double.parseDouble(new BigDecimal(kdmsResult.get(GisCreateUtil.BREAKING_WEAR)).add(new BigDecimal(yxsjResult.get(GisCreateUtil.OPERATIONAL_DATA))).add(new BigDecimal(yxsjdqsyResult.get(GisCreateUtil.OPERATION_PARAMETERS_DQSY))).add(new BigDecimal(sf6Result.get(GisCreateUtil.INSULATING_MEDIUM))).add(new BigDecimal(yxcsResult.get(GisCreateUtil.OPERATION_PARAMETERS))).multiply(BigDecimal.valueOf(100)).setScale(4, RoundingMode.HALF_UP) + "")) + "";
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("开断磨损", new BigDecimal(kdmsResult.get(GisCreateUtil.BREAKING_WEAR)).setScale(4, RoundingMode.HALF_UP).toString());
                jsonObject.put("运行数据", new BigDecimal(yxsjResult.get(GisCreateUtil.OPERATIONAL_DATA)).setScale(4, RoundingMode.HALF_UP).toString());
                jsonObject.put("运行数据-电气试验", new BigDecimal(yxsjdqsyResult.get(GisCreateUtil.OPERATION_PARAMETERS_DQSY)).setScale(4, RoundingMode.HALF_UP).toString());
                jsonObject.put("绝缘介质-SF6在线数据", new BigDecimal(sf6Result.get(GisCreateUtil.INSULATING_MEDIUM)).setScale(4, RoundingMode.HALF_UP).toString());
                jsonObject.put("运行参数", new BigDecimal(yxcsResult.get(GisCreateUtil.OPERATION_PARAMETERS)).setScale(4, RoundingMode.HALF_UP).toString());

                // step 18 结果
                step += 1;
                EvaluationNameUtil.setSpecialStep(step, null, score + "%", jsonObject, "最终结果");
                log.info("score::" + score);
            }

            Map<String, String> healthResult = GisAssessmentCalculate.formHealthResult(Convert.str2BigDecimal(score));

            String uuid = Uuid.getUUID();
            // 14-累计断开次数
            String sydkcs;
            if(semiAutomaticMark){
                sydkcs = new BigDecimal("14").subtract(latestSemiAutomaticEvaluateData.getBreakTimes()).toString();
            } else {
                sydkcs = new BigDecimal("14").subtract(new BigDecimal(kdmsResult.get(GisCreateUtil.CUMULATIVE_ACTION_TIMES))).toString();
            }

            log.info("预期剩余断开次数：" + sydkcs);
            log.info("健康水平：" + healthResult.get("gisStatus"));
            log.info("检修建议：" + healthResult.get("jxjy"));
            log.info("健康水平说明：" + healthResult.get("healthLevelExplain"));
            gisAssessmentResult = GisAssessmentCalculate.formGisAssessmentResult(uuid, vo.getSiteId(), vo.getId(), score, healthResult.get("gisStatus"), healthResult.get("healthLevelExplain"), kdmsResult, busiOfflineGisBrandVo, sydkcs, healthResult.get("jxjy"), "2");
            gisAssessmentResultService.saveGisAssessmentResult(gisAssessmentResult);

            GisAssessmentResultData result = GisAssessmentCalculate.formResult(kdmsResult, yxsjResult, sf6Result, yxcsResult, uuid, gisId, gisName, score, healthResult.get("gisStatus"), sydkcs, healthResult.get("jxjy"));
            gisAssessmentResultDataService.save(result);

            // 临时注释，调测后放开
            GisCreateUtil.createFile(result, true, basePath2, GisCreateUtil.FILE_PATH, fileName, date);

            // 新增算法步骤
            calculateStep.setStepJson(EvaluationNameUtil.listToJson());
            calculateStep.setPId(uuid);
            calculateStepService.insert(calculateStep);

        }
    }

    @Override
    public void semiAutoAssessmentForGis(String siteId , String mainTreeId) {
        BusiTreeNodeVo busiTreeNodeVo = new BusiTreeNodeVo();
        BusiSiteTree busiSiteTree = busiSiteTreeService.findByPK(mainTreeId);
        BeanUtils.copyPropertiesWithIgnoreNull(busiSiteTree,busiTreeNodeVo);
        List<BusiTreeNodeVo> list = Collections.singletonList(busiTreeNodeVo);
        assessmentForGis(list);
    }

    private boolean isSemiAuto(){
        BusiSemiAutomaticEvaluateConfigVo newestConfig = busiSemiAutomaticEvaluateConfigService.findNewestConfig();
        return newestConfig != null && "1".equals(newestConfig.getMark());
    }
}
