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.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.watch.WatchMonitor;
import cn.hutool.core.io.watch.Watcher;
import cn.hutool.core.io.watch.watchers.DelayWatcher;
import cn.hutool.core.lang.Console;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.io.File;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
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> 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);


    }


    public void watchFile(Long time){
       String fileName =  CommonStant.RECORD_TYPE_BACK_DATA_FILE+"_" +LocalDateTimeUtil.format(LocalDateTimeUtil.of(time),DatePattern.PURE_DATETIME_PATTERN)+".CIME";
        //获取扫描文件路径
        if (StrUtil.isEmpty(backFilePath)) {
            backFilePath = stationService.findThis().getBackFilePath();
        }


        File file = FileUtil.file(backFilePath+File.separatorChar +fileName);

        if (file.exists()) {// 判断目录是否存在

            Record record = new Record();
            record.setType(CommonStant.RECORD_TYPE_BACK_DATA_FILE);
            record.setState(StatusEnum.FILE_NULL.getCode());
            record.setStateContent(StatusEnum.FILE_NULL.getMsg());
            LocalDateTime localDateTime = LocalDateTimeUtil.of(DateTimeUtils.get15min(time));
            record.setTime(localDateTime);
            record.setCreateTime(LocalDateTime.now());

            try {

                    FileReader fileReader = new FileReader(file);
                    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);
            }


        }
    }

    /**
     * 解析回传数据文件
     */
    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();*/


    }


    public String fileAnalysis(List<String> contents) {
        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<>();

        BackStatData backStatData = new BackStatData();
        backStatData.setSignTime(signTime);
        backStatData.setAnalysisTime(LocalDateTime.now());

        List<BackForeUsForecastData> usList = new ArrayList<>();

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

        Station station = stationService.findThis();

        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行数据
            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();

            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 "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.setAnalysisTime(now);
                            backForeUsForecastData.setForecastTime(LocalDateTimeUtil.parse(datas[2], DatePattern.PURE_DATETIME_PATTERN));
                            backForeUsForecastData.setForecastValue(new BigDecimal(datas[3]));
                            backForeUsForecastData.setForecastOpenCap(new BigDecimal(datas[4]));
                            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]));
                            list.add(backForeForecastData);
                        }
                        result += "fp,";
                    } catch (Exception e) {
                        e.printStackTrace();
                    }


                    break;
            }
        }


        backStatDataService.save(backStatData);
        backForeUsForecastDataService.saveBatch(usList);
        backForeForecastDataService.saveBatch(list);


        return result;
    }


}
