package com.gyee.runeconomy.service.WindDirection;

import com.gyee.common.contant.ContantXk;
import com.gyee.runeconomy.dto.result.PowerPointData;
import com.gyee.runeconomy.init.CacheContext;
import com.gyee.runeconomy.model.auto.ProBasicEquipment;
import com.gyee.runeconomy.model.auto.ProBasicEquipmentPoint;
import com.gyee.runeconomy.model.auto.ProBasicModelPower;
import com.gyee.runeconomy.service.auto.IProBasicEquipmentPointService;
import com.gyee.runeconomy.util.DateUtil;
import com.gyee.runeconomy.util.DateUtils;
import com.gyee.runeconomy.util.realtimesource.feign.RemoteServiceBuilder;
import com.gyee.runeconomy.util.realtimesource.feign.TsDoubleData;
import io.swagger.models.auth.In;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class WindDirectionService {

    @Resource
    private IProBasicEquipmentPointService proBasicEquipmentPointService;
    @Resource
    private RemoteServiceBuilder remoteService;
    /**
     * 风向玫瑰图\风向频率玫瑰图
     *
     * @return
     */
    public Object fxRoses(String wtid, String kssj, String jssj) throws Exception {

        Date[] sjcl = DateUtils.sjcl(kssj, jssj);

        // 获取 startDate 和 endDate
        Date startDate = sjcl[0];
        Date endDate = sjcl[1];

        List<ProBasicEquipment> list = CacheContext.wtls.stream().filter(wt -> wtid.equals(wt.getId())).collect(Collectors.toList());
        if (list == null || list.size() == 0)
            return null;

        List<ProBasicEquipment> collect = CacheContext.wtls.stream()
                .filter(w -> wtid.equals(w.getId()) && w.getProjectId().contains("02")).collect(Collectors.toList());

        // 初始化设备点
        Map<EquipmentPointType, ProBasicEquipmentPoint> points = Arrays.stream(EquipmentPointType.values())
                .collect(Collectors.toMap(type -> type, type -> getEquipmentPoint(wtid, type)));

        // 获取历史数据
        Map<EquipmentPointType, List<TsDoubleData>> historyData = points.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                        entry -> getSortedHistory(entry.getValue(), startDate.getTime(), endDate.getTime(), 300)));

        // 创建时间戳到数据的映射表
        Map<Long, TsDoubleData> pjfsMap = historyData.get(EquipmentPointType.PJFS).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> sbztMap = historyData.get(EquipmentPointType.SBZT).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> dfwcMap = historyData.get(EquipmentPointType.DFWC).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> phjdMap = historyData.get(EquipmentPointType.PHJD).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> glMap = historyData.get(EquipmentPointType.GL).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> jcwzMap = historyData.get(EquipmentPointType.JCWZ).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> ssqfztMap = historyData.get(EquipmentPointType.ssqfzt).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));

        // 构造结果数据
        List<PowerPointData> lslist = new ArrayList<>();
        for (TsDoubleData fxData : historyData.get(EquipmentPointType.PJFX)) {
            long ts = fxData.getTs();
            TsDoubleData fsData = pjfsMap.get(ts);
            TsDoubleData ztData = sbztMap.get(ts);
            TsDoubleData dfwcData = dfwcMap.get(ts);
            TsDoubleData phjdData = phjdMap.get(ts);
            TsDoubleData glData = glMap.get(ts);
            TsDoubleData jcwzData = jcwzMap.get(ts);
            TsDoubleData ssqfztData = ssqfztMap.get(ts);

            PowerPointData data = new PowerPointData();
            data.setTime(DateUtils.formatTimestamp(ts));
          if (collect.size()>0){
                data.setFx(fxData.getDoubleValue() * 57.2958);
            } else {
                data.setFx(fxData.getDoubleValue());
            }
            data.setSpeed(fsData != null ? fsData.getDoubleValue() : 0);
            data.setMxzt(ztData != null ? (int) ztData.getDoubleValue() : 0);
            data.setDfwc(dfwcData != null ? dfwcData.getDoubleValue() : 0);
//            data.setAngle(phjdData != null ? phjdData.getDoubleValue() : 0);
            data.setAngle(phjdData != null ? jcwzData.getDoubleValue() : 0);//将机舱位置添加到偏航角度中，因没有机舱位置
            data.setPower(glData != null ? glData.getDoubleValue() : 0);
//            data.setYp1(jcwzData != null ? jcwzData.getDoubleValue() : 0);
            data.setQfzt(ssqfztData != null ? (int) ssqfztData.getDoubleValue() : 0);
            lslist.add(data);
        }


        /**
         * 数据预处理
         *
         * @param list   预处理的数据
         * @param map    风速对应的保证功率
         * @param maxs   最大风速
         * @param mins   最小风速
         * @param maxp   最大功率
         * @param minp   最小功率
         * @param isfbw  是否并网
         * @param isfhl  是否合理值
         * @param isbw   并网后10分钟
         * @param istj   停机前10分钟
         * @param isglpc 功率曲线偏差
         * @param isqfh  是否欠符合
         * @param qfhdj  欠符合等级
         * @param xd     是否限电
         * @return
         */
        /* 风速  ->  保证功率  来自数据库 **/
        List<ProBasicModelPower> modelPowerList = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(wtid).getModelId());
        Map<Double, Double> modelPowerMap = modelPowerList.stream().collect(Collectors.toMap(ProBasicModelPower::getSpeed, ProBasicModelPower::getEnsurePower));
        String timeBW = DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN);
        List<PowerPointData> tempei = new ArrayList<>();
        List<PowerPointData> tempqf = new ArrayList<>();

        Boolean isqfh = true;
        Integer qfhdj = 2;
        Boolean isfbw= true;
        Integer xd = 1;
        Double mins = 3.0;
        Double maxs = 25.0;
        Double minp = 0.0;
        Double maxp = 3000.0;
        Boolean isfhl =true;
        Boolean isbw =true;
        Boolean istj =true;
        Boolean isglpc =true;

        if(list==null || list.size()==0) System.out.println("预处理数据数量为0。");

        Double maxPower = Collections.max(modelPowerMap.values());//最大保证功率
        maxp=maxPower*1.05;

        //TODO 数据过滤  // 0正常，1过滤掉
        for (PowerPointData item : lslist) {
            int filter = 0;
            int fjstatus = 0;
            if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)) {
                timeBW = item.getTime();
            }
            // 过滤非并网值  风机状态不等于2
            if (filter == 0 && isfbw && item.getMxzt() != 2) {
                filter = 1;
                fjstatus = 1;
                timeBW = item.getTime();
            } else {
                filter = 0;
                fjstatus = 0;
            }

            //过滤限电状态，风机状态等于4或者5
//            if (xd == 1 && filter == 0 && isfbw && (item.getMxzt() == 8 || item.getMxzt() == 9)) {
//                filter = 1;
//                fjstatus = 1;
//                timeBW = item.getTime();
//            }
            // 按给定风速功率过滤
            if (item.getSpeed() < mins || item.getSpeed() > maxs || item.getPower() < minp || item.getPower() > maxp) {
                filter = 1;
            }
            // 过滤非合理值 并网状态下功率小于等于0
            if (filter == 0 && isfhl && item.getSpeed() < 0 && item.getPower() <= minp) {
                filter = 1;
            }
            // 过滤并网后十分钟
//            if (filter == 0 && isbw) {
//                if (DateUtil.getTimeDiff(item.getTime(), timeBW) <= 10)
//                    filter = 1;
//            }
            // 过滤停机前十分钟
//            if (istj) {
//                if (fjstatus == 0) {
//                    if (tempei.size() > 0) {
//                        if (DateUtil.getTimeDiff(tempei.get(0).getTime(), timeBW) >= 10) {
//                            tempei.remove(0);
//                        }
//                    }
//                    tempei.add(item);
//                } else {
//                    for (PowerPointData temp : tempei) {
//                        temp.setFilter(1);
//                    }
//                    tempei.clear();
//                }
//            }
            //欠发
//            if (filter == 0 && item.getSpeed() >= 6 && item.getSpeed() < 12.5 && isqfh && qfhdj < item.getQfzt()) {
//                filter = 1;
//                for (PowerPointData temp : tempqf) {
//                    temp.setFilter(1);
//                }
//            } else if (filter == 0 && item.getSpeed() >= 12.5 && isqfh && qfhdj < 1) {
//                filter = 1;
//                for (PowerPointData temp : tempqf) {
//                    temp.setFilter(1);
//                }
//            }
//            if (tempqf.size() > 0) {
//                if (DateUtil.getTimeDiff(tempqf.get(0).getTime(), item.getTime()) >= 5) {
//                    tempqf.remove(0);
//                }
//            }
//            tempqf.add(0, item);
//            item.setFilter(filter);

            //功率曲线偏差
//            if (isglpc) {
//                if (modelPowerMap.containsKey(item.getSpeed())) {
//
//                    double power = modelPowerMap.get(item.getSpeed());  //不同风速对应的保证功率
//                    double k = item.getPower() / power;  //保证功率/实际功率   k:偏差百分比
//                    if (item.getPower() > 0) {
//                        if (k < 0.95 && maxPower <= power) {
//                            item.setFilter(1);
//                        }
//                        if (k < 0.9 && maxPower > power) {
//                            item.setFilter(1);
//                        }
//                        if (k < 0.85 && item.getSpeed() < 6 && item.getSpeed() > 4) {
//                            item.setFilter(1);
//                        }
//
//                        if (k < 0.9 && item.getSpeed() <= 4 && item.getSpeed() > 3.5) {
//                            item.setFilter(1);
//                        }
//                    }
//                }
//            }
        }


        List<PowerPointData> filterls = new ArrayList<>();
        for (PowerPointData ls : lslist){
            if (ls.getFilter() != 1) {
                filterls.add(ls);
            }
        }
        List<Object> result = new ArrayList<>();

        for (ProBasicEquipment obj : list) {
            Map<String, Object> map = new HashMap<>();
            map.put("wt", obj.getAname());
            map.put("ys", WindALG.fxNewRoses(filterls));//风速、风向
            map.put("speeedtime", WindALG.speedtimeNewRoses(filterls));//风速
            map.put("roses", WindALG.fxysNewRoses(filterls));//风速、风向
            map.put("count", WindALG.fxNewCountRoses(filterls));//风速、风向
            map.put("radar", WindALG.fxRadarRoses(filterls,collect));//对风误差
            map.put("frequency", WindALG.windDeviationPoint(filterls)); //风速、风向、明细状态、功率、偏航角度
            result.add(map);
        }

        return result;
    }
    /**
     * 对风偏差率

     */
    public List<Object> windDeviationRatio(String wtid, String kssj, String jssj) throws ParseException {

        Date[] sjcl = DateUtils.sjcl(kssj, jssj);

        // 获取 startDate 和 endDate
        Date startDate = sjcl[0];
        Date endDate = sjcl[1];

        List<Object> list = new ArrayList<>();

        List<ProBasicEquipment> equipments = CacheContext.wtls.stream()
                .filter(w -> wtid.equals(w.getId()) && w.getProjectId().contains("02"))
                .collect(Collectors.toList());
        // 初始化设备点
        Map<EquipmentPointType, ProBasicEquipmentPoint> points = Arrays.stream(EquipmentPointType.values())
                .collect(Collectors.toMap(type -> type, type -> getEquipmentPoint(wtid, type)));

        // 获取历史数据
        Map<EquipmentPointType, List<TsDoubleData>> historyData = points.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey,
                        entry -> getSortedHistory(entry.getValue(), startDate.getTime(), endDate.getTime(), 300)));

        // 创建时间戳到数据的映射表
        Map<Long, TsDoubleData> pjfsMap = historyData.get(EquipmentPointType.PJFS).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> sbztMap = historyData.get(EquipmentPointType.SBZT).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> dfwcMap = historyData.get(EquipmentPointType.DFWC).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> phjdMap = historyData.get(EquipmentPointType.PHJD).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> glMap = historyData.get(EquipmentPointType.GL).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> jcwzMap = historyData.get(EquipmentPointType.JCWZ).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));
        Map<Long, TsDoubleData> ssqfztMap = historyData.get(EquipmentPointType.ssqfzt).stream()
                .collect(Collectors.toMap(TsDoubleData::getTs, Function.identity(), (a, b) -> a));

        // 构造结果数据
        List<PowerPointData> lslist = new ArrayList<>();
        for (TsDoubleData fxData : historyData.get(EquipmentPointType.PJFX)) {
            long ts = fxData.getTs();
            TsDoubleData fsData = pjfsMap.get(ts);
            TsDoubleData ztData = sbztMap.get(ts);
            TsDoubleData dfwcData = dfwcMap.get(ts);
            TsDoubleData phjdData = phjdMap.get(ts);
            TsDoubleData glData = glMap.get(ts);
            TsDoubleData jcwzData = jcwzMap.get(ts);
            TsDoubleData ssqfztData = ssqfztMap.get(ts);

            PowerPointData data = new PowerPointData();
            data.setTime(DateUtils.formatTimestamp(ts));
            if (equipments.size() > 0) {
                data.setFx(fxData.getDoubleValue() * 57.2958);
            } else {
                data.setFx(fxData.getDoubleValue());
            }
            data.setSpeed(fsData != null ? fsData.getDoubleValue() : 0);
            data.setMxzt(ztData != null ? (int) ztData.getDoubleValue() : 0);
            data.setDfwc(dfwcData != null ? dfwcData.getDoubleValue() : 0);
//            data.setAngle(phjdData != null ? phjdData.getDoubleValue() : 0);
            data.setAngle(phjdData != null ? jcwzData.getDoubleValue() : 0);//将机舱位置添加到偏航角度中，因没有机舱位置
            data.setPower(glData != null ? glData.getDoubleValue() : 0);
//            data.setYp1(jcwzData != null ? jcwzData.getDoubleValue() : 0);
            data.setQfzt(ssqfztData != null ? (int) ssqfztData.getDoubleValue() : 0);
            lslist.add(data);
        }


        /**
         * 数据预处理
         *
         * @param list   预处理的数据
         * @param map    风速对应的保证功率
         * @param maxs   最大风速
         * @param mins   最小风速
         * @param maxp   最大功率
         * @param minp   最小功率
         * @param isfbw  是否并网
         * @param isfhl  是否合理值
         * @param isbw   并网后10分钟
         * @param istj   停机前10分钟
         * @param isglpc 功率曲线偏差
         * @param isqfh  是否欠符合
         * @param qfhdj  欠符合等级
         * @param xd     是否限电
         * @return
         */
        /* 风速  ->  保证功率  来自数据库 **/
        List<ProBasicModelPower> modelPowerList = CacheContext.modelPowerDetailNewMap.get(CacheContext.wtmap.get(wtid).getModelId());
        Map<Double, Double> modelPowerMap = modelPowerList.stream().collect(Collectors.toMap(ProBasicModelPower::getSpeed, ProBasicModelPower::getEnsurePower));
        String timeBW = DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN);
        List<PowerPointData> tempei = new ArrayList<>();
        List<PowerPointData> tempqf = new ArrayList<>();

        Boolean isqfh = true;
        Integer qfhdj = 2;
        Boolean isfbw= true;
        Integer xd = 1;
        Double mins = 3.0;
        Double maxs = 25.0;
        Double minp = 0.0;
        Double maxp = 3000.0;
        Boolean isfhl =true;
        Boolean isbw =true;
        Boolean istj =true;
        Boolean isglpc =true;

        if(list==null || list.size()==0) System.out.println("预处理数据数量为0。");

        Double maxPower = Collections.max(modelPowerMap.values());//最大保证功率
        maxp=maxPower*1.05;

        //TODO 数据过滤  // 0正常，1过滤掉
        for (PowerPointData item : lslist) {
            int filter = 0;
            int fjstatus = 0;
            if (timeBW == DateUtil.format(new Date(0), DateUtil.DATE_TIME_PATTERN)) {
                timeBW = item.getTime();
            }
            // 过滤非并网值  风机状态不等于2
            if (filter == 0 && isfbw && item.getMxzt() != 2) {
                filter = 1;
                fjstatus = 1;
                timeBW = item.getTime();
            } else {
                filter = 0;
                fjstatus = 0;
            }

            //过滤限电状态，风机状态等于4或者5
//            if (xd == 1 && filter == 0 && isfbw && (item.getMxzt() == 8 || item.getMxzt() == 9)) {
//                filter = 1;
//                fjstatus = 1;
//                timeBW = item.getTime();
//            }
//            // 按给定风速功率过滤
            if (item.getSpeed() < mins || item.getSpeed() > maxs || item.getPower() < minp || item.getPower() > maxp) {
                filter = 1;
            }
            // 过滤非合理值 并网状态下功率小于等于0
            if (filter == 0 && isfhl && item.getSpeed() < 0 && item.getPower() <= minp) {
                filter = 1;
            }
            // 过滤并网后十分钟
//            if (filter == 0 && isbw) {
//                if (DateUtil.getTimeDiff(item.getTime(), timeBW) <= 10)
//                    filter = 1;
//            }
//            // 过滤停机前十分钟
//            if (istj) {
//                if (fjstatus == 0) {
//                    if (tempei.size() > 0) {
//                        if (DateUtil.getTimeDiff(tempei.get(0).getTime(), timeBW) >= 10) {
//                            tempei.remove(0);
//                        }
//                    }
//                    tempei.add(item);
//                } else {
//                    for (PowerPointData temp : tempei) {
//                        temp.setFilter(1);
//                    }
//                    tempei.clear();
//                }
//            }
//            //欠发
//            if (filter == 0 && item.getSpeed() >= 6 && item.getSpeed() < 12.5 && isqfh && qfhdj < item.getQfzt()) {
//                filter = 1;
//                for (PowerPointData temp : tempqf) {
//                    temp.setFilter(1);
//                }
//            } else if (filter == 0 && item.getSpeed() >= 12.5 && isqfh && qfhdj < 1) {
//                filter = 1;
//                for (PowerPointData temp : tempqf) {
//                    temp.setFilter(1);
//                }
//            }
//            if (tempqf.size() > 0) {
//                if (DateUtil.getTimeDiff(tempqf.get(0).getTime(), item.getTime()) >= 5) {
//                    tempqf.remove(0);
//                }
//            }
//            tempqf.add(0, item);
//            item.setFilter(filter);
//
//            //功率曲线偏差
//            if (isglpc) {
//                if (modelPowerMap.containsKey(item.getSpeed())) {
//
//                    double power = modelPowerMap.get(item.getSpeed());  //不同风速对应的保证功率
//                    double k = item.getPower() / power;  //保证功率/实际功率   k:偏差百分比
//                    if (item.getPower() > 0) {
//                        if (k < 0.95 && maxPower <= power) {
//                            item.setFilter(1);
//                        }
//                        if (k < 0.9 && maxPower > power) {
//                            item.setFilter(1);
//                        }
//                        if (k < 0.85 && item.getSpeed() < 6 && item.getSpeed() > 4) {
//                            item.setFilter(1);
//                        }
//
//                        if (k < 0.9 && item.getSpeed() <= 4 && item.getSpeed() > 3.5) {
//                            item.setFilter(1);
//                        }
//                    }
//                }
//            }
        }


        List<PowerPointData> filterls = new ArrayList<>();
        for (PowerPointData ls : lslist){
            if (ls.getFilter() != 1) {
                filterls.add(ls);
            }
        }

        List<ProBasicEquipment> listObj = CacheContext.wtls.stream().filter(wt -> wtid.equals(wt.getId())).collect(Collectors.toList());

            listObj.forEach(obj -> {
                int[] count = WindALG.windDeviationRatio(filterls,equipments);//风向、对风误差
                List<Point> scatter = WindALG.windDeviationScatter(filterls,equipments);//风速、风向、对风误差
                Map<String, Object> map = new HashMap<>();
                map.put("wtId", obj.getAname());
                map.put("count", count);
                map.put("scatter", scatter);
                list.add(map);
            });

        return list;
    }

    // 工具方法：获取设备点
    private ProBasicEquipmentPoint getEquipmentPoint(String wtid, EquipmentPointType type) {
        return proBasicEquipmentPointService.getEquipmentPoint(wtid, type.getCode());
    }

    // 工具方法：获取历史数据并排序
    private List<TsDoubleData> getSortedHistory(ProBasicEquipmentPoint point, long startTime, long endTime, int interval) {
        if (point == null) return new ArrayList<>();
        List<TsDoubleData> data = remoteService.adapterfd().getHistorySnap(point.getNemCode(), startTime, endTime, interval);
        data.sort(Comparator.comparing(TsDoubleData::getTs));
        return data;
    }


    // 枚举定义
    public enum EquipmentPointType {
        PJFS(ContantXk.CJ_SSFS),
        PJFX(ContantXk.CJ_FX),
        SBZT(ContantXk.MXZT),
        DFWC(ContantXk.CJ_DFJD),
        GL(ContantXk.CJ_SSGL),
        PHJD(ContantXk.CJ_PHJD),
        JCWZ(ContantXk.CJ_JCWZ),
        ssqfzt(ContantXk.SSQFZT);

        private final String code;

        EquipmentPointType(String code) {
            this.code = code;
        }

        public String getCode() {
            return code;
        }
    }

}
