package com.njcn.csharmonic.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.reflect.TypeToken;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.csdevice.api.*;
import com.njcn.csdevice.pojo.po.CsEquipmentDeliveryPO;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.csdevice.pojo.vo.DataArrayTreeVO;
import com.njcn.csdevice.pojo.vo.LineTargetVO;
import com.njcn.csharmonic.pojo.dto.ZuTaiDTO;
import com.njcn.csharmonic.pojo.dto.ZuTaiNewDTO;
import com.njcn.csharmonic.pojo.vo.CsRtDataVO;
import com.njcn.csharmonic.service.CsPagePOService;
import com.njcn.csharmonic.service.ILineTargetService;
import com.njcn.csharmonic.util.InfluxDbParamUtil;
import com.njcn.cssystem.enums.CsSystemResponseEnum;
import com.njcn.influx.pojo.dto.StatisticalDataDTO;
import com.njcn.influx.service.CommonService;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.api.EpdFeignClient;
import com.njcn.system.enums.DicDataEnum;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类的介绍：
 *
 * @author xuyang
 * @version 1.0.0
 * @createTime 2023/6/1 10:11
 */
@Service
@AllArgsConstructor
@Slf4j
public class LineTargetServiceImpl implements ILineTargetService {

    private final CsLedgerFeignClient csLedgerFeignClient;

    private final DevModelRelationFeignClient devModelRelationFeignClient;

    private final DataSetFeignClient dataSetFeignClient;

    private final DataArrayFeignClient dataArrayFeignClient;

    private final FileStorageUtil fileStorageUtil;

    private final CsPagePOService csPagePOService;

    private final EpdFeignClient epdFeignClient;

    private final CommonService commonService;

    private final CsLineFeignClient csLineFeignClient;

    private final DicDataFeignClient dicDataFeignClient;

    private final InfluxDbParamUtil influxDbParamUtil;

    private final EquipmentFeignClient equipmentFeignClient;

    @Override
    public List<DataArrayTreeVO> getLineTarget(String lineId) {
        List<String> setList = new ArrayList<>();
        String devId = csLedgerFeignClient.findDevByLineId(lineId).getData();
        //1.获取监测点的安装位置
        List<CsLinePO> lineList = csLineFeignClient.queryLineById(Collections.singletonList(lineId)).getData();
        if (CollectionUtils.isEmpty(lineList)){
            return new ArrayList<DataArrayTreeVO>();
        }
        CsLinePO line = csLineFeignClient.queryLineById(Collections.singletonList(lineId)).getData().get(0);
        String code = dicDataFeignClient.getDicDataById(line.getPosition()).getData().getCode();
        String modelId = null;
        List<LineTargetVO> dataSetList = new ArrayList<>();
        //治理监测点
        if (Objects.equals(code, DicDataEnum.OUTPUT_SIDE.getCode())){
            modelId = devModelRelationFeignClient.getModelByType(devId,0).getData();
            dataSetList = dataSetFeignClient.getDataSet(modelId,0).getData();
        }
        //电网侧监测点
        else if (Objects.equals(code, DicDataEnum.GRID_SIDE.getCode())){
            modelId = devModelRelationFeignClient.getModelByType(devId,1).getData();
            dataSetList = dataSetFeignClient.getDataSet(modelId,1).getData();
        }
        //负载侧监测点
        else if (Objects.equals(code, DicDataEnum.LOAD_SIDE.getCode())){
            modelId = devModelRelationFeignClient.getModelByType(devId,1).getData();
            dataSetList = dataSetFeignClient.getDataSet(modelId,2).getData();
        }
        setList = dataSetList.stream().map(LineTargetVO::getId).collect(Collectors.toList());
        return dataArrayFeignClient.getDataArray(setList).getData();
    }

//    @Override
//    public List<CsRtDataVO> getLineData(String id) {
//        List<CsRtDataVO> result = new ArrayList<>();
//        String path = csPagePOService.queryById(id).getPath();
//        InputStream inputStream = fileStorageUtil.getFileStream(path);
//        ZuTaiDTO zuTaiDto = analysisJson(inputStream);
//        zuTaiDto.getJson().forEach(item->{
//            if (!Objects.isNull(item.getTarget()) && StringUtils.isNotBlank(item.getTarget())){
//                String targetTag = item.getTarget().split("\\$")[0];
//                String phasic = item.getTarget().split("\\$")[1];
//                String dataType = item.getTarget().split("\\$")[2];
//                if (CollectionUtils.isEmpty(item.getUId()) || ObjectUtil.isNull(item.getLineId())){
//                    throw new BusinessException(CsHarmonicResponseEnum.BIND_TARGET_ERROR);
//                }
//                CsDataArray dataArray = dataArrayFeignClient.getDataArrayById(String.valueOf(item.getUId().get(0)),targetTag).getData().get(0);
//                String targetName = dataArray.getAnotherName();
//                String dataId = dataArray.getDataId();
//                String classId = epdFeignClient.selectById(dataId).getData().getClassId();
//                String clDid = influxDbParamUtil.getClDidByLineId(item.getLineId());
//                //基础信息
//                CsRtDataVO vo = getLineRtData(item.getId(),item.getLineId(),influxDbParamUtil.getTableNameByClassId(classId),targetTag,phasic,dataType,targetName,clDid);
//                //设备状态信息
//                CsEquipmentDeliveryPO po = equipmentFeignClient.getDevByLineId(item.getLineId()).getData();
//                vo.setDevStatus(po.getRunStatus());
//                result.add(vo);
//            }
//        });
//        return result;
//    }

    @Override
    public List<CsRtDataVO> getLineData(String id) {
        List<CsRtDataVO> result = new ArrayList<>();
        String path = csPagePOService.queryById(id).getPath();
        InputStream inputStream = fileStorageUtil.getFileStream(path);
        ZuTaiDTO zuTaiDto = analysisJson(inputStream);

        zuTaiDto.getJson().forEach(item->{
            if (ObjectUtil.isNotNull(item.getUIdType()) && item.getUIdType()) {
                Object lastElement = item.getUId().get(item.getUId().size() - 1);
                String data = String.valueOf(lastElement);
                //分解出来五个参数 第一个 指标字段 第二个 相别 第三个 数据类型 第四个 influxdb表名 第五个 限值名称
                String[] tempTable = data.replace("$", "").split("#");
                //解析指标名称
                String targetName = "指标名称获取失败";
                String[] tmepUidName = item.getTarget().split(" / ");
                if(tmepUidName.length==2) {
                    targetName = tmepUidName[0];
                }else if (tmepUidName.length==3) {
                    targetName = tmepUidName[0];
                } else if (tmepUidName.length==4) {
                    targetName = tmepUidName[1];
                }
                String clDid = influxDbParamUtil.getClDidByLineId(item.getLineId());
                //基础信息
                CsRtDataVO vo = getLineRtData(item.getId(),item.getLineId(),tempTable[3],tempTable[0],Objects.equals(tempTable[1],"T")?"T":tempTable[1],tempTable[2],targetName,clDid);
                //设备状态信息
                CsEquipmentDeliveryPO po = equipmentFeignClient.getDevByLineId(item.getLineId()).getData();
                vo.setDevStatus(po.getRunStatus());
                result.add(vo);
            }
        });
        return result;
    }


    @Override
    public List<CsRtDataVO> getLineDataNew(String id) {
        List<CsRtDataVO> result = new ArrayList<>();
        String path = csPagePOService.queryById(id).getPath();
        InputStream inputStream = fileStorageUtil.getFileStream(path);
        ZuTaiNewDTO zuTaiDto = analysisJsonNew(inputStream);

        zuTaiDto.getJson().forEach(item->{
            if (!CollectionUtils.isEmpty(item.getUidNames()) && Objects.isNull(item.getUidType())){
                for (int i = 0; i < item.getUidNames().size(); i++) {
                    String temp = item.getUidNames().get(i);
                    String targetTag = null;
                    String phasic = null;
                    String dataType = null;
                    if (CollectionUtils.isEmpty(item.getUid()) || org.springframework.util.StringUtils.isEmpty(item.getLineId())){
                        throw new BusinessException(CsSystemResponseEnum.BIND_TARGET_ERROR);
                    }
                    if (item.getUid().get(i) instanceof List) {
                        List<?> rawList = (List<?>) item.getUid().get(i);
                        List<String> tempUid = rawList.stream()
                                .filter(item2 -> item2 instanceof String)
                                .map(item2 -> (String) item2)
                                .collect(Collectors.toList());
                        String s = tempUid.get(tempUid.size() - 1);
                        String[] tempTable = s.replace("$", "").split("#");
                        phasic = Objects.equals(tempTable[1],"M") ? "T" : tempTable[1];
                        result.add(getLineRtDataNew(item.getId(),item.getLineId(),tempTable[3],tempTable[0],phasic,tempTable[2],temp,item.getUnit().get(i)));
                    }
                }
            }
        });
        return result;
    }


    /**
     * 解析json文件
     */
    public ZuTaiDTO analysisJson(InputStream inputStream) {
        Gson gson = new Gson();
        String text = new BufferedReader(
                new InputStreamReader(inputStream, StandardCharsets.UTF_8))
                .lines()
                .collect(Collectors.joining("\n"));
        return gson.fromJson(text, new TypeToken<ZuTaiDTO>(){}.getType());
    }

    /**
     * 解析json文件
     */
    public ZuTaiNewDTO analysisJsonNew(InputStream inputStream) {
        ObjectMapper mapper = new ObjectMapper();

        String text = new BufferedReader(
                new InputStreamReader(inputStream, StandardCharsets.UTF_8))
                .lines()
                .collect(Collectors.joining("\n"));


        ZuTaiNewDTO config = null;
        try {
            config = mapper.readValue(text, ZuTaiNewDTO.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        return config;
    }

    /**
     * 通过orm框架获取数据
     * @param id            图元Id
     * @param lineId        监测点Id
     * @param tableName     表名称
     * @param columnName    字段名称
     * @param phasic        相别
     * @param dataType      数据类型
     * @param target        数据名称
     * @param cldId         逻辑子设备标识
     * @return
     */
    public CsRtDataVO getLineRtData(String id,String lineId, String tableName, String columnName, String phasic, String dataType, String target, String cldId) {
        CsRtDataVO csRtDataVO = new CsRtDataVO();
        StatisticalDataDTO statisticalDataDTO = commonService.getLineRtData(lineId,tableName,columnName,phasic,dataType.toUpperCase(),cldId);
        if(Objects.isNull(statisticalDataDTO)){
            statisticalDataDTO = new StatisticalDataDTO();
            statisticalDataDTO.setLineId(lineId);
            statisticalDataDTO.setPhaseType(phasic);
            statisticalDataDTO.setValueType(dataType);
            statisticalDataDTO.setValue(3.1415926);
        } else {
            statisticalDataDTO.setValue(BigDecimal.valueOf(statisticalDataDTO.getValue()).setScale(4, RoundingMode.HALF_UP).doubleValue());
        }
        statisticalDataDTO.setStatisticalName(target);
        statisticalDataDTO.setTarget(columnName + "$" + phasic + "$" + dataType);
        BeanUtils.copyProperties(statisticalDataDTO,csRtDataVO);
        csRtDataVO.setId(id);
        return csRtDataVO;
    }


    /**
     * 通过orm框架获取数据
     * @param id            图元Id
     * @param lineId        监测点Id
     * @param tableName     表名称
     * @param columnName    字段名称
     * @param phasic        相别
     * @param dataType      数据类型
     * @param target        数据名称
     * @return
     */
    public CsRtDataVO getLineRtDataNew(String id,String lineId, String tableName, String columnName, String phasic, String dataType, String target,String uint) {
        CsRtDataVO csRtDataVO = new CsRtDataVO();
        String clDid = influxDbParamUtil.getClDidByLineId(lineId);
        StatisticalDataDTO statisticalDataDTO = commonService.getLineRtData(lineId,tableName,columnName,phasic,dataType.toUpperCase(),clDid);
        if(Objects.isNull(statisticalDataDTO)){
            statisticalDataDTO = new StatisticalDataDTO();
            statisticalDataDTO.setLineId(lineId);
            statisticalDataDTO.setPhaseType(phasic);
            statisticalDataDTO.setValueType(dataType);
            statisticalDataDTO.setValue(3.1415926);
        } else {
            statisticalDataDTO.setValue(BigDecimal.valueOf(statisticalDataDTO.getValue()).setScale(4, RoundingMode.HALF_UP).doubleValue());
        }
        String targetTag = null;
        String targetPhasic = null;
        String targetDataType = null;

        String[] tmepUidName = target.split(" / ");
        if(tmepUidName.length==2){
            targetTag = tmepUidName[0];
            targetDataType = getDataType(tmepUidName[1]) ;
        }else if (tmepUidName.length==3){
            targetTag = tmepUidName[0];
            targetPhasic = tmepUidName[1];
            targetDataType =getDataType(tmepUidName[2]) ;
        } else if (tmepUidName.length==4) {
            targetTag = tmepUidName[1];
            targetPhasic = tmepUidName[2];
            targetDataType =getDataType(tmepUidName[3]) ;
        }
        statisticalDataDTO.setStatisticalName((Objects.isNull(targetPhasic)?"":targetPhasic+"相_")+targetTag+"_"+targetDataType);
        statisticalDataDTO.setTarget(columnName + "$" + phasic + "$" + dataType);
        BeanUtils.copyProperties(statisticalDataDTO,csRtDataVO);
        csRtDataVO.setId(id);
        csRtDataVO.setUnit(uint);
        return csRtDataVO;
    }

    public String getDataType(String statItem){
        String valueTypeName = "";
        switch (statItem) {
            case "max":
                valueTypeName = "最大值";
                break;
            case "min":
                valueTypeName = "最小值";
                break;
            case "avg":
                valueTypeName = "平均值";
                break;
            case "cp95":
                valueTypeName = "cp95值";
                break;
            default:
                break;
        }
        return valueTypeName;
    }
}
