package com.jiayue.insu.incloud.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jiayue.insu.incloud.constants.CommonStant;
import com.jiayue.insu.incloud.constants.enums.StatusEnum;
import com.jiayue.insu.incloud.constants.vo.FileCreateLog;
import com.jiayue.insu.incloud.entity.*;
import com.jiayue.insu.incloud.service.*;
import com.jiayue.insu.incloud.utils.HuaWeiObsUtil;
import com.jiayue.insu.incloud.utils.JsonResultUtil;
import com.jiayue.insu.incloud.utils.SystermUtils;
import com.jiayue.insu.minio.util.MinioUtilService;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.io.*;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 预测数据业务实现
 *
 * @author yh
 * @version 1.0
 * @since 2022/5/22 11:29
 */
@Slf4j
@Service
public class ApiServiceImpl implements ApiService {

    @Value("${minio.pull.url}")
    String url;
    @Value("${minio.pull.fileurl}")
    String fileurl;
    @Value("${minio.fileurl}")
    String fileDir;
    @Value("${minio.bucketname}")
    private String bucketName;
    @Value("${minio.pull.cloudFileCreateLog}")
    private String cloudFileCreateLog;
    @Value("${minio.postBackUrl}")
    private String postBackUrl;
    @Value("${minio.pushCorrFileUrl}")
    private String pushCorrFileUrl;


    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private StationService stationService;
    @Autowired
    private VelocityEngine velocityEngine;
    @Autowired
    private MinioUtilService minioUtilService;
    @Autowired
    public RecordService recordService;
    @Autowired
    private ForecastDataService forecastDataService;
    @Autowired
    private UltraShortTermService ultraShortTermService;
    @Autowired
    private PowerStationStatusDataService powerStationStatusDataService;

    /**
     * 获取token
     *
     * @param userInfo
     * @return
     */
    @Override
    public JSONObject getToken(JSONObject userInfo) {
        JSONObject result;
        //获取用户名密码
        String requestUserName = userInfo.getStr(CommonStant.REQUEST_USER_NAME);
        String requestUserPass = userInfo.getStr(CommonStant.REQUEST_USER_PASS);
        // 获取用户列表
        Map<String, String> userMap = redisTemplate.opsForHash().entries(CommonStant.REDIS_USERS);
        // 根据用户名获取密码
        String password = userMap.get(requestUserName);
        // 加密后的密码
        String passwordMD5t = DigestUtils.md5DigestAsHex(password.getBytes()).toUpperCase();
        // 如果密码匹配成功
        if (passwordMD5t.equals(requestUserPass)) {
            // 拼接kdy名 例如：integration:cloud:userToken:user1
            String key = CommonStant.REDIS_USER_TOKEN + CommonStant.CHARACTER_COLON + requestUserName;
            String token = String.valueOf(redisTemplate.opsForValue().get(key));
            // 如果token存在并且时间大于1小时，则不再生成新token
            if (token != null && !"".equals(token) && !"null".equals(token)) {
                // 获取剩余时间
                long timeout = redisTemplate.opsForValue().getOperations().getExpire(key);
                // 如果剩余时间>1小时，返回redis中存储的token，否则生成新token
                if (timeout > 360) {
                    result = JsonResultUtil.success();
                    result.set("token", token);
                    log.info("用户:" + requestUserName + "获取token，剩余有效期" + timeout + "秒");
                    return result;
                }
            }
            // 生成token
            JwtBuilder builder = Jwts.builder()
                    .setSubject(requestUserName)
                    //用于设置签发时间
                    .setIssuedAt(new Date())
                    //用于设置签名秘钥
                    .signWith(SignatureAlgorithm.HS256, requestUserPass);
            // 获取token
            token = builder.compact();
            result = JsonResultUtil.success();
            result.set(CommonStant.TOKEN, token);
            // 成功生成token后，将toke存入redis 有效期24小时
            redisTemplate.opsForValue().set(key, token, 24, TimeUnit.HOURS);
            log.info("用户:" + requestUserName + "获取token，剩余有效期86400秒");
            // 返回结果
            return result;
        } else {
            log.info("密码错误");
            return JsonResultUtil.failure("密码错误");
        }
    }

    /**
     * 从minIo上获取短期文件并解析返回json格式
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject getShortWpfData(JSONObject requestJson) {
        JSONObject result = new JSONObject();
        JSONArray stationCodeArr = requestJson.getJSONArray("wfId");
        JSONArray dataArr = new JSONArray();
        boolean getStatus = false;
        //
        for (int i = 0; i < stationCodeArr.size(); i++) {
            // 根据场站编号查询场站信息
            Station station = stationService.findByStationCode(stationCodeArr.get(i).toString());
            JSONObject errMsg = new JSONObject();
            // 从minIo获取文件
            File file = downLoadFileFromMinIo(station, "dq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"), errMsg);
            // 解析短期文件
            JSONObject fileResult = null;
            // 内蒙古马吉拉湖光伏电站 返回未来10天数据
            if ("J00476".equals(station.getStationCode()) || "T00002-A".equals(station.getStationCode()) || "J00971-A".equals(station.getStationCode())) {
                fileResult = fileAnalysis(file, station, "dq", requestJson.getStr("beginDate"), requestJson.getStr("beginDate"));
            } else {
                fileResult = fileAnalysis(file, station, "dq", requestJson.getStr("beginDate"), requestJson.getStr("beginDate"));
            }
            // 如果解析文件成功，则放入data集合中
            if (JsonResultUtil.Type.success.value().equals(fileResult.get(JsonResultUtil.CODE_TAG))) {
                result = fileResult;
                dataArr.addAll(fileResult.getJSONArray("data"));
                getStatus = true;
            } else {
                dataArr.add(stationCodeArr.get(i).toString() + ":" + errMsg.getStr("msg"));
            }
        }
        // 如果全部文件都未下载，返回失败原因
        if (!getStatus) {
            return JsonResultUtil.failure(dataArr);
        }

        result.set("data", dataArr);
        // 如果解析完的短期文件列表为空
        return result;
    }

    @Override
    public JSONObject getNwpData(JSONObject requestJson) {
        JSONObject result = new JSONObject();
        JSONArray stationCodeArr = requestJson.getJSONArray("wfId");
        JSONArray dataArr = new JSONArray();
        boolean getStatus = false;
        //
        for (int i = 0; i < stationCodeArr.size(); i++) {
            // 根据场站编号查询场站信息
            Station station = stationService.findByStationCode(stationCodeArr.get(i).toString());
            JSONObject errMsg = new JSONObject();
            // 从minIo获取文件
            File file = downLoadFileFromMinIo(station, "nwp", requestJson.getStr("beginDate"), requestJson.getStr("endDate"), errMsg);
            // 解析短期文件
            JSONObject fileResult = fileAnalysis(file, station, "nwp", requestJson.getStr("beginDate"), requestJson.getStr("beginDate"));
            // 如果解析文件成功，则放入data集合中
            if (JsonResultUtil.Type.success.value().equals(fileResult.get(JsonResultUtil.CODE_TAG))) {
                getStatus = true;
                result = fileResult;
                dataArr.addAll(fileResult.getJSONArray("data"));
            } else {
                dataArr.add(stationCodeArr.get(i).toString() + ":" + errMsg.getStr("msg"));
            }
        }
        // 如果全部文件都未下载，返回失败原因
        if (!getStatus) {
            return JsonResultUtil.failure(dataArr);
        }
        // 将data放入列表
        result.set("data", dataArr);
        // 如果解析完的短期文件列表为空
        return result;
    }

    /**
     * 接收修正短期数据
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject putShortWpfData(JSONObject requestJson) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 根据场站编号查询场站信息
        Station station = stationService.findByStationCode(requestJson.getStr("wfId"));
        // 文件生成时间
        String recDate = requestJson.getStr("recDate");
        // 功率json
        JSONObject values = JSONUtil.parseObj(requestJson.getJSONArray("values").get(0));
        // 明日修正后数据Arr
        JSONArray datas = values.getJSONArray("datas");
        log.info("{}修正数据为：{}", station.getStationCode(), datas.toString());
        List<Map<String, Object>> dqListMap = new ArrayList<>();
        // 山东莱芜单独判断（其中T00002-A为给对面提供的测试场站）
        if ("T00002-A".equals(station.getStationCode()) || "J00971-A".equals(station.getStationCode())){
            String stationName = station.getName();
            List<ForecastData> forecastDataList = forecastDataService.findByInitTimeAndStationCode(LocalDateTimeUtil.beginOfDay(LocalDateTime.now()),station.getStationCode());
            DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            for (int i = 0; i < forecastDataList.size(); i++) {
                Map<String, Object> entry = new HashMap<>();
                boolean foundMatch = false;
                String forecastTimeStr = sdf.format(new Date(forecastDataList.get(i).getForecastTime()));
                for (int j = 0; j < datas.size(); j++) {
                    JSONObject data = datas.getJSONObject(j);
                    String timeStr = data.getStr("time");
                    String formattedTime = "";

                    try {
                        LocalDateTime dateTime = LocalDateTime.parse(timeStr, inputFormatter);
                        formattedTime = dateTime.format(outputFormatter);
                    } catch (Exception e) {
                        formattedTime = timeStr + ":00";
                    }

                    if (forecastTimeStr.equals(formattedTime)) {
                        entry.put("stationName", stationName);
                        entry.put("fpValue", new BigDecimal(String.valueOf(data.get("data"))).divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP));
                        entry.put("forecastTime", formattedTime);
                        foundMatch = true;
                        break;
                    }
                }
                if (!foundMatch) {
                    entry.put("stationName", stationName);
                    entry.put("fpValue", forecastDataList.get(i).getFpValue());
                    entry.put("forecastTime", forecastTimeStr);
                }
                dqListMap.add(entry);
            }

        }else {
            // 将json数据转化为ListMap
            dqListMap = getDqListMap(station, datas, station.getName());
        }

        // 短期文件模板
        String vmsPath = SystermUtils.getResourceBasePath() + "/vms/DQ.vm";
        JSONObject result = genFile(station, dqListMap, vmsPath, "_CORR", "DQ");
        if (JsonResultUtil.Type.failure.value().equals(result.get(JsonResultUtil.CODE_TAG))) {
            Record record = new Record(CommonStant.RECORD_TYPE_PUSH_CORRECT_TO_MIN_IO, "CSGS", requestJson.getStr("wfId"), null, LocalDateTime.now(), LocalDateTime.now(), JsonResultUtil.Type.failure.msg(), JsonResultUtil.Type.failure.value());
            recordService.save(record);
        }
        return JsonResultUtil.success();
    }

    /**
     * 从minIo上获取超短期文件并解析返回json格式
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject getSShortWpfData(JSONObject requestJson) {
        JSONObject result;
        String stationCode = requestJson.getStr("wfId");
        // 根据场站编号查询场站信息
        Station station = stationService.findByStationCode(stationCode);
        JSONObject errMsg = new JSONObject();
        // 从minIo下载文件
        File file = downLoadFileFromMinIo(station, "cdq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"), errMsg);
        //解析短期文件
        result = fileAnalysis(file, station, "cdq", requestJson.getStr("beginDate"), requestJson.getStr("endDate"));
        return result;
    }

    /**
     * 接收修正超短期数据
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject putSShortWpfData(JSONObject requestJson) {
        // 根据场站编号查询场站信息
        Station station = stationService.findByStationCode(requestJson.getStr("wfId"));
        // 功率json
        JSONObject values = JSONUtil.parseObj(requestJson.getJSONArray("values").get(0));
        // 文件生成时间
        String recDate = requestJson.getStr("recDate");
        // 所有日期的数据Arr
        JSONArray datas = values.getJSONArray("datas");
        // 将json数据转化为ListMap
        List<Map<String, Object>> dqListMap = getDqListMap(station, datas, station.getName());
        // 短期文件模板
        String vmsPath = SystermUtils.getResourceBasePath() + "/vms/CDQ.vm";
        // 生成cdq文件
        genFile(station, dqListMap, vmsPath, "_CORR", "CDQ");
        return JsonResultUtil.success();
    }

    /**
     * 解析短期文件
     *
     * @param dqFile
     * @param station
     * @param startDate
     * @param endDate
     * @return
     */
    public JSONObject fileAnalysis(File dqFile, Station station, String type, String startDate, String endDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String dateChange = startDate + " 00:00:00";
        Long useStartTime = null;
        try {
            useStartTime = dateFormat.parse(dateChange).getTime();
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Long useEndTime = useStartTime + 11 * 24 * 60 * 60 * 1000L;
        if (dqFile == null) {
            log.info("请求的文件不存在");
            return JsonResultUtil.failure("请求的文件不存在");
        }
        JSONArray resultArr = new JSONArray();
        boolean jx = true;
        if (dqFile.renameTo(dqFile)) {
            InputStreamReader dqRead = null;
            BufferedReader dqBufferedReader = null;
            String stringLine;
            String compareDate = "";
            // 获取短期文件生成日期
            String recDate = dqFile.getName().substring(3, 11);
            // 超短期起始时间
            String cdqFileStartTime = "";
            // 获取短期文件生成时间在几点
            String fileTime = dqFile.getName().substring(11, 13);
            // 如果文件生成时间>=12点，则为pm(下午)，否则为上午
            String version = "AM";
            if (Integer.valueOf(fileTime) >= 12) {
                version = "PM";
            }
            try {
                // 按照每行来解析文件
                dqRead = new InputStreamReader(new FileInputStream(dqFile), "utf-8");
                dqBufferedReader = new BufferedReader(dqRead);
                JSONObject dayInfoJson = new JSONObject();
                //一天中的96条数据信息
                JSONArray valuesArr = new JSONArray();
                JSONObject oneJson;
                JSONArray datas = new JSONArray();
                // 如果是短期
                if ("dq".equals(type)) {
                    while ((stringLine = dqBufferedReader.readLine()) != null) {
                        String[] string_arr = stringLine.split("\t");
                        if (string_arr.length == 4 && string_arr[0].startsWith("#")) {
                            if (StrUtil.isNotEmpty(string_arr[2])) {
                                //当条的日期
                                String thisDate = string_arr[2].split(" ")[0];
                                // 如果是短期
                                if ("dq".equals(type)) {
                                    // 内蒙古马吉拉光伏电站返回未来10天数据
                                    if ("J00476".equals(station.getStationCode()) || "T00002-A".equals(station.getStationCode())|| "J00971-A".equals(station.getStationCode())) {
                                        // 如果  当条日期>开始时间 || 当条日期<结束时间 跳过当次循环
                                        if (thisDate.compareTo(format.format(useStartTime)) <= 0 || thisDate.compareTo(format.format(useEndTime)) >= 0) {
                                            continue;
                                        }
                                    } else {
                                        // 如果  当条日期<开始时间 || 当条日期>结束时间 跳过当次循环
                                        if (thisDate.compareTo(startDate) < 0 || thisDate.compareTo(endDate) > 0) {
                                            continue;
                                        }
                                    }

                                }
                                // 如果当条的日期和上调日期不一致，新建dayInfoJson(日数据json)
                                if (!"J00476".equals(station.getStationCode()) && !"T00002-A".equals(station.getStationCode()) && !"J00971-A".equals(station.getStationCode())) {
                                    if (!thisDate.equals(compareDate)) {
                                        // 如果不是第一条，且和上一条日期不是同一天，则将上条日期的96条数据放入日json数据
                                        if (!"".equals(compareDate)) {
                                            dayInfoJson.set("datas", datas);
                                            valuesArr.add(dayInfoJson);
                                            datas = new JSONArray();
                                        }
                                        // 将当条日期放入compareDate
                                        compareDate = thisDate;
                                        // 新建日json数据
                                        dayInfoJson = new JSONObject();
                                        dayInfoJson.set("date", thisDate);
                                        dayInfoJson.set("version", version);
                                        dayInfoJson.set("recDate", recDate);
                                    }
                                }
                                // 每一条数据的json，放入预测数据和预测时间
                                oneJson = new JSONObject();
                                BigDecimal bigData = new BigDecimal(string_arr[3]);
                                bigData = bigData.multiply(new BigDecimal("1000"));
                                oneJson.set("data", bigData);
                                oneJson.set("time", string_arr[2]);
                                // 将一每条数据放入datas(一天的json)中
                                datas.add(oneJson);
                            }
                        }
                    }

                    // 将最后一日数据放入valuesArr
                    dayInfoJson.set("datas", datas);
                    valuesArr.add(dayInfoJson);

                    // 将短期预测数据放入powerJson中
                    JSONObject powerJson = putPowerJson(station.getStationCode(), "power", valuesArr);
                    //返回短期数据JSONArray
                    resultArr.add(powerJson);
                    // 如果是超短期
                } else if ("cdq".equals(type)) {
                    while ((stringLine = dqBufferedReader.readLine()) != null) {
                        String[] string_arr = stringLine.split("\t");
                        if (string_arr.length == 4 && string_arr[0].startsWith("#")) {
                            if (StrUtil.isNotEmpty(string_arr[2])) {
                                if ("#1".equals(string_arr[0])) {
                                    cdqFileStartTime = string_arr[2];
                                    datas = new JSONArray();
                                    dayInfoJson = new JSONObject();
                                    dayInfoJson.set("date", cdqFileStartTime);
                                    dayInfoJson.set("version", version);
                                    dayInfoJson.set("recDate", recDate);
                                }
                                oneJson = new JSONObject();
                                oneJson.set("data", string_arr[3]);
                                oneJson.set("time", string_arr[2]);
                                // 将一每条数据放入datas(一天的json)中
                                datas.add(oneJson);
                                // 每一条数据的json，放入预测数据和预测时间
                                oneJson = new JSONObject();
                                BigDecimal bigData = new BigDecimal(string_arr[3]);
                                oneJson.set("data", new BigDecimal("1000").multiply(bigData));
                                oneJson.set("time", string_arr[2]);
                                // 将一每条数据放入datas(一天的json)中
                                datas.add(oneJson);
                            }
                        }
                    }
                    // 将最后一日数据放入vaulesArr
                    dayInfoJson.set("datas", datas);
                    valuesArr.add(dayInfoJson);
                    // 将短期预测数据放入powerJson中
                    JSONObject powerJson = putPowerJson(station.getStationCode(), "power", valuesArr);
                    //返回短期数据JSONArray
                    resultArr.add(powerJson);
                } else if ("nwp".equals(type)) {
                    while ((stringLine = dqBufferedReader.readLine()) != null) {
                        String[] string_arr = stringLine.split("\t");
                        if (string_arr[0].startsWith("#")) {
                            if (StrUtil.isNotEmpty(string_arr[2])) {
                                // 每一条数据的json，放入预测数据和预测时间
                                oneJson = new JSONObject();
                                oneJson.set("farmId", string_arr[1]);
                                oneJson.set("scDate", string_arr[2]);
                                oneJson.set("scTime", string_arr[3]);
                                oneJson.set("preDate", string_arr[4]);
                                oneJson.set("preTime", string_arr[5]);
                                oneJson.set("t", new BigDecimal(string_arr[6]).subtract(new BigDecimal("273.15")));
                                oneJson.set("rh", new BigDecimal(string_arr[7]));
                                oneJson.set("pressure", new BigDecimal(string_arr[8]));
                                oneJson.set("swr", new BigDecimal(string_arr[9]));
                                oneJson.set("lwr", new BigDecimal(string_arr[10]));
                                oneJson.set("senf", new BigDecimal(string_arr[11]));
                                oneJson.set("ws10", new BigDecimal(string_arr[12]));
                                oneJson.set("ws30", new BigDecimal(string_arr[13]));
                                oneJson.set("ws50", new BigDecimal(string_arr[14]));
                                oneJson.set("ws70", new BigDecimal(string_arr[15]));
                                oneJson.set("ws80", new BigDecimal(string_arr[16]));
                                oneJson.set("ws90", new BigDecimal(string_arr[17]));
                                oneJson.set("ws100", new BigDecimal(string_arr[18]));
                                oneJson.set("ws170", new BigDecimal(string_arr[19]));
                                oneJson.set("wd10", new BigDecimal(string_arr[20]));
                                oneJson.set("wd30", new BigDecimal(string_arr[21]));
                                oneJson.set("wd50", new BigDecimal(string_arr[22]));
                                oneJson.set("wd70", new BigDecimal(string_arr[23]));
                                oneJson.set("wd80", new BigDecimal(string_arr[24]));
                                oneJson.set("wd90", new BigDecimal(string_arr[25]));
                                oneJson.set("wd100", new BigDecimal(string_arr[26]));
                                oneJson.set("wd170", new BigDecimal(string_arr[27]));
                                // 将一每条数据放入datas(一天的json)中
                                datas.add(oneJson);
                            }
                        }
                    }
                    // 将最后一日数据放入valuesArr
                    dayInfoJson.set("datas", datas);
                    valuesArr.add(dayInfoJson);
                    // 将短期预测数据放入powerJson中
                    JSONObject powerJson = putPowerJson(station.getStationCode(), "nwp", valuesArr);
                    //返回短期数据JSONArray
                    resultArr.add(powerJson);

                }
            } catch (Exception e) {
                jx = false;
                log.error(station.getStationCode() + " 解析当天DQ文件错误:", e);
                return JsonResultUtil.failure(" 解析当天DQ文件错误:");
            } finally {
                close(dqBufferedReader, dqRead);
            }
        }
        //如果解析成功
        if (jx) {
            return JsonResultUtil.success(resultArr);
        } else {
            return JsonResultUtil.failure("解析失败");
        }
    }

    /**
     * 关闭文件流
     *
     * @param bufferedReader 字符数据
     * @param read           字节流
     */
    private void close(BufferedReader bufferedReader, InputStreamReader read) {
        try {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
            if (read != null) {
                read.close();
            }
        } catch (IOException e) {
            log.error("关闭文件流失败:", e);
        }
    }

    /**
     * 拼接短期修正后数据Map
     *
     * @param dqDate
     * @param stationName
     * @param station
     * @return
     */
    public List<Map<String, Object>> getDqListMap(Station station, JSONArray dqDate, String stationName) {
        List<Map<String, Object>> result = new ArrayList<>();
        // 获取当前时间
        String dateNow = DateUtil.format(new Date(), "yyyy-MM-dd");
        JSONObject errMsg = new JSONObject();
        // 下载当天文件
        File file = downLoadFileFromMinIo(station, "dq", dateNow, dateNow, errMsg);
        //解析短期文件，并获取当天数据
        JSONObject todayData = fileAnalysis(file, station, "dq", dateNow, dateNow);
        if (JsonResultUtil.Type.success.value().equals(todayData.get(JsonResultUtil.CODE_TAG))) {
            addListData(result, todayData, stationName, "minIo");
        }
        // 将修正后的明天的数据放入
        addListData(result, JsonResultUtil.success(dqDate), stationName, "other");
        // 获取后天日期
        LocalDateTime dayAfterTomorrowDateTime = LocalDateTime.now().plus(2, ChronoUnit.DAYS);
        String dayAfterTomorrowStr = dayAfterTomorrowDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        //解析短期文件，并获取后天之后的数据
        JSONObject otherData = fileAnalysis(file, station, "dq", dayAfterTomorrowStr, "2123-01-01");
        // 放入后天之后的数据
        if (JsonResultUtil.Type.success.value().equals(otherData.get(JsonResultUtil.CODE_TAG))) {
            addListData(result, otherData, stationName, "minIo");
        }
        return result;
    }

    /**
     * 生成文件
     *
     * @param station  场站信息
     * @param listDate 数据列表
     * @param vmsPath  模板路径
     * @param dateType 数据类型(CORR:修正)
     * @param fileType 文件类型(DQ/CDQ)
     * @return
     */
    public JSONObject genFile(Station station, List<Map<String, Object>> listDate, String vmsPath, String dateType, String fileType) {
        Template template = this.velocityEngine.getTemplate(vmsPath);
        if (template == null) {
            log.info("模板为空");
            return JsonResultUtil.failure("生成模板为空");
        }
        // 初始化模板
        VelocityContext velocityContext = new VelocityContext();
        // 将数据放入模板中
        velocityContext.put("date", DateUtil.format(new Date(), "yyyy-MM-dd"));
        velocityContext.put("stationName", station.getName());
        velocityContext.put("vList", listDate);
        // 将数据写入模板
        StringWriter writer = new StringWriter();
        template.merge(velocityContext, writer);
        // 生成文件的路径
        String fUrl = fileDir + File.separatorChar + "correct" + File.separatorChar + station.getStationCode();
        log.info("生成文件的路径" + fUrl);
        // 初始化文件路径
        File fileUrl = new File(fUrl);
        if (!fileUrl.exists()) {// 判断目录是否存在
            fileUrl.mkdirs();
        }
        Date now = new Date();
        // 文件名
        String fileName = fileType + "_" + DateUtil.format(now, "yyyyMMddHHmmss") + "0" + dateType + ".RB";

        // 根据文件路径和文件名，初始化文件
        File file = new File(fUrl + File.separatorChar + fileName);
        // 文件输出入流
        FileOutputStream os = null;
        try {
            // 创建文件
            boolean res = file.createNewFile();
            // 如果创建成功，将数据写入
            if (res) {
                os = new FileOutputStream(file);
                // 采用UTF-8字符集
                os.write(writer.toString().getBytes("UTF-8"));
                os.flush();
            } else {
                log.warn(station.getStationCode() + " 生成" + fileType + "文件失败");
            }
        } catch (IOException e) {
            e.printStackTrace();
            log.warn(station.getStationCode() + " 创建" + fileType + "文件失败");
            return JsonResultUtil.failure(" 创建" + fileType + "文件失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("文件生成关闭流失败", e);
                }
            }
        }
        log.info("生成文件名" + file.getName());
        // 将生成的文件放入MinIo
        JSONObject pushMinIoResult = pushFileToMinIo(file, station.getStationCode());
        if (JsonResultUtil.Type.failure.value().equals(pushMinIoResult.get(JsonResultUtil.CODE_TAG))) {
            return JsonResultUtil.failure(pushMinIoResult.get(JsonResultUtil.DETAIL_TAG));
        }
        // 获取推送到minIo的文件名
        String minIoFileUrl = pushMinIoResult.getStr(JsonResultUtil.DATA_TAG);
        String[] minIoFileUrlArr = minIoFileUrl.split(";");
        String pushDate = DateUtil.format(now, "yyyyMMdd");
        if (minIoFileUrlArr.length > 1) {
            for (String url : minIoFileUrlArr) {
                if (url.contains(station.getStationCode())) {
//                    postFileCreateInfoToCloud(station.getStationCode(), file.getName(), url);
                    pushCorr(station, file.getName(), pushDate, url);
                } else {
                    station.setStationCode(station.getStationCode().replace("-A", "-B"));
//                    postFileCreateInfoToCloud(station.getStationCode(), file.getName(), url);
                    pushCorr(station, file.getName(), pushDate, url);
                }
            }
        } else {
            // 如果文件放成功，回传文件生成信息到云端
            postFileCreateInfoToCloud(station.getStationCode(), file.getName(), pushMinIoResult.getStr(JsonResultUtil.DATA_TAG));
            pushCorr(station, file.getName(), pushDate, minIoFileUrl);
        }
        return JsonResultUtil.success();
    }

    /**
     * 向minIo中放入文件
     *
     * @param file
     * @param stationCode
     * @return
     */
    public JSONObject pushFileToMinIo(File file, String stationCode) {
        // 存放完文件后返回的文件路径
        String minIoFileUrl;
        InputStream in = null;
        InputStream inB = null;
        try {
            // 查看桶名称是否存在
//            boolean flag = minioUtilService.bucketExists(bucketName);
//            if (!flag) {
//                return JsonResultUtil.failure("MinIo桶不存在");
//            }
            // 向minIo中放入文件
            in = new FileInputStream(file);
            byte[] bytes = IOUtils.toByteArray(in);
            String fileName =  stationCode + "/" + file.getName();
            minIoFileUrl = HuaWeiObsUtil.uploadFile(bucketName, fileName, bytes);
            // 如果是AB机，向B中也放入文件
            if (stationCode.indexOf("-A") > 0) {
                // InputStream 在被读取后，指针已经移动到了流的末尾，第二次上传B时就已经没有数据了，故新建一个输入流
                inB = new FileInputStream(file);
                byte[] byteB = IOUtils.toByteArray(inB);
                String fileNameB =  stationCode.replace("-A", "-B") + "/" + file.getName();
                minIoFileUrl = minIoFileUrl + ";" + HuaWeiObsUtil.uploadFile(bucketName, fileNameB, byteB);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonResultUtil.failure("推送MinIo失败");
        }finally {
            close(in);
            close(inB);
        }
        return JsonResultUtil.success(minIoFileUrl);
    }

    /**
     * 请求V3云平台返回上传minIo文件信息
     *
     * @param stationCode
     * @param fileName
     * @param fileDownloadUrl
     */
    public void postFileCreateInfoToCloud(String stationCode, String fileName, String fileDownloadUrl) {
        fileDownloadUrl = fileDownloadUrl.split("\\?")[0];
        Map<String, Object> urlMap = new HashMap<>();
        urlMap.put("stationCode", stationCode);
        urlMap.put("stationName", stationCode);
        urlMap.put("fileName", fileName);
        urlMap.put("fileDownloadUrl", fileDownloadUrl);
        urlMap.put("sign", SystermUtils.caluMd5Sign(stationCode + DateUtil.today()));
        try {
            String body = HttpUtil.post(cloudFileCreateLog, urlMap, 10000);
            JSONObject result = JSONUtil.parseObj(body);
            if (!"0".equals(result.getStr(JsonResultUtil.CODE_TAG))) {
                log.info("请求V3云平台失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("请求V3云平台失败");
        }
    }

    /**
     * 从minIo下载文件
     *
     * @param station
     * @param type
     * @return
     */
    public File downLoadFileFromMinIo(Station station, String type, String startTime, String endTime, JSONObject errMsg) {
        // 如果场站信息为空
        if (station == null) {
            log.info("场站信息为空");
            errMsg.set("msg", "场站信息为空");
            return null;
        }

        if (startTime == null || "".equals(startTime)) {
            log.info("文件获取失败，开始时间为空");
            errMsg.set("msg", "文件获取失败，开始时间为空");
            return null;
        }

        // 校验日期格式
        if (startTime.indexOf("-") == -1) {
            log.info("文件获取失败，开始时间格式不正确，正确格式为yyyy-MM-dd");
            errMsg.set("msg", "文件获取失败，开始时间格式不正确，正确格式为yyyy-MM-dd");
            return null;
        }

        Record record = new Record();
        log.info("下载minIo原始RB文件 --> {}" + station.getStationCode());
        try {
            // 从云上获取minIo中指定日期的文件信息 格式https://117.78.19.70:9010/client/getFileLogsForAio/J00260/2023-08-11
            String getUrl = url + station.getStationCode() + "/" + startTime;
            HttpRequest httpRequest = HttpRequest.get(getUrl);
            httpRequest.setGlobalTimeout(20000);
            String body = httpRequest.execute().body();
            JSONObject json = JSONUtil.parseObj(body);
            String data = json.get("data").toString();
            String code = json.get("code").toString();
            if (!code.equals("0") || data.length() <= 0) {
                record.setState(StatusEnum.RESPONSE_FAIL.getCode());
                log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
                errMsg.set("msg", "下载原始文件失败");
                return null;
            }
            // 获取文件信息列表
            JSONArray array = JSONUtil.parseArray(data);
            // 文件列表
            List<FileCreateLog> list = array.toList(FileCreateLog.class);
            // 如果文件列表为空，则未获取到文件
            if (CollectionUtil.isEmpty(list)) {
                record.setState(StatusEnum.FILE_NULL.getCode());
                log.info("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
                errMsg.set("msg", "下载原始文件失败");
                return null;
            }

            // 保存文件路径
            String fileSaveUrl = fileDir + File.separatorChar + "init" + File.separatorChar + station.getStationCode();
            log.info("文件保存路径" + fileSaveUrl);
            File dir = new File(fileSaveUrl);
            if (!dir.exists()) {// 判断目录是否存在
                dir.mkdirs();
                log.info("创建目录:" + fileSaveUrl);
            }
            // 筛选指定日期短期文件
            List<FileCreateLog> listFile = new ArrayList<>();
            String nowUrl = "";
            String downloadFileName = "";
            // 如果是短期
            if ("dq".equals(type)) {
                listFile = list.stream().filter(f -> f.getFileName().contains("DQ_" + startTime.replace("-", ""))).collect(Collectors.toList());
                //  如果文件为空，
                if (CollectionUtil.isEmpty(listFile)) {
                    record.setState(StatusEnum.FILE_NULL.getCode());
                    log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode() + " DQ文件", StatusEnum.FILE_NULL.getMsg());
                    errMsg.set("msg", "下载原始文件失败");
                    return null;
                }
                // 将短期文件倒序，获取最新的文件
                listFile.sort(Comparator.comparing(FileCreateLog::getFileName).reversed());
                // 拼接下载文件url=fileUrl(下载文件请求地址)+从minIo获取的最新一条的文件id
                nowUrl = fileurl + listFile.get(0).getId();
                downloadFileName = listFile.get(0).getFileName();
                // 如果是超短期
            } else if ("cdq".equals(type)) {
                // 格式化开始时间 将时间2019-10-10 01:15 转为=》201910100115
                String formatStartTime = startTime.replace("-", "").replace(" ", "").replace(":", "");
                // 根据CDQ_201910100115 筛选超短期文件
                listFile = list.stream().filter(f -> f.getFileName().contains("CDQ_" + formatStartTime)).collect(Collectors.toList());
            } else if ("nwp".equals(type)) {
                listFile = list.stream().filter(f -> f.getFileName().contains("NWP_" + startTime.replace("-", ""))).collect(Collectors.toList());
                // 将短期文件倒序，获取最新的文件
                listFile.sort(Comparator.comparing(FileCreateLog::getFileName).reversed());
                // 拼接下载文件url=fileUrl(下载文件请求地址)+从minIo获取的最新一条的文件id
                nowUrl = fileurl + listFile.get(0).getId();
                downloadFileName = listFile.get(0).getFileName();
            }
            //  如果文件为空，
            if (CollectionUtil.isEmpty(listFile)) {
                log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
                record.setState(StatusEnum.FILE_NULL.getCode());
                errMsg.set("msg", "下载原始文件失败");
                return null;
            }

            try {
                // 通过url下载文件
                File nowFile = HttpUtil.downloadFileFromUrl(nowUrl, fileSaveUrl + File.separatorChar + downloadFileName);
                if (nowFile == null) {
                    record.setState(StatusEnum.DOWNLOAD_FILE_ERROR.getCode());
                    log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.FILE_NULL.getMsg());
                    errMsg.set("msg", "下载原始文件失败");
                    return null;
                }

                // 回传dq和nwp文件状态
                this.postBackMinIoState(station.getStationCode(), nowFile.getName(), "down", "是");
                // 返回文件
                return nowFile;
            } catch (Exception e) {
                record.setState(StatusEnum.DOWNLOAD_FILE_FAIL.getCode());
                log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.DOWNLOAD_FILE_FAIL.getMsg());
                e.printStackTrace();
                errMsg.set("msg", "下载原始文件失败");
                return null;
            }
        } catch (Exception e) {
            record.setState(StatusEnum.RESPONSE_FAIL.getCode());
            log.error("下载minIo原始RB文件 --> {} 失败，失败原因:{}", station.getStationCode(), StatusEnum.RESPONSE_FAIL.getMsg());
            e.printStackTrace();
            errMsg.set("msg", "下载原始文件失败");
            return null;
        }
    }

    /**
     * 向list中添加数据
     *
     * @param list
     * @param data
     * @param stationName
     * @param type
     * @return
     */
    public List<Map<String, Object>> addListData(List<Map<String, Object>> list, JSONObject data, String stationName, String type) {
        if (JsonResultUtil.Type.success.value().equals(data.get(JsonResultUtil.CODE_TAG))) {
            JSONArray dataArr;
            if ("minIo".equals(type)) {
                dataArr = data.getJSONArray("data").getJSONObject(0).getJSONArray("values");
                for (Object one : dataArr) {
                    JSONArray oneDaysData = JSONUtil.parseObj(one).getJSONArray("datas");
                    addOneDay(list, oneDaysData, stationName);
                }
            } else if ("other".equals(type)) {
                dataArr = data.getJSONArray("data");
                addOneDay(list, dataArr, stationName);
            }
        }
        return list;
    }

    /**
     * 添加1天的数据
     *
     * @param list
     * @param dataArr
     * @param stationName
     * @return
     */
    public List<Map<String, Object>> addOneDay(List<Map<String, Object>> list, JSONArray dataArr, String stationName) {
        for (Object one : dataArr) {
            JSONObject oneJson = JSONUtil.parseObj(one);
            Map<String, Object> map = new HashMap<>();
            map.put("stationName", stationName);
            map.put("fpValue", oneJson.getStr("data") == null ? "-99" : new BigDecimal(oneJson.getStr("data")).divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP));
            map.put("forecastTime", oneJson.getStr("time").length() == 16 ? oneJson.getStr("time") + CommonStant.CHARACTER_TIME_ZERO : oneJson.getStr("time"));
            list.add(map);
        }
        return list;
    }

    /**
     * 从minIo下载文件后，回传状态
     *
     * @param stationCode
     * @param fileName
     * @param type
     * @param status
     */
    @Override
    public void postBackMinIoState(String stationCode, String fileName, String type, String status) {
        Map urlParams = new HashMap(4);
        urlParams.put("stationCode", stationCode);
        urlParams.put("forecastFileName", fileName);
        urlParams.put("type", type);
        urlParams.put("status", status);
        log.debug("回传文件状态给新平台,请求参数", JSONUtil.toJsonStr(urlParams));
        String repose = HttpUtil.post(postBackUrl, urlParams, 10000);
        log.info("回传文件状态给新平台，请求相应 {}", repose);
    }

    /**
     * 设置短期数据
     *
     * @param stationCode
     * @param type
     * @param valuesArr
     * @return
     */
    public JSONObject putPowerJson(String stationCode, String type, JSONArray valuesArr) {
        JSONObject result = new JSONObject();
        result.set("wfId", stationCode);
        result.set("type", type);
        result.set("values", valuesArr);
        return result;
    }

    /**
     * @param station
     * @param fileName
     * @param url
     */
    public void pushCorr(Station station, String fileName, String pushDate, String url) {
        // 如果场站信息为空或者 不推送修正数据
        if (station == null || "0".equals(station.getIsPushCorr())) {
            return;
        }
        Map params = new HashMap(5);
        params.put("stationCode", station.getStationCode());
        params.put("forecastDay", pushDate);
        params.put("forecastFileName", fileName);
        String fileDownloadUrl = url.split("\\?")[0];
        params.put("fileDownloadPath", fileDownloadUrl);
        params.put("remark", "数源:一体化修正");
        log.info("发送下发修正文件请求");
        String repose = HttpUtil.post(pushCorrFileUrl, params, 10000);
        log.info("发送下发修正文件请求，请求响应 {}", repose);
    }

    /*----------------------------------------------------------以下为新增-----------------------------------------------------------------*/

    /**
     * 获取所有今天的数据返给站端
     *
     * @param station
     * @param initTime
     * @return
     */
    @Override
    public JSONObject getSHCorrect(Station station, LocalDateTime initTime) {
        JSONArray jsonArray = new JSONArray();
        JSONObject finalJsonObject = new JSONObject();
        List<Map<String, Object>> list = new ArrayList<>();
        if (station.getInCode().equals("SHKJLN")) {
            List<ForecastData> forecastDataList = forecastDataService.findInitTimeByStation(initTime, station.getStationCode());
            if (forecastDataList.size() > 0) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                forecastDataList.stream().sorted(Comparator.comparing(ForecastData::getForecastTime));

                for (ForecastData forecastData : forecastDataList) {
                    Map<String, Object> map = new HashMap<>();
                    if (null != forecastData.getFpValueCorrect()) {
                        map.put("power", forecastData.getFpValueCorrect());
                    } else {
                        map.put("power", forecastData.getFpValue());
                    }
                    map.put("time", simpleDateFormat.format(forecastData.getForecastTime()));
                    list.add(map);
                }
                // 将 List<Map<String, Object>> 转换为 JSONArray
                jsonArray = new JSONArray();
                for (Map<String, Object> map : list) {
                    JSONObject jsonObject = new JSONObject(map);
                    jsonArray.add(jsonObject);
                }
                // 将 JSONArray 嵌入到一个 JSONObject 中
                finalJsonObject.put("code", 200);
                finalJsonObject.put("station_id", station.getStationCode());
                finalJsonObject.put("data", jsonArray);
            } else {
                finalJsonObject.put("code", 500);
                finalJsonObject.set("msg", "当天没有下载原始数据，请使用原始数据直接上送");
                return finalJsonObject;
            }
            return finalJsonObject;
        } else {
            finalJsonObject.put("code", 500);
            finalJsonObject.set("msg", "无该场站相关信息！");
            return finalJsonObject;
        }

    }

    /**
     * 获取武穴原始超短期数据
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject getUltraShortTermData(JSONObject requestJson) {
        JSONObject result = new JSONObject();
        JSONArray stationCodeArr = requestJson.getJSONArray("stationIds");
        JSONArray dateTimeArr = requestJson.getJSONArray("datetime");
        JSONArray dataArr = new JSONArray();

        // 创建一个最外层的LinkedHashMap
        Map<String, Map<String, Double>> outerMap = new LinkedHashMap<>();

        for (Object o : dateTimeArr) {
            Long genDte = Long.valueOf(o.toString());
            List<UltraShortTerm> ultraShortTermList = ultraShortTermService.findByGenDate(genDte, stationCodeArr.get(0).toString());

            // 注意：这里应该使用 sorted() 的返回结果，因为它返回一个新的排序后的流
            // 如果你需要保留排序后的列表，应该使用 collect(Collectors.toList())
            List<UltraShortTerm> sortedUltraShortTermList = ultraShortTermList.stream()
                    .sorted(Comparator.comparing(UltraShortTerm::getForecastTime))
                    .collect(Collectors.toList());

            Map<String, Double> innerMap = new LinkedHashMap<>();
            for (UltraShortTerm ultraShortTerm : sortedUltraShortTermList) {
                innerMap.put(ultraShortTerm.getForecastTime().toString(), ultraShortTerm.getFpValue().doubleValue());
            }
            outerMap.put(genDte.toString(), innerMap);
        }

        if (!outerMap.isEmpty()) {
            result.put("statusCode", "1000");
            result.put("message", "请求成功");
            result.put("result", "OK");
            result.put("data", outerMap);  // 直接将 outerMap 作为 data 的值
        } else {
            result.put("statusCode", "1004");
            result.put("message", "系统异常");
            result.put("result", "FALSE");
        }

        return result;
    }

    /**
     * 接收超短期原始数据存入数据库
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject putUltraShortTermData(JSONObject requestJson) {
        JSONObject result = new JSONObject();
        String stationCodeArr = requestJson.getStr("stationIds");
        Long genDate = Long.valueOf(requestJson.getStr("genDate"));
        List<UltraShortTerm> ultraShortTermList = new ArrayList<>();
        try {
            ultraShortTermList = correctWindData(requestJson.getStr("data"), stationCodeArr, genDate);
            if (ultraShortTermList.size() > 0) {
                log.info("接收原始超短期数据：{}", ultraShortTermList.size());
                ultraShortTermService.save(ultraShortTermList);
                result.set("retCode", 200);
                result.set("retMsg", "接收超短期原始数据成功！");
            } else {
                log.info("接收原始超短期数据失败！数据为空！");
                result.set("retCode", 500);
                result.set("retMsg", "接收原始超短期数据失败！");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 接收实际功率数据
     *
     * @param requestJson
     * @return
     */
    @Override
    public JSONObject putRealValueData(JSONObject requestJson) {
        JSONObject result = new JSONObject();
        String stationCodeArr = requestJson.getStr("stationIds");
        Long genDate = Long.valueOf(requestJson.getStr("genDate"));
        List<PowerStationStatusData> powerStationStatusDataList = new ArrayList<>();
        try {
            powerStationStatusDataList = correctRealValueData(requestJson.getStr("data"), stationCodeArr, genDate);
            if (powerStationStatusDataList.size() > 0) {
                log.info("接收实际功率数据：{}", powerStationStatusDataList.size());
                powerStationStatusDataService.save(powerStationStatusDataList);
                result.set("retCode", 200);
                result.set("retMsg", "接收实际功率数据成功！");
            } else {
                log.info("接收实际功率数据失败！数据为空！");
                result.set("retCode", 500);
                result.set("retMsg", "接收实际功率数据失败！");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 解析传入超短期数据
     *
     * @param data 待解析数据
     * @return 解析数据
     * @throws Exception
     */
    public List<UltraShortTerm> correctWindData(String data, String stationCode, Long genDate) throws Exception {

        data = data.substring(1, data.length() - 1);
        String[] content = data.split("(?<=})\\s*,\\s*");

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

        for (int i = 0; i < content.length; i++) {

            UltraShortTerm inUltraShortTerm = new UltraShortTerm();
            String column = content[i];

            //JSON 字符串转换为一个树状结构
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(column);
            // 通过键名获取相应的值
            String forecastTime = rootNode.get("forecastTime").asText();
            double fpValue = rootNode.get("fpValue").asDouble();
            // 将预测时间转换为时间戳格式
            Long forecast = Long.valueOf(forecastTime);

            inUltraShortTerm.setGenDate(genDate);
            inUltraShortTerm.setForecastTime(forecast);
            inUltraShortTerm.setFpValue(isNumberOrNull(String.valueOf(fpValue)));
            inUltraShortTerm.setStationCode(stationCode);
            list.add(inUltraShortTerm);
        }
        return list;
    }


    /**
     * 解析传入实际功率数据
     *
     * @param data 待解析数据
     * @return 解析数据
     * @throws Exception
     */
    public List<PowerStationStatusData> correctRealValueData(String data, String stationCode, Long genDate) throws Exception {

        data = data.substring(1, data.length() - 1);
        String[] content = data.split("(?<=})\\s*,\\s*");

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

        for (int i = 0; i < content.length; i++) {

            PowerStationStatusData powerStationStatusData = new PowerStationStatusData();
            String column = content[i];

            //JSON 字符串转换为一个树状结构
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(column);
            // 通过键名获取相应的值
            String forecastTime = rootNode.get("forecastTime").asText();
            double fpValue = rootNode.get("fpValue").asDouble();
            // 将预测时间转换为时间戳格式
            Long forecast = Long.valueOf(forecastTime);

            powerStationStatusData.setGenDate(genDate);
            powerStationStatusData.setForecastTime(forecast);
            powerStationStatusData.setRealValue(isNumberOrNull(String.valueOf(fpValue)));
            powerStationStatusData.setStationCode(stationCode);
            list.add(powerStationStatusData);
        }
        return list;
    }


    /**
     * 判断是否是NULL 和是否是数值
     *
     * @param data
     * @return
     */
    public BigDecimal isNumberOrNull(String data) {
        BigDecimal bigDecimal = new BigDecimal("-99");
        if (!data.contains("null") && !data.contains("NULL")) {

            Pattern pattern = Pattern.compile("-[0-9]+(.[0-9]+)?|[0-9]+(.[0-9]+)?");
            Matcher isNum = pattern.matcher(data);
            try {
                if (isNum.matches()) {
                    bigDecimal = new BigDecimal(data).setScale(2, BigDecimal.ROUND_DOWN);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return bigDecimal;
    }

    // 封装一个安全的关闭方法
    private static void close(InputStream inputStream) {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace(); // 可选：日志记录
            }
        }
    }
}
