package com.jiayue.insu.incloud.pushdata;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.jcraft.jsch.SftpException;
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.RecordService;
import com.jiayue.insu.incloud.utils.FileUtils;
import com.jiayue.insu.incloud.utils.HttpUtils;
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.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 北京中央研究院推送数据
 *
 * @author yh
 * @version 1.0
 * @since 2022/5/22 11:29
 */
@Component
@Slf4j
public class PushDataForBJZYYJY implements IPushInitForecastData {
    @Autowired
    private RecordService recordService;
    @Autowired
    private IntegrationCompanyService integrationCompanyService;
    @Autowired
    private FileUtils fileUtils;
    @Autowired
    private HttpUtils httpUtils;
    @Autowired
    private SFTPUtil sftpUtil;
    @Value("${localFilePath.initFilePath}")
    String initFilePath;
    @Value("${localFilePath.bjFilePath}")
    String bjFilePath;

    /**
     * 推送原始预测数据
     *
     * @param station 场站信息
     * @return 是否成功
     */
    @Override
    public Boolean pushDQAndNWPData(Station station) {
        return null;
    }

    /**
     * 将下载好的原始短期文件通过sftp推送
     *
     * @param station
     * @return
     */
    @Override
    public Boolean pushDQData(Station station) {
        boolean pushResult ;
        // 获取场站编号
        String stationCode = station.getStationCode();
        Record record = new Record(CommonStant.RECORD_TYPE_PUSH_INIT_TO_SFTP, CompanyConstant.COMPANY_BJZYYJY, 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;
        }
        // 获取指定目录下的短期原始数据(/jiayue/insu/file/init/J00269/)
        String filePath = initFilePath + stationCode + File.separatorChar;
        File files = new File(filePath);
        String[] fileNames = files.list();
        // 如果文件名列表为空
        if (fileNames == null || fileNames.length == 0) {
            log.info("指定目录下无文件");
            record.setState(StatusEnum.FILE_NULL.getSign());
            record.setStateContent(StatusEnum.FILE_NULL.getMsg());
            recordService.save(record);
            return false;
        }
        // 获取当天日期
        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并根据日期筛选排序
        List<String> fileList = Arrays.stream(fileNames).collect(Collectors.toList());
        List<String> filterFileList = fileList.stream().filter(s -> s.contains(todayStr)).filter(s -> s.contains("DQ")).collect(Collectors.toList());
        // 如果筛选后无文件
        if (filterFileList.size() == 0) {
            log.info("无当日文件");
            record.setState(StatusEnum.FILE_NULL.getSign());
            record.setStateContent(StatusEnum.FILE_NULL.getMsg());
            recordService.save(record);
            return false;
        }
        filterFileList.sort(Collections.reverseOrder());
        // 获取原始文件
        File originalFile = new File(filterFileList.get(0));
        // 读取文件
        FileReader fileReader = new FileReader(filePath + originalFile);
        List<String> originalContents = fileReader.readLines();

        List<Map<String, Object>> vList = new ArrayList<>();
        String dataTime[];
        // 循环解析原始短期文件
        for (String originalContent : originalContents) {
            // 从有#的数据开始获取 数据示例：#1	帽子山光伏电站	2023-06-22 00:00:00	0.0
            if (originalContent.contains("#")) {
                // 刨除当天的数据
                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]);
                vList.add(map);
            }
        }

        // 文件存放路径 /jiayue/insu/file/bjInit/J00269/
        String newFilePath = bjFilePath + stationCode + File.separatorChar;
        String templateName = File.separatorChar + "vms" + File.separatorChar + "BJZYYJYDQ.vm";
        String tomorrowStr = DateUtil.format(DateUtil.tomorrow(), "yyyyMMdd");
        String newFileName = "modeloutput-" + stationCode + "J001-" + tomorrowStr + "AM_SUBSHORT.RB";
        String fileType = todayStr+ File.separatorChar+"dq";
        // 文件数据开始时间
        String fileDateStr = DateUtil.format(DateUtil.beginOfDay(DateUtil.tomorrow()), "yyyyMMdd_HH:mm:ss");

        pushResult = this.pushFileToSftp(record, vList, newFilePath, newFileName, templateName, station, fileType, todayStr, fileDateStr);
        return pushResult;
    }

    @Override
    public Boolean pushNWPData(Station station) {
        return false;
    }

    /**
     * 通过sftp推送实际功率
     *
     * @param station
     * @return
     */
    public Boolean pushRealPowerData(Station station) {
        boolean pushResult ;
        Record record = new Record(CommonStant.RECORD_TYPE_PUSH_REAL_POWER_TO_SFTP, CompanyConstant.COMPANY_BJZYYJY, station.getStationCode(), null, LocalDateTime.now(), LocalDateTime.now(), null, null);
        // 获取公司信息
        IntegrationCompany integrationCompany = integrationCompanyService.findByCode(CompanyConstant.COMPANY_BJZYYJY);
        // 获取云上实际功率接口url
        String url = integrationCompany.getPullUrl();
        // 获取当天日期
        LocalDateTime today = LocalDateTime.now();
        LocalDateTime yesterday = today.plusDays(-1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

        String yesterdayStr = yesterday.format(formatter);
        String todayStr = today.format(formatter);
        String stationCode = station.getStationCode();
        // 获取Signature
        String sign = getSignature("123456&", stationCode, yesterdayStr, todayStr);
        // post请求参数
        HashMap<String, String> paramMap = new HashMap<>();
        paramMap.put("stationCode", station.getStationCode());
        paramMap.put("startTime", yesterdayStr);
        paramMap.put("endTime", todayStr);
        paramMap.put("sign", sign);
        // 发送post请求并获取结果
        JSONObject responseJson = httpUtils.httpPost(url, paramMap);
        JSONArray dataArr = new JSONArray();
        if (responseJson != null && responseJson.getInt("code") == 0) {
            dataArr = responseJson.getJSONArray("data");
        }
        List<Map<String, Object>> vList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
        long time;
        String realValue;
        // 循环将请求的数据解析
        for (int i = 0; i < dataArr.size(); i++) {
            Map<String, Object> map = new HashMap<>();
            time = dataArr.getJSONObject(i).getLong("dataTimeStamp");
            realValue = dataArr.getJSONObject(i).getStr("realPower");
            map.put("forecastTime", sdf.format(time));
            map.put("realPower", realValue);
            vList.add(map);
        }
        // 文件存放路径 /jiayue/insu/file/bjInit/J00269/
        String newFilePath = bjFilePath + stationCode + File.separatorChar;
        String newFileName = "realpowerdata-" + stationCode + "J001-" + todayStr + "085500.RB";
        String templateName = File.separatorChar + "vms" + File.separatorChar + "BJZYYJYRP.vm";
        // sftp具体路径
        String sftpFilePath = todayStr + File.separatorChar + "real";
        // 文件数据开始时间
        String fileDateStr = DateUtil.format(DateUtil.beginOfDay(DateUtil.yesterday()), "yyyyMMdd_HH:mm:ss");
        pushResult = this.pushFileToSftp(record, vList, newFilePath, newFileName, templateName, station, sftpFilePath, todayStr, fileDateStr);
        return pushResult;
    }

    /**
     * @param record
     * @param vList
     * @param newFilePath
     * @param newFileName
     * @param templateName
     * @param station
     * @param dateAndFileType
     * @param todayStr
     * @return
     */
    public boolean pushFileToSftp(Record record, List<Map<String, Object>> vList, String newFilePath, String newFileName, String templateName, Station station, String dateAndFileType, String todayStr, 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());

        File newFile;
        // 生成新文件
        try {
            newFile = fileUtils.createFileByVelocityTemplate(newFilePath, newFileName, templateName, velocityContext);
        } 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(CompanyConstant.COMPANY_BJZYYJY);
        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());
        // 多级目录创建并上传
        sftpUtil.uploadByFileAndPath(userName, passWord, sftpUrl, sftpPort, newFile, sftpFilePath, newFile.getName());
        // 保存日志
        recordService.save(record);
        return true;
    }

    /**
     * @param keyStr
     * @param paramsStr
     * @return
     */
    public String getSignature(String keyStr, String... paramsStr) {
        byte[] key = keyStr.getBytes();
        HMac mac = new HMac(HmacAlgorithm.HmacMD5, key);
        //拼接签名元数据
        String signOrg = Convert.toStr(paramsStr);
        String macHexSign = mac.digestHex(signOrg);
        return macHexSign;
    }
}
