package com.jiayue.insu.inclientqn.service.client;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.util.StrUtil;
import com.jiayue.insu.inclientqn.constant.CommonStant;
import com.jiayue.insu.inclientqn.entity.*;
import com.jiayue.insu.inclientqn.inenum.ElectricFieldTypeEnum;
import com.jiayue.insu.inclientqn.inenum.QNHLEnum;
import com.jiayue.insu.inclientqn.inenum.StatusEnum;
import com.jiayue.insu.inclientqn.service.*;
import com.jiayue.insu.inclientqn.util.DateTimeUtils;
import com.jiayue.insu.inclientqn.util.SystermUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @description: 回传数据文件解析
 * @author: yuanhao
 * @createDate: 2022/6/17
 * @version: 1.0
 */
@Service
@Slf4j
@RequiredArgsConstructor
@RefreshScope
public class BackDataAnalysisService {

    @Value("${backdata.filepath}")
    private String backFilePath;

    private final RecordService recordService;

    private final StationService stationService;

    private final BackStatDataService backStatDataService;

    private final BackForeUsForecastDataService backForeUsForecastDataService;

    private final BackForeForecastDataService backForeForecastDataService;

    private static Map<String, Map<String, Object>> labelMap = new HashMap<>();

    static {
        // 设定文件模板
        Map<String, Object> rp = new HashMap<>();
        rp.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_RealPower.getCode() + ">");
        rp.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_RealPower.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_RealPower.getCode(), rp);

        // 理论可用功率
        Map<String, Object> ty = new HashMap<>();
        ty.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_TheoryPower.getCode() + ">");
        ty.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_TheoryPower.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_TheoryPower.getCode(), ty);

        // 两则准确率
        Map<String, Object> accuracy = new HashMap<>();
        accuracy.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_AccuracyRate.getCode() + ">");
        accuracy.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_AccuracyRate.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_AccuracyRate.getCode(), accuracy);

        // 限电
        Map<String, Object> lpf = new HashMap<>();
        lpf.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_LimitPowerFlag.getCode() + ">");
        lpf.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_LimitPowerFlag.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_LimitPowerFlag.getCode(), lpf);

        Map<String, Object> rw = new HashMap<>();
        rw.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_RealWeather.getCode() + ">");
        rw.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_RealWeather.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_RealWeather.getCode(), rw);

        Map<String, Object> fpr = new HashMap<>();
        fpr.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_ForecastPowerReport.getCode() + ">");
        fpr.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_ForecastPowerReport.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_ForecastPowerReport.getCode(), fpr);

        Map<String, Object> ufpr = new HashMap<>();
        ufpr.put("label_start", "<" + QNHLEnum.DATA_STAT_TYPE_UltraShortTermForecastReport.getCode() + ">");
        ufpr.put("label_end", "</" + QNHLEnum.DATA_STAT_TYPE_UltraShortTermForecastReport.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_STAT_TYPE_UltraShortTermForecastReport.getCode(), ufpr);

        Map<String, Object> fp = new HashMap<>();
        fp.put("label_start", "<" + QNHLEnum.DATA_FORE_TYPE_ForecastPower.getCode() + ">");
        fp.put("label_end", "</" + QNHLEnum.DATA_FORE_TYPE_ForecastPower.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_FORE_TYPE_ForecastPower.getCode(), fp);

        Map<String, Object> ufp = new HashMap<>();
        ufp.put("label_start", "<" + QNHLEnum.DATA_FORE_TYPE_UltraShortTermForecast.getCode() + ">");
        ufp.put("label_end", "</" + QNHLEnum.DATA_FORE_TYPE_UltraShortTermForecast.getCode() + ">");
        labelMap.put(QNHLEnum.DATA_FORE_TYPE_UltraShortTermForecast.getCode(), ufp);
    }

    /**
     * 解析文件
     *
     * @param time
     */
    public void watchFile(Long time) {
        // 如果配置文件中回传路径未配置，则查询数据库
        if (StrUtil.isEmpty(backFilePath)) {
            // 获取回传文件路径
            backFilePath = stationService.findThis().getBackFilePath();
        }
        // 获取指定目录下所有文件夹名称
        List<String> stationCodeFileNames = SystermUtils.getFileNames(backFilePath);
        // 获取文件名
        String fileName = CommonStant.RECORD_TYPE_BACK_DATA_FILE + "_" + LocalDateTimeUtil.format(LocalDateTimeUtil.of(time), DatePattern.PURE_DATETIME_PATTERN) + ".CIME";
        File file;
        // 如果场站文件目录分为AB机的情况 例：/home/syjy/zxgl/new/J00195-A
        if (stationCodeFileNames != null && stationCodeFileNames.size() > 0) {
            // 循环场站编码
            for (String stationCode : stationCodeFileNames) {
                // 查询操作记录
                Record record = recordService.findTimeAndTypeAndStateAndStationCode(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_BACK_DATA_FILE, StatusEnum.SUCCESS.getSign(), stationCode);
                // 如果操作记录存在，则不进行解析文件
                if (record != null) {
                    log.info(LocalDateTimeUtil.of(time) + stationCode + "操作记录存在，不进行解析文件");
                    break;
                }
                file = FileUtil.file(backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                log.info("解析文件路径" + backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                // 根据文件及场站信息，解析文件
                this.analysisAndSave(time, file, stationCode);
            }
        } else {

            List<Station> stationList = stationService.findAll();
            String stationCode = "";
            if (stationList != null && stationList.size() > 0) {
                stationCode = stationList.get(0).getStationCode();
            }
            // 查询操作记录
            Record record = recordService.findTimeAndTypeAndState(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_BACK_DATA_FILE, StatusEnum.SUCCESS.getSign());
            // 如果操作记录不存在，则进行解析文件
            if (record != null) {
                log.info(LocalDateTimeUtil.of(time) + "操作记录存在，不进行解析文件");
                return;
            }
            file = FileUtil.file(backFilePath + File.separatorChar + fileName);
            // 根据文件及场站信息，解析文件
            this.analysisAndSave(time, file, stationCode);
        }
    }

    /**
     * 解析理论可用文件
     *
     * @param time
     */
    public void watchLlKyFile(Long time) {
        // 如果配置文件中回传路径未配置，则查询数据库
        if (StrUtil.isEmpty(backFilePath)) {
            // 获取回传文件路径
            backFilePath = stationService.findThis().getBackFilePath();
        }
        // 获取指定目录下所有文件夹名称
        List<String> stationCodeFileNames = SystermUtils.getFileNames(backFilePath);
        // 获取文件名
        String fileName = CommonStant.RECORD_TYPE_BACK_DATA_LLKY_FILE + "_" + LocalDateTimeUtil.format(LocalDateTimeUtil.of(time), DatePattern.PURE_DATETIME_PATTERN) + ".CIME";
        File file;
        // 如果场站文件目录分为AB机的情况 例：/home/syjy/zxgl/new/J00195-A
        if (stationCodeFileNames != null && stationCodeFileNames.size() > 0) {
            // 循环场站编码
            for (String stationCode : stationCodeFileNames) {
                // 查询操作记录
                Record record = recordService.findTimeAndTypeAndStateAndStationCode(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_BACK_DATA_LLKY_FILE, StatusEnum.SUCCESS.getSign(), stationCode);
                // 如果操作记录存在，则不进行解析文件
                if (record != null) {
                    log.info(LocalDateTimeUtil.of(time) + stationCode + "操作记录存在，不进行解析文件");
                    break;
                }
                file = FileUtil.file(backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                log.info("解析文件路径" + backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                // 根据文件及场站信息，解析文件
                this.analysisLlKyAndSave(time, file, stationCode);
            }
        } else {

            List<Station> stationList = stationService.findAll();
            String stationCode = "";
            if (stationList != null && stationList.size() > 0) {
                stationCode = stationList.get(0).getStationCode();
            }
            // 查询操作记录
            Record record = recordService.findTimeAndTypeAndState(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_BACK_DATA_LLKY_FILE, StatusEnum.SUCCESS.getSign());
            // 如果操作记录不存在，则进行解析文件
            if (record != null) {
                log.info(LocalDateTimeUtil.of(time) + "操作记录存在，不进行解析文件");
                return;
            }
            file = FileUtil.file(backFilePath + File.separatorChar + fileName);
            // 根据文件及场站信息，解析文件
            this.analysisLlKyAndSave(time, file, stationCode);
        }
    }

    public void analysisAndSave(Long time, File file, String stationCode) {
        // 获取当前时间所在15分钟节点 例如 10:18=》10:15 、 11:29=>11:15
        LocalDateTime localDateTime = LocalDateTimeUtil.of(DateTimeUtils.get15min(time));
        // 判断目录是否存在
        if (file.exists()) {
            // 初始化记录
            Record record = new Record(CommonStant.RECORD_TYPE_BACK_DATA_FILE, null, localDateTime, LocalDateTime.now(), StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getCode(), stationCode);
            try {
                // 读取文件
                FileReader fileReader = new FileReader(file);
                List<String> contents = fileReader.readLines();
                // 如果文件内容不为空
                if (CollectionUtil.isNotEmpty(contents)) {
                    // 解析文件，获取操作类型
                    String fileContentStr = fileAnalysis(contents, stationCode);
                    // 如果操作类型不为空
                    if (StrUtil.isNotEmpty(fileContentStr)) {
                        //存入操作类型和状态
                        record.setStateContent(fileContentStr);
                        record.setState(StatusEnum.SUCCESS.getCode());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                record.setCreateTime(LocalDateTime.now());
                record.setTime(localDateTime);
                recordService.save(record);
            }
        } else {
            log.info("文件不存在，路径：" + file.getAbsolutePath() + file.getName());
            Record record = new Record(CommonStant.RECORD_TYPE_BACK_DATA_FILE, null, localDateTime, localDateTime, StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getMsg(), stationCode);
            recordService.save(record);
        }
    }

    /**
     * 根据文件及场站信息，解析文件
     *
     * @param time
     * @param file
     * @param stationCode
     */
    public void analysisLlKyAndSave(Long time, File file, String stationCode) {
        // 获取当前时间所在5分钟节点
        LocalDateTime localDateTime = LocalDateTimeUtil.of(DateTimeUtils.get5min(time));
        // 判断目录是否存在
        if (file.exists()) {
            // 初始化记录
            Record record = new Record(CommonStant.RECORD_TYPE_BACK_DATA_LLKY_FILE, null, localDateTime, LocalDateTime.now(), StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getCode(), stationCode);
            try {
                // 读取文件
                FileReader fileReader = new FileReader(file);
                List<String> contents = fileReader.readLines();
                // 如果文件内容不为空
                if (CollectionUtil.isNotEmpty(contents)) {
                    // 解析理论可用文件，获取操作类型
                    String fileContentStr = fileLlKyAnalysis(contents, stationCode);
                    // 如果操作类型不为空
                    if (StrUtil.isNotEmpty(fileContentStr)) {
                        //存入操作类型和状态
                        record.setStateContent(fileContentStr);
                        record.setState(StatusEnum.SUCCESS.getCode());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                record.setCreateTime(LocalDateTime.now());
                record.setTime(localDateTime);
                recordService.save(record);
            }
        } else {
            log.info("文件不存在，路径：" + file.getAbsolutePath() + file.getName());
            Record record = new Record(CommonStant.RECORD_TYPE_BACK_DATA_LLKY_FILE, null, localDateTime, localDateTime, StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getMsg(), stationCode);
            recordService.save(record);
        }
    }

    /**
     * 解析回传数据文件
     */
    public void watchFile() {


      /*  //获取扫描文件路径
        if (StrUtil.isEmpty(backFilePath)) {
            backFilePath = stationService.findThis().getBackFilePath();
        }


        File file = FileUtil.file(backFilePath);

        if (!file.exists()) {// 判断目录是否存在
            file.mkdirs();
        }
        WatchMonitor watchMonitor = WatchMonitor.create(file, WatchMonitor.ENTRY_CREATE);

        watchMonitor.setWatcher(new DelayWatcher(new Watcher() {
            @Override
            public void onCreate(WatchEvent<?> event, Path currentPath) {
                Record record = new Record();
                record.setType(CommonStant.RECORD_TYPE_BACK_DATA_FILE);
                record.setContent("BACK_FILE_ANALYSIS");
                record.setState(StatusEnum.FILE_NULL.getCode());
                record.setStateContent(StatusEnum.FILE_NULL.getMsg());
                LocalDateTime localDateTime = LocalDateTimeUtil.of(DateTimeUtils.get15min(DateUtil.date().getTime()));
                record.setTime(localDateTime);
                record.setCreateTime(LocalDateTime.now());

                try {
                    Object obj = event.context();

                    Console.log("创建：{}-> {}", currentPath, obj);
                    if (obj.toString().startsWith(CommonStant.RECORD_TYPE_BACK_DATA_FILE)) {

                        FileReader fileReader = new FileReader(currentPath.toString() + File.separatorChar + obj.toString());
                        List<String> contents = fileReader.readLines();
                        if (CollectionUtil.isNotEmpty(contents)) {
                            String s = fileAnalysis(contents);
                            if (StrUtil.isNotEmpty(s)) {
                                record.setStateContent(s);
                                record.setState(StatusEnum.SUCCESS.getCode());
                            }

                        }


                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    record.setCreateTime(LocalDateTime.now());
                    record.setTime(localDateTime);
                    recordService.save(record);
                }


            }

            @Override
            public void onModify(WatchEvent<?> event, Path currentPath) {
                Object obj = event.context();
                Console.log("修改：{}-> {}", currentPath, obj);
            }

            @Override
            public void onDelete(WatchEvent<?> event, Path currentPath) {
                Object obj = event.context();
                Console.log("删除：{}-> {}", currentPath, obj);
            }

            @Override
            public void onOverflow(WatchEvent<?> event, Path currentPath) {
                Object obj = event.context();
                Console.log("Overflow：{}-> {}", currentPath, obj);
            }

        }, 5000));

        //设置监听目录的最大深入，目录层级大于制定层级的变更将不被监听，默认只监听当前层级目录
        watchMonitor.setMaxDepth(3);
        //启动监听
        watchMonitor.start();*/


    }

    /**
     * 解析文件并返回操作类型
     *
     * @param contents
     * @return
     */
    public String fileAnalysis(List<String> contents, String stationCode) {
        BackStatData backStatData;
        String result = "";
        // 获取文件时间
        String[] fileTime = contents.get(0).split("\\s+")[2].split("=");
        LocalDateTime signTime = LocalDateTimeUtil.parse(fileTime[1].substring(1, fileTime[1].length() - 1), DatePattern.PURE_DATETIME_PATTERN);
        LocalDateTime now = LocalDateTime.now();
        // 根据类型分类的文件内容
        Map<String, List<String>> contentMap = new HashMap<>();
        // 查询数据库中是否有相同时间点的数据
        List<BackStatData> backStatDataList = backStatDataService.findBySignTime(signTime);
        if (null != backStatDataList && backStatDataList.size() > 0) {
            backStatData = backStatDataList.get(0);
        } else {
            backStatData = new BackStatData();
        }
        // 回传数据
        backStatData.setSignTime(signTime);
        backStatData.setAnalysisTime(LocalDateTime.now());
        backStatData.setStationCode(stationCode);
        // 超短期数据
        List<BackForeUsForecastData> usList = new ArrayList<>();
        // 短期数据
        List<BackForeForecastData> list = new ArrayList<>();
        // 场站信息
        Station station = stationService.findByStationCode(stationCode);
        // 循环文件模板，根据标签内容，将文件内容分类存入map
        for (Map.Entry<String, Map<String, Object>> entry : labelMap.entrySet()) {
            Map<String, Object> map = entry.getValue();
            // 获取起始标签和结束标签
            String label_start = (String) map.get("label_start");
            String label_end = (String) map.get("label_end");
            int start_index = 0;
            int end_index = 0;
            // 获取标签头和标签尾位置
            for (int i = 0; i < contents.size(); i++) {
                if (contents.get(i).equals(label_start)) {
                    start_index = i;
                }
                if (contents.get(i).equals(label_end)) {
                    end_index = i;
                }
            }
            //标签头和标签尾相减大于2  说明除了表头 至少还有1行数据，把数据放入map
            if (end_index - start_index > 2) {
                contentMap.put(entry.getKey(), ListUtil.sub(contents, start_index + 2, end_index));
            }
        }

        // 循环分类后的文件
        for (Map.Entry<String, List<String>> entry : contentMap.entrySet()) {
            // 获取
            List<String> value = entry.getValue();
            // 判断内容分类的key名
            switch (entry.getKey()) {
                case "RealPower":
                    try {
                        String[] rpData = value.get(0).split("\\s+");
                        if (rpData.length == 3) {
                            backStatData.setRealPower(new BigDecimal(rpData[2]));
                            result += "RealPower,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "RealWeather":
                    try {
                        String[] rwData = value.get(0).split("\\s+");
                        if (station.getType().equals(ElectricFieldTypeEnum.E2.name())) {
                            if (rwData.length == 7) {
                                backStatData.setWs(new BigDecimal(rwData[2]));
                                backStatData.setWd(new BigDecimal(rwData[3]));
                                backStatData.setTemperature(new BigDecimal(rwData[4]));
                                backStatData.setHumidity(new BigDecimal(rwData[5]));
                                backStatData.setPressure(new BigDecimal(rwData[6]));
                                result += "RealWeather,";
                            }
                        } else {
                            if (rwData.length == 11) {
                                backStatData.setGlobalR(new BigDecimal(rwData[2]));
                                backStatData.setDirectR(new BigDecimal(rwData[3]));
                                backStatData.setDiffuseR(new BigDecimal(rwData[4]));
                                backStatData.setTemperature(new BigDecimal(rwData[5]));
                                backStatData.setCellT(new BigDecimal(rwData[6]));
                                backStatData.setHumidity(new BigDecimal(rwData[7]));
                                backStatData.setPressure(new BigDecimal(rwData[8]));
                                backStatData.setWs(new BigDecimal(rwData[9]));
                                backStatData.setWd(new BigDecimal(rwData[10]));
                                result += "RealWeather,";
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "TheoryPower":
                    try {
                        String[] tpData = value.get(0).split("\\s+");
                        if (tpData.length == 4) {
                            backStatData.setTheoryPower(new BigDecimal(tpData[2]));
                            backStatData.setAvailablePower(new BigDecimal(tpData[3]));
                            result += "TheoryPower,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "AccuracyRate":
                    try {
                        String[] arData = value.get(0).split("\\s+");
                        if (arData.length == 3) {
                            if ("无可用数据计算".equals(arData[2]) || "无计算公式".equals(arData[2])){
                                backStatData.setAccuracy(BigDecimal.ZERO);
                            }else {
                                backStatData.setAccuracy(new BigDecimal(arData[2]));
                            }
                            result += "AccuracyRate,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "LimitPowerFlag":
                    try {
                        String[] lpfData = value.get(0).split("\\s+");
                        if (lpfData.length == 3) {
                            backStatData.setPowerLimitSign(new BigDecimal(lpfData[2]));
                            result += "LimitPowerFlag,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "ForecastPowerReport":
                    try {
                        String[] fpr = value.get(0).split("\\s+");
                        if (fpr.length == 3) {
                            backStatData.setReportStateForecast(new BigDecimal(fpr[2]));
                            result += "fReport,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "UltraShortTermForecastReport":
                    try {
                        String[] ufpr = value.get(0).split("\\s+");
                        if (ufpr.length == 3) {
                            backStatData.setReportStateForecastshort(new BigDecimal(ufpr[2]));
                            result += "usfReport,";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "UltraShortTermForecast":
                    try {
                        for (String content : value) {
                            String[] datas = content.split("\\s+");
                            BackForeUsForecastData backForeUsForecastData = new BackForeUsForecastData();
                            backForeUsForecastData.setSignTime(signTime);
                            backForeUsForecastData.setForecastTime(LocalDateTimeUtil.parse(datas[2], DatePattern.PURE_DATETIME_PATTERN));
                            backForeUsForecastData.setForecastValue(new BigDecimal(datas[3]));
                            backForeUsForecastData.setForecastOpenCap(new BigDecimal(datas[4]));
                            backForeUsForecastData.setAnalysisTime(now);
                            backForeUsForecastData.setStationCode(stationCode);
                            usList.add(backForeUsForecastData);
                        }
                        result += "usf,";
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
                case "ForecastPower":
                    try {
                        for (String content : value) {
                            String[] datas = content.split("\\s+");
                            BackForeForecastData backForeForecastData = new BackForeForecastData();
                            backForeForecastData.setSignTime(LocalDateTimeUtil.beginOfDay(signTime));
                            backForeForecastData.setAnalysisTime(now);
                            backForeForecastData.setForecastTime(LocalDateTimeUtil.parse(datas[2], DatePattern.PURE_DATETIME_PATTERN));
                            backForeForecastData.setForecastValue(new BigDecimal(datas[3]));
                            backForeForecastData.setForecastOpenCap(new BigDecimal(datas[4]));
                            backForeForecastData.setStationCode(stationCode);
                            list.add(backForeForecastData);
                        }
                        result += "fp,";
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
        // 保存或更新回传数据
        backStatDataService.saveOrUpdate(backStatData);
        // 保存超短期数据
        backForeUsForecastDataService.saveBatch(usList);
        // 保存短期数据
        backForeForecastDataService.saveBatch(list);
        return result;
    }

    /**
     * 解析文件并返回操作类型
     *
     * @param contents
     * @return
     */
    public String fileLlKyAnalysis(List<String> contents, String stationCode) {
        BackStatData backStatData;

        String result = "";
        // 获取文件时间
        String[] fileTime = contents.get(0).split("\\s+")[2].split("=");
        LocalDateTime signTime = LocalDateTimeUtil.parse(fileTime[1].substring(1, fileTime[1].length() - 1), DatePattern.PURE_DATETIME_PATTERN);
        // 根据类型分类的文件内容
        Map<String, List<String>> contentMap = new HashMap<>();
        // 先查询库中是否有相同时间点的数据
        List<BackStatData> backStatDataList = backStatDataService.findBySignTime(signTime);
        if (null != backStatDataList && backStatDataList.size() > 0) {
            backStatData = backStatDataList.get(0);
        } else {
            backStatData = new BackStatData();
        }
        // 保存或修改回传数据
        backStatData.setSignTime(signTime);
        backStatData.setAnalysisTime(LocalDateTime.now());
        backStatData.setStationCode(stationCode);

        // 循环文件模板，根据标签内容，将文件内容分类存入map
        for (Map.Entry<String, Map<String, Object>> entry : labelMap.entrySet()) {
            Map<String, Object> map = entry.getValue();
            // 获取起始标签和结束标签
            String label_start = (String) map.get("label_start");
            String label_end = (String) map.get("label_end");
            int start_index = 0;
            int end_index = 0;
            // 获取标签头和标签尾位置
            for (int i = 0; i < contents.size(); i++) {
                if (contents.get(i).equals(label_start)) {
                    start_index = i;
                }
                if (contents.get(i).equals(label_end)) {
                    end_index = i;
                }
            }
            //标签头和标签尾相减大于2  说明除了表头 至少还有1行数据，把数据放入map
            if (end_index - start_index > 2) {
                contentMap.put(entry.getKey(), ListUtil.sub(contents, start_index + 2, end_index));
            }
        }

        // 循环分类后的文件
        for (Map.Entry<String, List<String>> entry : contentMap.entrySet()) {
            // 获取
            List<String> value = entry.getValue();
            // 判断内容分类的key名
            switch (entry.getKey()) {
                case "TheoryPower":
                    try {
                        String[] tyData = value.get(0).split("\\s+");
                        if (tyData.length == 4) {
                            backStatData.setTheoryPower(new BigDecimal(tyData[2]));
                            backStatData.setAvailablePower(new BigDecimal(tyData[3]));
                            result += "TheoryPower";
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
        }
        // 保存或更新回传数据
        backStatDataService.saveOrUpdate(backStatData);

        return result;
    }

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

    /**
     * 解析武穴回传超短期文件
     *
     * @param time
     */
    public void watchCdqFile(Long time) {
        // 如果配置文件中回传路径未配置，则查询数据库
        if (StrUtil.isEmpty(backFilePath)) {
            // 获取回传文件路径
            backFilePath = stationService.findThis().getBackFilePath();
        }
        // 获取指定目录下所有文件夹名称
        List<String> stationCodeFileNames = SystermUtils.getFileNames(backFilePath);
        // 获取文件名
        String fileName = CommonStant.RECORD_TYPE_CDQ_FILE + "_" + LocalDateTimeUtil.format(LocalDateTimeUtil.of(time), "yyyyMMdd_HHmm") + "_CDQ.PVD";
        File file;
        // 如果场站文件目录分为AB机的情况 例：/home/syjy/zxgl/new/J00195-A
        if (stationCodeFileNames != null && stationCodeFileNames.size() > 0) {
            // 循环场站编码
            for (String stationCode : stationCodeFileNames) {
                // 查询操作记录
                Record record = recordService.findTimeAndTypeAndStateAndStationCode(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_CDQ_BACK_DATA_FILE, StatusEnum.SUCCESS.getSign(), stationCode);
                // 如果操作记录存在，则不进行解析文件
                if (record != null) {
                    log.info(LocalDateTimeUtil.of(time) + stationCode + "操作记录存在，不进行解析文件");
                    break;
                }
                file = FileUtil.file(backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                log.info("解析文件路径" + backFilePath + File.separatorChar + stationCode + File.separatorChar + fileName);
                // 根据文件及场站信息，解析文件
                this.cdqAnalysisAndSave(time, file, stationCode);
            }
        } else {

            List<Station> stationList = stationService.findAll();
            String stationCode = "";
            if (stationList != null && stationList.size() > 0) {
                stationCode = stationList.get(0).getStationCode();
            }
            // 查询操作记录
            Record record = recordService.findTimeAndTypeAndState(LocalDateTimeUtil.of(time), CommonStant.RECORD_TYPE_CDQ_BACK_DATA_FILE, StatusEnum.SUCCESS.getSign());
            // 如果操作记录不存在，则进行解析文件
            if (record != null) {
                log.info(LocalDateTimeUtil.of(time) + "操作记录存在，不进行解析文件");
                return;
            }
            file = FileUtil.file(backFilePath + File.separatorChar + fileName);
            // 根据文件及场站信息，解析文件
            this.cdqAnalysisAndSave(time, file, stationCode);
        }
    }

    /**
     * 解析回传超短期文件
     *
     * @param time
     * @param file
     * @param stationCode
     */
    public void cdqAnalysisAndSave(Long time, File file, String stationCode) {
        // 获取当前时间所在15分钟节点 例如 10:18=》10:15 、 11:29=>11:15
        LocalDateTime localDateTime = LocalDateTimeUtil.of(DateTimeUtils.get15min(time));
        // 判断目录是否存在
        if (file.exists()) {
            // 初始化记录
            Record record = new Record(CommonStant.RECORD_TYPE_CDQ_BACK_DATA_FILE, null, localDateTime, LocalDateTime.now(), StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getCode(), stationCode);
            try {

                    // 解析文件，获取操作类型
                   Map<String,List> map = cdqSave(file,stationCode);
                    // 如果操作类型不为空
                    if (map.get("list").size() > 0) {
                        //存入操作类型和状态
                        record.setStateContent("CDQ");
                        record.setState(StatusEnum.SUCCESS.getCode());
                        backForeUsForecastDataService.saveOrUpdateBatch(map.get("list"));
                    }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                record.setCreateTime(LocalDateTime.now());
                record.setTime(localDateTime);
                recordService.save(record);
            }
        } else {
            log.info("文件不存在，路径：" + file.getAbsolutePath());
            Record record = new Record(CommonStant.RECORD_TYPE_CDQ_BACK_DATA_FILE, null, localDateTime, localDateTime, StatusEnum.FILE_NULL.getCode(), StatusEnum.FILE_NULL.getMsg(), stationCode);
            recordService.save(record);
        }
    }

    public Map<String,List> cdqSave(File file,String stationCode){
        List<BackForeUsForecastData> backForeUsForecastDataList = new ArrayList<>();
        List<BigDecimal> suCapacity=new ArrayList<>();
        Long signTime = null;
        // 当文件未被使用时，进行解析上报
        if (file.renameTo(file)) {
            InputStreamReader read = null;
            BufferedReader bufferedReader = null;
            String stringLine;
            BackForeUsForecastData stf;

            try {
                read = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
                bufferedReader = new BufferedReader(read);

                // 读取文件内容
                String line;
                int lineCount = 1;
                Long time = null;
                while ((line = bufferedReader.readLine()) != null) {
                    //获取预测时间
                    if (lineCount == 2) {
                        String[] timeArr = line.split("'");
                        if (timeArr.length >= 2) {
                            String dateString =timeArr[1];
                            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH:mm");
                            Date date = dateFormat.parse(dateString);
                            time = date.getTime();
                            signTime = time - 15 * 60 * 1000l;
                        }
                    }
                    if (lineCount ==6){
                        String[] dataKj = line.split("\\s+");
                        if (dataKj.length >= 2) {
                            suCapacity.add(new BigDecimal(dataKj[1]));
                        }
                    }
                    if (line.startsWith("#") && lineCount>6) {
                        stf = new BackForeUsForecastData();
                        String[] dataArr = line.split("\\s+");
                        if (dataArr.length >= 2) {
                            BigDecimal power = new BigDecimal(dataArr[1]);
                            stf.setForecastValue(power);
                            stf.setForecastTime(LocalDateTimeUtil.of(time));
                            stf.setSignTime(LocalDateTimeUtil.of(signTime));
                            stf.setStationCode(stationCode);
                            stf.setForecastOpenCap(suCapacity.get(0));
                            stf.setAnalysisTime(LocalDateTime.now());
                            backForeUsForecastDataList.add(stf);
                            time += 15 * 60 * 1000;
                        }
                    }
                    lineCount++;
                }
            }  catch (IOException | RuntimeException e) {
                log.error("系统错误：", e);
                File destFile = new File(file.getPath().replaceFirst("new", "error"));
                if (destFile.exists()) {
                    destFile.delete();
                }
                try {
                    FileUtils.moveFile(file, destFile);
                } catch (IOException e1) {
                    log.error(file.getName() + "文件解析失败", e);
                }
            } catch (ParseException e) {
                throw new RuntimeException(e);
            } finally {
                close(bufferedReader, read);
            }
        }
        Map<String ,List> map = new HashMap<>();
        map.put("list", backForeUsForecastDataList);
        map.put("suCapacity",suCapacity);
        return map;
    }
    /**
     * 关闭文件流
     *
     * @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);
        }
    }
}
