package com.cpp.web.job;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.Sftp;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cpp.system.service.ISysConfigService;

import com.cpp.web.domain.datafactory.SftpChannel;
import com.cpp.web.domain.enums.RegulationStatusEnum;
import com.cpp.web.domain.regulation.TempShortRegulation;
import com.cpp.web.domain.regulation.TempShortRegulationDetail;
import com.cpp.web.domain.station.*;
import com.cpp.web.service.datafactory.SftpChannelService;
import com.cpp.web.service.regulation.TempShortRegulationDetailService;
import com.cpp.web.service.regulation.TempShortRegulationService;
import com.cpp.web.service.station.ElectricFieldService;
import com.cpp.web.service.station.ForecastPowerShortTermSendService;
import com.cpp.web.service.station.ForecastPowerShortTermStationService;
import com.cpp.web.utils.CppFileUtil;
import com.cpp.web.utils.DateTimeUtil;
import com.cpp.web.utils.SftpUtil;
import com.cpp.web.utils.sftp.SftpTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.*;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 定时任务管理类
 */
@Component
@Order(9)
@Slf4j
public class RgulationSendJob {
    @Autowired
    ISysConfigService iSysConfigService;
    @Autowired
    ForecastPowerShortTermStationService forecastPowerShortTermStationService;
    @Autowired
    TempShortRegulationService tempShortRegulationService;
    @Autowired
    TempShortRegulationDetailService tempShortRegulationDetailService;
    @Autowired
    VelocityEngine velocityEngine;
    @Autowired
    ElectricFieldService electricFieldService;
    @Autowired
    SftpChannelService sftpChannelService;
    @Autowired
    ForecastPowerShortTermSendService forecastPowerShortTermSendService;

    /**
     * 生成调控下发文件定时任务
     */
    @Scheduled(fixedDelay = 60000L)
    public void createRegulationFile() {
        try {
            // 判断调控截止时间
            String dqEndTime = iSysConfigService.selectConfigByKey("dqEndTime");
            if (!StrUtil.isBlankIfStr(dqEndTime)) {
                // 生成截止时间
                Date dqEndDate = DateUtils.parseDate(DateFormatUtils.format(new Date(), "yyyy-MM-dd " + dqEndTime), "yyyy-MM-dd HH:mm");
                if (new Date().after(dqEndDate)) {
                    Date tkDate = DateTimeUtil.getDayStartTime(System.currentTimeMillis());
                    QueryWrapper<TempShortRegulation> tempShortRegulationQueryWrapper = new QueryWrapper<>();
                    tempShortRegulationQueryWrapper.eq("tk_date", tkDate)
                            .and(wrapper -> wrapper.eq("regulation_status_enum", RegulationStatusEnum.E1.name()).or().eq("regulation_status_enum", RegulationStatusEnum.E3.name()));
                    // 查找调控主表当日未下发的记录
                    List<TempShortRegulation> tempShortRegulationList = tempShortRegulationService.list(tempShortRegulationQueryWrapper);
                    // 存在未下发的记录就执行下发任务
                    if (tempShortRegulationList.isEmpty()) {
                        // 超过截止时间就执行调控下发，获取当天将要下发的调控记录
                        QueryWrapper<TempShortRegulationDetail> tempShortRegulationDetailQueryWrapper = new QueryWrapper<>();
                        // 当日调控
                        tempShortRegulationDetailQueryWrapper.eq("tk_date", tkDate);
                        List<TempShortRegulationDetail> tempShortRegulationDetailList = tempShortRegulationDetailService.list(tempShortRegulationDetailQueryWrapper);
                        if (!tempShortRegulationDetailList.isEmpty()) {
                            // 按场站编号分组
                            Map<String, List<TempShortRegulationDetail>> tempShortRegulationDetailGroup = tempShortRegulationDetailList.stream().collect(Collectors.groupingBy(s -> s.getStationCode()));
                            // 统计出需要调控的场站编号
                            List<String> stationCodeList = new ArrayList<>(tempShortRegulationDetailGroup.keySet());
                            // 获取场站原始值
                            QueryWrapper<ForecastPowerShortTermStation> forecastPowerShortTermStationQueryWrapper = new QueryWrapper<>();
                            forecastPowerShortTermStationQueryWrapper.eq("gen_date", DateTimeUtil.getDayStartTime(System.currentTimeMillis()));
                            forecastPowerShortTermStationQueryWrapper.and(wrapper ->
                                    stationCodeList.stream()
                                            .map(code -> wrapper.eq("station_code", code).or())
                                            .reduce((a, b) -> b)
                                            .get()
                            );
                            List<ForecastPowerShortTermStation> forecastPowerShortTermStationList = forecastPowerShortTermStationService.list(forecastPowerShortTermStationQueryWrapper);
                            // 获取所有场站信息
                            List<ElectricField> electricFieldList = electricFieldService.list();
                            // 获取所有sftp通道信息
                            List<SftpChannel> sftpChannelList = sftpChannelService.list();
                            // 循环场站生成调控文件
                            for (String stationCode : stationCodeList) {
                                String vmFileName = "";
                                // 定义下发状态
                                String isSend = RegulationStatusEnum.E3.name();
                                List<ForecastPowerShortTermStation> tempStationList = new ArrayList<>();
                                try {
                                    List<TempShortRegulationDetail> shortRegulationDetailList = tempShortRegulationDetailGroup.get(stationCode);
                                    Map<Long, BigDecimal> tkMap = new HashMap<>();
                                    for (TempShortRegulationDetail tempShortRegulationDetail : shortRegulationDetailList) {
                                        tkMap.put(tempShortRegulationDetail.getTime().getTime(), tempShortRegulationDetail.getTkValue());
                                    }

                                    // 获取该场站的原始值
                                    tempStationList = forecastPowerShortTermStationList.stream().filter(s -> s.getStationCode().equals(stationCode)).collect(Collectors.toList());
                                    tempStationList.sort(Comparator.comparing(ForecastPowerShortTermStation::getTime));
                                    for (ForecastPowerShortTermStation forecastPowerShortTermStation : tempStationList) {
                                        // 遍历原始值每个点位，如果该点位存在调控值，则替换原始值。
                                        if (tkMap.get(forecastPowerShortTermStation.getTime().getTime()) != null) {
                                            forecastPowerShortTermStation.setFpValue(tkMap.get(forecastPowerShortTermStation.getTime().getTime()));
                                        }
                                    }
                                    // 获取该场站信息
                                    ElectricField electricField = electricFieldList.stream().filter(s -> s.getStationCode().equals(stationCode)).findFirst().get();

                                    // 生成调控文件
                                    VelocityContext velocityContext = new VelocityContext();
                                    velocityContext.put("vList", tempStationList);
                                    velocityContext.put("stationSign", electricField.getStationSign());
                                    velocityContext.put("capacity", electricField.getCapacity());
                                    velocityContext.put("firstTime", DateFormatUtils.format(tempStationList.get(0).getTime(), "yyyy-MM-dd_HH:mm"));
                                    // 系统当前日期
                                    velocityContext.put("currentTime", DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd_HH:mm:ss"));
                                    StringWriter writer = new StringWriter();
                                    org.apache.velocity.Template template = this.velocityEngine.getTemplate(CppFileUtil.getResourceBasePath() + "/templates/send_dq.vm");
                                    template.merge(velocityContext, writer);
                                    vmFileName = electricField.getStationSign() + "_" + DateFormatUtils.format(tempStationList.get(0).getTime(), "yyyyMMdd_HHmm") + "_DQ.WPD";
                                    // 获取临时存储文件路径
                                    String tempCreateFilePath = CppFileUtil.getTempCreateFilePath();
                                    File dirFile = FileUtil.mkdir(tempCreateFilePath);
                                    if (dirFile == null) {
                                        throw new RuntimeException("创建文件夹tempCreateFile失败");
                                    }

                                    createSendDqFile(writer, new File(tempCreateFilePath + File.separator + vmFileName));
                                    SftpChannel sftpChannel = sftpChannelList.stream().filter(s -> s.getId().longValue() == electricField.getSftpChanelId().longValue()).findFirst().get();
                                    SftpTool sftpTool = SftpUtil.createSftp(sftpChannel);
                                    Sftp sftp = sftpTool.getSftp();
                                    try (InputStream inputStream = new FileInputStream(tempCreateFilePath + File.separator + vmFileName)) {
                                        sftp.getClient().put(inputStream, electricField.getSftpSendUrl() + "/" + vmFileName);
                                    } finally {
                                        sftpTool.close();
                                    }
                                    isSend = RegulationStatusEnum.E1.name();
                                } catch (Exception e) {
                                    log.error(stationCode + "生成调控下发文件定时任务失败", e);
                                } finally {
                                    if (!tempStationList.isEmpty()) {
                                        // 插入下发调控表
                                        List<ForecastPowerShortTermSend> forecastPowerShortTermSendList = new ArrayList<>();
                                        // 将调控后的数据拷贝到下发集合中
                                        for (ForecastPowerShortTermStation forecastPowerShortTermStation : tempStationList) {
                                            ForecastPowerShortTermSend newSend = new ForecastPowerShortTermSend();
                                            newSend.setStationCode(forecastPowerShortTermStation.getStationCode());
                                            newSend.setFpValue(forecastPowerShortTermStation.getFpValue());
                                            newSend.setTime(forecastPowerShortTermStation.getTime());
                                            newSend.setForecastHowLongAgo(forecastPowerShortTermStation.getForecastHowLongAgo());
                                            newSend.setCapacity(forecastPowerShortTermStation.getCapacity());
                                            newSend.setOpenCapacity(forecastPowerShortTermStation.getOpenCapacity());
                                            forecastPowerShortTermSendList.add(newSend);
                                        }
                                        forecastPowerShortTermSendService.saveBatch(forecastPowerShortTermSendList);
                                    }
                                    // 更新调控主表下发状态
                                    UpdateWrapper<TempShortRegulation> regulationUpdateWrapper = new UpdateWrapper<>();
                                    regulationUpdateWrapper.eq("station_code", stationCode).eq("tk_date", tkDate).set("regulation_status_enum", isSend);
                                    tempShortRegulationService.update(regulationUpdateWrapper);
                                    // 删除本地文件
                                    if (!StrUtil.isBlankIfStr(vmFileName)) {
                                        FileUtil.del(CppFileUtil.getTempCreateFilePath() + File.separator + vmFileName);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("生成调控下发文件定时任务失败", e);
        }
    }

    /**
     * 生成上报文件
     *
     * @param writer
     * @param file
     */
    protected void createSendDqFile(StringWriter writer, File file) {
        FileOutputStream os = null;
        try {
            os = new FileOutputStream(file);
            // 采用UTF-8字符集
            os.write(writer.toString().getBytes("UTF-8"));
            os.flush();

        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    log.error("文件生成关闭流失败", e);
                }
            }
        }
    }
}
