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.service.auto.IProBasicEquipmentPointService;
import com.gyee.runeconomy.util.DateUtils;
import com.gyee.runeconomy.util.realtimesource.feign.RemoteServiceBuilder;
import com.gyee.runeconomy.util.realtimesource.feign.TsDoubleData;
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;

@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;

        // 初始化设备点
        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(), 900)));

        // 创建时间戳到数据的映射表
        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));

        // 构造结果数据
        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);

            PowerPointData data = new PowerPointData();
            data.setTime(DateUtils.formatTimestamp(ts));
            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.setPower(glData != null ? glData.getDoubleValue() : 0);
            lslist.add(data);
        }

        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(lslist));//风速、风向
            map.put("speeedtime", WindALG.speedtimeNewRoses(lslist));//风速
            map.put("roses", WindALG.fxysNewRoses(lslist));//风速、风向
            map.put("count", WindALG.fxNewCountRoses(lslist));//风速、风向
            map.put("radar", WindALG.fxRadarRoses(lslist));//对风误差
            map.put("frequency", WindALG.windDeviationPoint(lslist)); //风速、风向、明细状态、功率、偏航角度
            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<>();
        // 初始化设备点
        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(), 900)));

        // 创建时间戳到数据的映射表
        Map<Long, TsDoubleData> pjfsMap = historyData.get(EquipmentPointType.PJFS).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));

        // 构造结果数据
        List<PowerPointData> lslist = new ArrayList<>();
        for (TsDoubleData fxData : historyData.get(EquipmentPointType.PJFX)) {
            long ts = fxData.getTs();
            TsDoubleData fsData = pjfsMap.get(ts);
            TsDoubleData dfwcData = dfwcMap.get(ts);

            PowerPointData data = new PowerPointData();
            data.setTime(DateUtils.formatTimestamp(ts));
            data.setFx(fxData.getDoubleValue());
            data.setSpeed(fsData != null ? fsData.getDoubleValue() : 0);
            data.setDfwc(dfwcData != null ? dfwcData.getDoubleValue() : 0);
            lslist.add(data);
        }

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

            listObj.forEach(obj -> {
                int[] count = WindALG.windDeviationRatio(lslist);//风向、对风误差
                List<Point> scatter = WindALG.windDeviationScatter(lslist);//风速、风向、对风误差
                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);

        private final String code;

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

        public String getCode() {
            return code;
        }
    }

}
