package com.jiayue.insu.incloud.pushdata;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.jiayue.insu.incloud.constants.CommonStant;
import com.jiayue.insu.incloud.constants.CompanyConstant;
import com.jiayue.insu.incloud.constants.enums.StatusEnum;
import com.jiayue.insu.incloud.entity.IntegrationCompany;
import com.jiayue.insu.incloud.entity.Record;
import com.jiayue.insu.incloud.entity.Station;
import com.jiayue.insu.incloud.service.IntegrationCompanyService;
import com.jiayue.insu.incloud.service.MinIoService;
import com.jiayue.insu.incloud.service.RecordService;
import com.jiayue.insu.incloud.utils.FileUtils;
import com.jiayue.insu.incloud.utils.SFTPUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 将数据推送至sftp
 *
 * @author changchenglong
 * @version 1.0
 * @since 2025/5/27 14:29
 */
@Component
@Slf4j
public class PushCommon {
    @Autowired
    private RecordService recordService;
    @Autowired
    private IntegrationCompanyService integrationCompanyService;
    @Autowired
    private FileUtils fileUtils;
    @Autowired
    private SFTPUtil sftpUtil;
    @Value("${localFilePath.initFilePath}")
    String initFilePath;
    @Value("${localFilePath.bjFilePath}")
    String bjFilePath;

    /**
     * 推送短期数据导sftp
     *
     * @param station
     * @param companyCode
     * @param newFilePath
     * @param newFileName
     * @param templateName
     * @param newFilePath
     * @param newFilePath
     * @return
     */
    public Boolean pushDQData(Station station, String companyCode, String newFilePath, String newFileName, String templateName) {
        // 获取场站编号
        String stationCode = station.getStationCode();
        Record record = new Record(CommonStant.RECORD_TYPE_PUSH_INIT_TO_SFTP, companyCode, stationCode, null, LocalDateTime.now(), LocalDateTime.now(), null, null);
        record.setState(StatusEnum.SUCCESS.getSign());
        // 如果场站编号为空，则返回
        if (stationCode == null || "".equals(stationCode)) {
            record.setState(StatusEnum.STATION_CODE_NULL.getSign());
            record.setStateContent(StatusEnum.STATION_CODE_NULL.getMsg());
            recordService.save(record);
            return false;
        }

        // 获取文件路径
        String filePath = initFilePath + stationCode + File.separatorChar;

        // 获取当时时间
        LocalDateTime today = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        DateTimeFormatter formatterSeparator = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String todaySeparatorStr = today.format(formatterSeparator);
        String todayStr = today.format(formatter);

        // 获取已经下载的预测文件内容
        List<String> originalContents = getInitFileLines(stationCode ,todayStr,filePath,record,"DQ");
        if (originalContents == null || originalContents.size() == 0) {
            log.error("场站{}下载的文件为空",stationCode);
            return false;
        }
        List<Map<String, Object>> vList = new ArrayList<>();
        String dataTime[];
        // 循环解析原始短期文件
        for (String originalContent : originalContents) {
            // 从有#的数据开始获取 数据示例：#1	XXX光伏电站	2023-06-22 00:00:00	0.0
            if (originalContent.contains("#")) {
                // 如果是帽子山光伏电站，刨除掉当天数据
                if (CompanyConstant.STATION_MZS_CODE.equals(stationCode)) {
                    // 刨除当天的数据
                    if (originalContent.contains(todaySeparatorStr)) {
                        continue;
                    }
                }

                // 根据分隔符分割，取时间和功率
                String[] originalContentArr = originalContent.split("\t");
                Map<String, Object> map = new HashMap<>();
                // 如果分割后的数组长度小于4，则数据格式不正确
                if (originalContentArr.length < 4) {
                    continue;
                }
                // 将时间2023-06-22 00:00:00根据分隔分割并组成2023-06-22_00:00:00格式
                dataTime = originalContentArr[2].split(" ");
                // 如果分割后的数组长度小于2，则数据格式不正确
                if (dataTime.length < 2) {
                    continue;
                }
                // 将预测时间和预测功率放入list中
                map.put("forecastTime", dataTime[0] + "_" + dataTime[1]);
                map.put("fpValue", originalContentArr[3]);
                String valueString = originalContentArr[3];
                try {
                    BigDecimal decimal = new BigDecimal(valueString);
                    map.put("upper", decimal.multiply(new BigDecimal("1.1")));
                    map.put("lower", decimal.multiply(new BigDecimal("0.9")));
                } catch (NumberFormatException e) {
                    System.err.println("输入字符串格式错误");
                }
                vList.add(map);
            }
        }

        String fileType = todayStr + File.separatorChar + "dq";
        // 文件数据开始时间
        String fileDateStr = DateUtil.format(DateUtil.beginOfDay(DateUtil.date()), "yyyyMMdd_HH:mm:ss");
        // 推送数据至sftp
        this.pushFileToSftp(record, vList, newFilePath, newFileName, templateName, station, fileType, companyCode, fileDateStr);
        return true;
    }

    /**
     * 推送nwp数据导sftp
     *
     * @param station
     * @param companyCode
     * @param newFilePath
     * @param newFileName
     * @param templateName
     * @return
     */
    public Boolean pushNWPData(Station station, String companyCode, String newFilePath, String newFileName, String templateName) {
        // 获取场站编号
        String stationCode = station.getStationCode();
        Record record = new Record(CommonStant.RECORD_TYPE_PUSH_INIT_TO_SFTP, companyCode, stationCode, null, LocalDateTime.now(), LocalDateTime.now(), null, null);
        record.setState(StatusEnum.SUCCESS.getSign());

        // 获取文件路径
        String filePath = initFilePath + stationCode + File.separatorChar;

        // 获取当时时间
        DateTime today = DateUtil.date();
        String todayStr = today.toString("yyyyMMdd");

        // 获取已经下载的预测文件内容
        List<String> originalContents = getInitFileLines(stationCode,todayStr,filePath,record,"NWP");
        if (originalContents == null || originalContents.size() == 0) {
            log.error("场站{}下载的文件为空",stationCode);
            return false;
        }

        List<Map<String, Object>> vList = new ArrayList<>();
        for (String originalContent : originalContents) {
            if (originalContent.startsWith("#")) {
                String[] string_arr = originalContent.split("\t");
                if (StrUtil.isNotEmpty(string_arr[2])) {
                    // 每一条数据的json，放入预测数据和预测时间
                    Map<String, Object> oneJson = new HashMap<>();
                    oneJson.put("farmId", string_arr[1]);
                    oneJson.put("scDate", string_arr[2]);
                    oneJson.put("scTime", string_arr[3]);
                    oneJson.put("preDate", string_arr[4]);
                    oneJson.put("preTime", string_arr[5]);
                    oneJson.put("t", new BigDecimal(string_arr[6]).subtract(new BigDecimal("273.15")));
                    oneJson.put("rh", new BigDecimal(string_arr[7]));
                    oneJson.put("pressure", new BigDecimal(string_arr[8]));
                    oneJson.put("swr", new BigDecimal(string_arr[9]));
                    oneJson.put("lwr", new BigDecimal(string_arr[10]));
                    oneJson.put("senf", new BigDecimal(string_arr[11]));
                    oneJson.put("ws10", new BigDecimal(string_arr[12]));
                    oneJson.put("ws30", new BigDecimal(string_arr[13]));
                    oneJson.put("ws50", new BigDecimal(string_arr[14]));
                    oneJson.put("ws70", new BigDecimal(string_arr[15]));
                    oneJson.put("ws80", new BigDecimal(string_arr[16]));
                    oneJson.put("ws90", new BigDecimal(string_arr[17]));
                    oneJson.put("ws100", new BigDecimal(string_arr[18]));
                    oneJson.put("ws170", new BigDecimal(string_arr[19]));
                    oneJson.put("wd10", new BigDecimal(string_arr[20]));
                    oneJson.put("wd30", new BigDecimal(string_arr[21]));
                    oneJson.put("wd50", new BigDecimal(string_arr[22]));
                    oneJson.put("wd70", new BigDecimal(string_arr[23]));
                    oneJson.put("wd80", new BigDecimal(string_arr[24]));
                    oneJson.put("wd90", new BigDecimal(string_arr[25]));
                    oneJson.put("wd100", new BigDecimal(string_arr[26]));
                    oneJson.put("wd170", new BigDecimal(string_arr[27]));
                    // 将一每条数据放入datas(一天的json)中
                    vList.add(oneJson);
                }
            }
        }

        String fileDateStr = DateUtil.format(DateUtil.beginOfDay(DateUtil.date()), "yyyy-MM-dd");
        String fileType = todayStr + File.separatorChar + "nwp";
        this.pushFileToSftp(record, vList, newFilePath, newFileName, templateName, station, fileType, companyCode, fileDateStr);
        return true;
    }

    /**
     * @param record
     * @param vList
     * @param newFilePath
     * @param newFileName
     * @param templateName
     * @param station
     * @param dateAndFileType
     * @param companyCode
     * @return
     */
    public boolean pushFileToSftp(Record record, List<Map<String, Object>> vList, String newFilePath, String newFileName, String templateName, Station station, String dateAndFileType, String companyCode, String fileDateStr) {

        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("vList", vList);
        velocityContext.put("createTime", DateUtil.format(new Date(), "yyyyMMdd_HH:mm:ss"));
        velocityContext.put("date", fileDateStr);
        velocityContext.put("stationCode", station.getStationCode());
        velocityContext.put("stationName", station.getName());
        velocityContext.put("signCode", station.getSignCode());

        File newFile;
        // 生成新文件
        try {
            newFile = fileUtils.createFileByVelocityTemplate(newFilePath, newFileName, templateName, velocityContext);
            if(newFile!=null){
                log.info("生成文件路径：{}",newFile.getAbsolutePath());
            }
        } catch (Exception e) {
            e.printStackTrace();
            record.setState(StatusEnum.CREATE_FILE_FAIL.getSign());
            record.setStateContent(StatusEnum.CREATE_FILE_FAIL.getMsg());
            recordService.save(record);
            return false;
        }
        // 获取公司信息
        IntegrationCompany integrationCompany = integrationCompanyService.findByCode(companyCode);
        String sftpInfo = integrationCompany.getPushUrl();
        String[] sftpInfoArr = sftpInfo.split(":");
        // 如果sftp的url配置不对，正确为   用户名:密码:ip:端口号:路径
        if (sftpInfoArr.length < 5) {
            record.setState(StatusEnum.PUSH_URL_ERROR.getSign());
            record.setStateContent(StatusEnum.PUSH_URL_ERROR.getMsg());
            recordService.save(record);
            return false;
        }
        String userName = sftpInfoArr[0];
        String passWord = sftpInfoArr[1];
        String sftpUrl = sftpInfoArr[2];
        // 如果端口为空
        if (sftpInfoArr[3] == null || "".equals(sftpInfoArr[3])) {
            record.setState(StatusEnum.PUSH_URL_ERROR.getSign());
            record.setStateContent(StatusEnum.PUSH_URL_ERROR.getMsg());
            recordService.save(record);
            return false;
        }
        int sftpPort = Integer.valueOf(sftpInfoArr[3]);
        String sftpFilePath = sftpInfoArr[4];
        sftpFilePath = sftpFilePath + File.separatorChar + dateAndFileType;

        log.info("getUsername:" + userName);
        log.info("getPassword:" + passWord);
        log.info("sftpUrl:" + sftpUrl);
        log.info("sftpPort:" + sftpPort);
        log.info("sftpFilePath:" + sftpFilePath);
        log.info("newFileName:" + newFile.getName());
        // 多级目录创建并上传
//        sftpFilePath = "/home/20250528/dq";
        sftpUtil.uploadByFileAndPath(userName, passWord, sftpUrl, sftpPort, newFile, sftpFilePath, newFile.getName());
        // 保存日志
        recordService.save(record);
        return true;
    }

    /**
     * 获取已经下载的预测原始文件内容
     * @return
     */
    public List<String> getInitFileLines(String stationCode,String todayStr,String filePath ,Record record ,String fileType){
        List<String> originalContents = new ArrayList<>();
        // 获取指定目录下的短期原始数据(/jiayue/insu/file/init/J00269/)
        File files = new File(filePath);
        String[] fileNames = files.list();
        // 如果文件名列表为空
        if (fileNames == null || fileNames.length == 0) {
            log.info("场站：{},指定目录:{} 下无文件",stationCode,filePath);
            record.setState(StatusEnum.FILE_NULL.getSign());
            record.setStateContent(StatusEnum.FILE_NULL.getMsg());
            recordService.save(record);
            return originalContents;
        }

        // 转为list并根据日期筛选排序
        List<String> fileList = Arrays.stream(fileNames).collect(Collectors.toList());
        List<String> filterFileList = fileList.stream().filter(s -> s.contains(todayStr)).filter(s -> s.contains(fileType)).collect(Collectors.toList());
        // 如果筛选后无文件
        if (filterFileList.size() == 0) {
            log.info("场站：{},无当日文件",stationCode);
            record.setState(StatusEnum.FILE_NULL.getSign());
            record.setStateContent(StatusEnum.FILE_NULL.getMsg());
            recordService.save(record);
            return originalContents;
        }

        // 根据时间倒序，选择最新的文件
        filterFileList.sort(Collections.reverseOrder());
        // 获取原始文件
        File originalFile = new File(filterFileList.get(0));
        // 读取文件
        FileReader fileReader = new FileReader(filePath + originalFile);
        originalContents = fileReader.readLines();
        return originalContents;
    }

}
