package com.hdkj.lt.si.service.simulation.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.hdkj.lt.base.constants.ErrorLogConstant;
import com.hdkj.lt.base.enums.EventTypeEnum;
import com.hdkj.lt.base.enums.OperationStepEnum;
import com.hdkj.lt.base.exception.ExceptionCast;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultAwaitTransferAreaResult;
import com.hdkj.lt.core.bizms.modle.po.fault.FaultPowerCut;
import com.hdkj.lt.core.bizms.modle.po.operationAbnormality.FhzgOperationAbnormalityTransferAreaResult;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanPowerCut;
import com.hdkj.lt.core.bizms.modle.po.plan.FhzgPlanPowerCutSwitch;
import com.hdkj.lt.core.bizms.modle.po.plan.PlanAwaitTransferAreaResultPO;
import com.hdkj.lt.core.log.exception.ExceptionErrorLogCast;
import com.hdkj.lt.core.log.model.param.ErrorLogParam;
import com.hdkj.lt.modle.dto.simulation.ElectricalModelRequest;
import com.hdkj.lt.modle.dto.simulation.ElectricalModelResponse;
import com.hdkj.lt.modle.dto.simulation.FaultTransferSchemeDTO;
import com.hdkj.lt.modle.dto.simulation.OperationSchemeDTO;
import com.hdkj.lt.modle.dto.simulation.PlanTransferSchemeDTO;
import com.hdkj.lt.si.dao.*;
import com.hdkj.lt.si.service.simulation.ISimulationService;
import com.hdkj.lt.si.service.simulation.TyptResponseEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;

/**
 * @author rj
 * @date 2025/5/26 下午4:21
 * @description
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SimulationServiceImpl implements ISimulationService {


    private final FaultPowerCutMapper faultPowerCutMapper;
    private final PlanPowerCutMapper planPowercutMapper;
    private final PlanAwaitTransferAreaResultMapper planAwaitTransferAreaResultMapper;
    private final FaultAwaitTransferAreaResultMapper faultAwaitTransferAreaResultMapper;
    private final FhzgOperationAbnormalityTransferAreaResultMapper operationAbnormalityTransferAreaResultMapper;
    private final String BASE_URL = "http://25.91.83.252:28081";

    @Value("${simulation.xToken}")
    private String xToken;

    @Autowired
    @Qualifier("simpleRestTemplate")
    private RestTemplate simpleRestTemplate;

    @Override
    public String getPlanTransferScheme(PlanTransferSchemeDTO planTransferSchemeDTO) {
        String url = BASE_URL + "/api/power/power-transfer/plan-analysis";
        log.info("开始时间" + LocalDateTime.now().toString());
        PlanTransferSchemeDTO.LoopCheckRule loopCheckRule = new PlanTransferSchemeDTO.LoopCheckRule();
        FhzgPlanPowerCut powerCut = planPowercutMapper.selectById(planTransferSchemeDTO.getPlanId());
        loopCheckRule.setLoopIMargin(120);
        loopCheckRule.setAngleDifMargin(15);
        loopCheckRule.setVolDifMargin(5);
        loopCheckRule.setFeederLoadRate(80);
        planTransferSchemeDTO.setLoopCheckRule(loopCheckRule);
        log.info("计划：{} --请求推演平台参数：{}", planTransferSchemeDTO.getPlanId(), JSON.toJSONString(planTransferSchemeDTO));
        FhzgPlanPowerCutSwitch planPowerCutSwitch = new FhzgPlanPowerCutSwitch();
        planPowerCutSwitch.setPlanId(planTransferSchemeDTO.getPlanId());
        planPowerCutSwitch.setAnalysisJson(JSON.toJSONString(planTransferSchemeDTO));
        planPowercutMapper.saveAnalysisJson(planPowerCutSwitch);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("x-token", xToken);
        HttpEntity<String> requestEntity = new HttpEntity<>(JSON.toJSONString(planTransferSchemeDTO), headers);
        TyptResponseEntity rs = simpleRestTemplate.postForObject(url, requestEntity, TyptResponseEntity.class);
        log.info("计划-推演平台结果：{}", JSONObject.toJSONString(rs.getSuccess()));
        if (rs.getSuccess()) {
            LambdaUpdateWrapper<PlanAwaitTransferAreaResultPO> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(PlanAwaitTransferAreaResultPO::getPlanId, planTransferSchemeDTO.getPlanId());
            planAwaitTransferAreaResultMapper.delete(wrapper);
            //保存结果
            PlanAwaitTransferAreaResultPO po = new PlanAwaitTransferAreaResultPO();
            po.setPlanId(planTransferSchemeDTO.getPlanId());
            po.setTransferAreaJson(JSON.toJSONString(rs, SerializerFeature.WriteMapNullValue));
            planAwaitTransferAreaResultMapper.insert(po);
            log.info(LocalDateTime.now().toString());
            return "true";
        } else {
            ErrorLogParam errorLogParam = new ErrorLogParam()
                    .setErrorTime(LocalDateTime.now())
                    .setEventType(EventTypeEnum.PLAN.getCode())
                    .setEventId(powerCut.getPlanNo())
                    .setErrorCategory("计算推演平台调用失败")
                    .setErrorLevel("Warning")
                    .setSourceSystem("1")
                    .setOperationStep("调用计算推演平台")
                    .setRelatedId(planTransferSchemeDTO.getPlanId().toString())
                    .setStage("4")
                    .setRelatedCategory("fhzg_plan_power_cut")
                    .setDetails("计划id：" + planTransferSchemeDTO.getPlanId() + " 请求推演平台返回报错，请求参数：")
                    .setAdditionalInfo(JSONObject.toJSONString(planTransferSchemeDTO));
            ExceptionErrorLogCast.cast(errorLogParam);
            ExceptionCast.cast("计划-推演平台方案生成失败");
            return Boolean.toString(rs.getSuccess());
        }
    }

    @Override
    public String getFaultTransferScheme(FaultTransferSchemeDTO faultTransferSchemeDTO) {
        String url = BASE_URL + "/api/power/power-transfer/analysis";
        Long faultId = faultTransferSchemeDTO.getFaultId();
        log.info("故障：{} --请求推演平台参数：{}", faultId, faultTransferSchemeDTO.getFaultTransferSchemeParam());
        LocalDateTime start = LocalDateTime.now();
        long startTime = System.currentTimeMillis();
        TyptResponseEntity rs;
        String callTime;
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            httpHeaders.set("x-token", xToken);
            HttpEntity<String> httpEntity = new HttpEntity<>(faultTransferSchemeDTO.getFaultTransferSchemeParam(), httpHeaders);
            rs = simpleRestTemplate.postForObject(url, httpEntity, TyptResponseEntity.class);
        } finally {
            long cost = System.currentTimeMillis() - startTime;
            double minutes = cost / 60000.0;
            callTime = String.format("%.2f", minutes);
        }
        LambdaUpdateWrapper<FaultAwaitTransferAreaResult> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(FaultAwaitTransferAreaResult::getFaultId, faultId);
        faultAwaitTransferAreaResultMapper.delete(wrapper);
        FaultPowerCut faultPowerCut = new FaultPowerCut();
        faultPowerCut.setId(faultId);
        faultPowerCut.setSchemeCreateTime(start);
        faultPowerCut.setSchemeCreateDuration(callTime);
        if (rs == null) {
            faultPowerCut.setPowerOnSuccess(3);
        } else if (!rs.getSuccess()) {
            faultPowerCut.setPowerOnSuccess(3);
        }
        faultPowerCutMapper.updateById(faultPowerCut);
        //保存结果
        FaultAwaitTransferAreaResult po = new FaultAwaitTransferAreaResult();
        po.setFaultId(faultId);
        po.setTransferAreaJson(JSONObject.toJSONString(rs, SerializerFeature.WriteMapNullValue));
        po.setCreateTime(LocalDateTime.now());
        faultAwaitTransferAreaResultMapper.insert(po);
        if (rs != null && rs.getSuccess()) {
            log.info("故障：{} --推演平台结果：{}", faultId, JSON.toJSONString(rs));
        } else {
            ErrorLogParam errorLogParam = new ErrorLogParam()
                    .setErrorTime(LocalDateTime.now())
                    .setEventType(EventTypeEnum.FAULT.getCode())
                    .setEventId(faultId.toString())
                    .setStage(ErrorLogConstant.Stage.GET_FAULT)
                    .setSourceSystem(ErrorLogConstant.SourceSystem.FHZG)
                    .setOperationStep(OperationStepEnum.FAULT.getName())
                    .setErrorCategory("推演平台返回报错")
                    .setDetails("故障id：" + faultTransferSchemeDTO.getFaultId() + " 请求推演平台返回报错，请求参数：" + faultTransferSchemeDTO.getFaultTransferSchemeParam());
            ExceptionErrorLogCast.cast(errorLogParam);
        }
        return JSON.toJSONString(rs);
    }

    @Override
    public String getOperationScheme(OperationSchemeDTO operationSchemeDTO) {
        if (operationSchemeDTO.getId() == null) {
            log.info("缺少调优事件id");
            return "缺少调优事件id";
        }
        Long oaID = operationSchemeDTO.getOaID();
        operationSchemeDTO.setOaID(null);
        String url = BASE_URL + "/api/power/operationMode/queryResult?id={id}";
        log.info("调优-请求推演平台参数：{}", JSON.toJSONString(operationSchemeDTO));
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.set("x-token", xToken);
        HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
        TyptResponseEntity rs = simpleRestTemplate.exchange(url, HttpMethod.GET,httpEntity,TyptResponseEntity.class,operationSchemeDTO.getId()).getBody();
        log.info("调优-推演平台结果：{}", JSONObject.toJSONString(rs.getSuccess()));
        if (rs.getSuccess()) {
            operationAbnormalityTransferAreaResultMapper.delete(new LambdaUpdateWrapper<FhzgOperationAbnormalityTransferAreaResult>().eq(FhzgOperationAbnormalityTransferAreaResult::getOaId, operationSchemeDTO.getId()));
            FhzgOperationAbnormalityTransferAreaResult fhzgOperationAbnormalityTransferAreaResult = new FhzgOperationAbnormalityTransferAreaResult();
            fhzgOperationAbnormalityTransferAreaResult.setOaId(oaID);
            fhzgOperationAbnormalityTransferAreaResult.setTransferAreaJson(JSONObject.toJSONString(rs));
            operationAbnormalityTransferAreaResultMapper.insert(fhzgOperationAbnormalityTransferAreaResult);
            return "true";
        } else {
            ErrorLogParam errorLogParam = new ErrorLogParam()
                    .setErrorTime(LocalDateTime.now())
                    .setEventType(EventTypeEnum.PLAN.getCode())
                    .setEventId(operationSchemeDTO.getId())
                    .setErrorCategory("运行调优计算推演平台调用失败")
                    .setErrorLevel("Warning")
                    .setSourceSystem("1")
                    .setOperationStep("调用计算推演平台")
                    .setRelatedId(operationSchemeDTO.getId())
                    .setStage("6")
                    .setRelatedCategory("fhzg_grid_operation_abnormality")
                    .setDetails("运行调优id：" + operationSchemeDTO.getId() + " 请求推演平台返回报错，请求参数：")
                    .setAdditionalInfo(JSON.toJSONString(operationSchemeDTO.getId()));
            ExceptionErrorLogCast.cast(errorLogParam);
            ExceptionCast.cast("运行调优-推演平台方案生成失败");
            return Boolean.toString(rs.getSuccess());
        }
    }

    @Override
    public String getElectricalModel(ElectricalModelRequest request) {
        // TODO: 配置化接口地址
        String url = BASE_URL + "/api/power/electrical-model/query";
        log.info("配网电气模型查询-请求参数：{}", JSON.toJSONString(request));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        // TODO: 配置化接口鉴权
        headers.set("x-token", xToken);

        HttpEntity<String> requestEntity = new HttpEntity<>(JSON.toJSONString(request), headers);
        try {
            String responseStr = simpleRestTemplate.postForObject(url, requestEntity, String.class);
            log.info("配网电气模型查询-响应：{}", responseStr);
            return responseStr;
        } catch (Exception e) {
            log.error("配网电气模型查询失败", e);
            ErrorLogParam errorLogParam = new ErrorLogParam()
                    .setErrorTime(LocalDateTime.now())
                    .setEventType(EventTypeEnum.PLAN.getCode())
                    .setEventId(request.getCityId())
                    .setErrorCategory("配网电气模型接口调用失败")
                    .setErrorLevel("Warning")
                    .setSourceSystem("1")
                    .setOperationStep("调用配网电气模型接口")
                    .setRelatedId(request.getCityId())
                    .setStage("7")
                    .setRelatedCategory("electrical_model")
                    .setDetails("配网电气模型查询失败，请求参数：" + JSON.toJSONString(request))
                    .setAdditionalInfo(e.getMessage());
            ExceptionErrorLogCast.cast(errorLogParam);
            throw new RuntimeException("配网电气模型查询失败: " + e.getMessage(), e);
        }
    }

}
