package com.njcn.prepare.harmonic.service.influxdb.impl;

import com.njcn.device.pms.api.MonitorClient;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.influx.deprecated.InfluxDBPublicParam;
import com.njcn.influx.pojo.po.DataI;
import com.njcn.influx.pojo.po.DataV;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.prepare.harmonic.pojo.dto.OverLimitFlagDTO;
import com.njcn.prepare.harmonic.pojo.param.LineParam;
import com.njcn.prepare.harmonic.service.influxdb.RStatWorkOrderCreateService;
import com.njcn.process.api.RStatWorkOrderFeignClient;
import com.njcn.system.enums.DicDataEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.dto.QueryResult;
import org.influxdb.impl.InfluxDBResultMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Description:
 * 接口文档访问地址：http://serverIP:port/swagger-ui.html
 * Date: 2023/2/10  15:43【需求编号】
 *
 * @author clam
 * @version V1.0.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RStatWorkOrderCreateServiceImpl implements RStatWorkOrderCreateService {

    private final InfluxDbUtils influxDbUtils;
    private final MonitorClient monitorClient;
    private final RStatWorkOrderFeignClient rStatWorkOrderFeignClient;
    @Override
    public void workOrderCreate(LineParam lineParam) {
        List<String> lineIds = lineParam.getLineIds ( );
        List<OverLimitFlagDTO> overLimitFlagDTOList = new ArrayList();
        String startTime = lineParam.getDataDate ()+" "+"00:00:00";
        String endTime = lineParam.getDataDate ()+" "+"23:59:59";
        lineIds.stream ().forEach (lineId->{

            Overlimit overlimit = monitorClient.getOverLimitData(lineId).getData ();
            List<DataV> dataV = getDataV(lineId,startTime,endTime);
            List<OverLimitFlagDTO> checkResultV = checkOverLimitV(dataV,overlimit);
            /*Datav3分钟一条数据连续4个小时越限说明OverLimitFlagDTO.overLimtFlag要连续80个是1才生成工单*/
            List<OverLimitFlagDTO> workOrderV = checkOverLimitFlag (checkResultV);
            for (OverLimitFlagDTO overLimitFlagDTO : workOrderV) {
                OverLimitFlagDTO result = new OverLimitFlagDTO ();
                BeanUtils.copyProperties (overLimitFlagDTO, result);
                result.setLineId (lineId);
                result.setOverLimtType (DicDataEnum.VOLTAGE_LIMIT.getCode ());
                overLimitFlagDTOList.add (result);
            }
            List<DataI> dataI = getDataI(lineId,startTime,endTime);
            List<OverLimitFlagDTO> checkResultI = checkOverLimitI(dataI,overlimit);
            List<OverLimitFlagDTO> workOrderI= checkOverLimitFlag (checkResultI);
            for (OverLimitFlagDTO overLimitFlagDTO : workOrderI) {
                OverLimitFlagDTO result = new OverLimitFlagDTO ();
                BeanUtils.copyProperties (overLimitFlagDTO, result);
                result.setLineId (lineId);
                result.setOverLimtType (DicDataEnum.CURRENT_LIMIT.getCode ());
                overLimitFlagDTOList.add (result);
            }

        });
        rStatWorkOrderFeignClient.createProblem (overLimitFlagDTOList);
    }
    /**
    * @Description: 对比监测一天的电流是否越限，越限返回1，未越限返回0
    * @Param: [dataI, overlimit]
    * @return: java.util.List<com.njcn.prepare.harmonic.pojo.dto.OverLimitFlagDTO>
    * @Author: clam
    * @Date: 2023/2/13
    */
    private List<OverLimitFlagDTO> checkOverLimitI(List<DataI> dataI, Overlimit overlimit) {
        List<OverLimitFlagDTO> result = new ArrayList<> ();
        dataI.stream ().forEach (datai ->{
            Integer temp = 0;

            for(int i=2 ;i<26;i++){

                    String vi = getFieldValueByFieldName("v"+i,datai);
                    String overLimiti= getFieldValueByFieldName("uharm"+i,overlimit);
                    if(Double.valueOf (vi)>Double.valueOf (overLimiti)){
                        temp = 1;
                        break;
                    }

            }
            OverLimitFlagDTO overLimitFlagDTO = new OverLimitFlagDTO();
            overLimitFlagDTO.setOverLimtFlag (temp);
            overLimitFlagDTO.setStartTime (LocalDateTime.ofInstant(datai.getTime (), ZoneId.systemDefault()));
            result.add (overLimitFlagDTO);
        });
        return  result;
    }

    /** Datav3分钟一条数据,每天480条数据连续4个小时越限说明OverLimitFlagDTO.overLimtFlag要连续80个是1才生成工单
    * @Description: checkOverLimitFlag
    * @Param: [checkResult]
    * @return: java.util.List<com.njcn.prepare.harmonic.pojo.dto.OverLimitFlagDTO>
    * @Author: clam
    * @Date: 2023/2/13
    */
    private List<OverLimitFlagDTO> checkOverLimitFlag(List<OverLimitFlagDTO> checkResult) {
        List<OverLimitFlagDTO> result = new ArrayList<> ();
        int temp = checkResult.size ()-40;
        for (int i=0;i<temp;i++){
            List<OverLimitFlagDTO> collect = checkResult.stream ( ).skip (i).limit (80).collect (Collectors.toList ( ));
            int sum = collect.stream ( ).mapToInt (OverLimitFlagDTO::getOverLimtFlag).sum ( );
            if(sum==80){
            /*sum==80连续4个小时越限生成工单，统计越限时间*/
                OverLimitFlagDTO overLimitFlagDTO = new OverLimitFlagDTO();
                overLimitFlagDTO.setStartTime (checkResult.get (i).getStartTime ());
               Integer temp2 =i+80;
                while(checkResult.get (temp2).getOverLimtFlag ()==1){
                    temp2++ ;
                    if(temp2==checkResult.size ()-1){
                        break;
                    }
                }
                overLimitFlagDTO.setEndTime (checkResult.get (temp2-1).getStartTime ());
                i=temp2;
                result.add (overLimitFlagDTO);
            }
        }

        return result;
    }

    /**
    * @Description: 对比监测一天的电压是否越限，越限返回1，未越限返回0
    * @Param: [dataV, overlimit]
    * @return: java.lang.String[]
    * @Author: clam
    * @Date: 2023/2/13
    */
    private List<OverLimitFlagDTO> checkOverLimitV(List<DataV> dataV, Overlimit overlimit) {
        List<OverLimitFlagDTO> result = new ArrayList<> ();
        dataV.stream ().forEach (datav ->{
            Integer temp = 0;

            for(int i=1 ;i<26;i++){
                if(i==1){
                    if(datav.getVThd ()>overlimit.getUaberrance ()){
                        temp = 1;
                        break;
                    }
                }else {
                    String vi = getFieldValueByFieldName("v"+i,datav);
                    String overLimiti= getFieldValueByFieldName("uharm"+i,overlimit);
                    if(Double.valueOf (vi)>Double.valueOf (overLimiti)){
                        temp = 1;
                        break;
                    }
                }
            }
            OverLimitFlagDTO overLimitFlagDTO = new OverLimitFlagDTO();
            overLimitFlagDTO.setOverLimtFlag (temp);
            overLimitFlagDTO.setStartTime (LocalDateTime.ofInstant(datav.getTime (), ZoneId.systemDefault()));
            result.add (overLimitFlagDTO);
        });
        return  result;
    }

    /**
     * 功能描述:获取dataVCP95值数据
     * @author xy
     * @param lineIndex    监测点集ID
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @date 2022/5/10 14:56
     * @return List<DataV>
     */
    public List<DataV> getDataV(String lineIndex, String startTime, String endTime){
        List<DataV> result = new ArrayList<> ();

        //CP95值
        StringBuilder stringBuilder7 = new StringBuilder();
        StringBuilder stringBuilder8 = new StringBuilder();
        stringBuilder7.append("MAX(v_thd) AS v_thd,");
        for (int i = 2; i <=25 ; i++) {
            if (i==25){
                stringBuilder7.append("MAX(v_").append(i).append(") AS v_").append(i);
            } else {
                stringBuilder7.append("MAX(v_").append(i).append(") AS v_").append(i).append(",");
            }
        }
        stringBuilder8.append ("line_id='").append (lineIndex).append ("' and ").append(InfluxDBPublicParam.TIME + " >= '").append(startTime).append("' and ").append(InfluxDBPublicParam.TIME).append(" <= '").append(endTime).append("' and value_type = 'CP95' group by time(3m) fill(0)").append(InfluxDBPublicParam.TIME_ZONE);
        String sql4 = "select "+stringBuilder7+" from "+ InfluxDBPublicParam.DATA_V+" where "+stringBuilder8;
        QueryResult sqlResult4 = influxDbUtils.query(sql4);
        InfluxDBResultMapper resultMapper4 = new InfluxDBResultMapper();
        List<DataV> list4 = resultMapper4.toPOJO(sqlResult4, DataV.class);
        list4.forEach(item->{
            item.setValueType("CP95");
        });
        result.addAll(list4);
        return result;
    }

    /**
     * 功能描述:获取dataI CP95数据
     * @author xy
     * @param lineIndex    监测点ID
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @date 2022/5/10 14:56
     * @return List<DataI>
     */
    public List<DataI> getDataI(String lineIndex, String startTime, String endTime){
        List<DataI> result = new ArrayList<>();

        //CP95值
        StringBuilder stringBuilder7 = new StringBuilder();
        StringBuilder stringBuilder8 = new StringBuilder();
        for (int i = 2; i <=25 ; i++) {
            if (i==25){
                stringBuilder7.append("MAX(i_").append(i).append(") AS i_").append(i);
            } else {
                stringBuilder7.append("MAX(i_").append(i).append(") AS i_").append(i).append(",");
            }
        }
        stringBuilder8.append ("line_id='").append (lineIndex).append ("' and ").append(InfluxDBPublicParam.TIME + " >= '").append(startTime).append("' and ").append(InfluxDBPublicParam.TIME).append(" <= '").append(endTime).append("' and value_type = 'CP95' group by time(3m) fill(0)").append(InfluxDBPublicParam.TIME_ZONE);
        String sql4 = "select "+stringBuilder7+" from "+ InfluxDBPublicParam.DATA_I+" where "+stringBuilder8;
        QueryResult sqlResult4 = influxDbUtils.query(sql4);
        InfluxDBResultMapper resultMapper4 = new InfluxDBResultMapper();
        List<DataI> list4 = resultMapper4.toPOJO(sqlResult4, DataI.class);
        list4.forEach(item->{
            item.setValueType("CP95");
        });
        result.addAll(list4);
        return result;
    }

    /**
     * 根据属性名获取属性值
     *
     * @param fieldName
     * @param object
     * @return
     */
    private String getFieldValueByFieldName(String fieldName, Object object) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            //设置对象的访问权限，保证对private的属性的访问
            field.setAccessible(true);
            return  field.get(object)+"";
        } catch (Exception e) {

            return null;
        }
    }


}
