package com.jiayue.ipp.idp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
import com.jiayue.ipp.common.data.entity.DqIntervene;
import com.jiayue.ipp.common.data.entity.ForecastPowerShortTerm;
import com.jiayue.ipp.idp.dto.ForecastData;
import com.jiayue.ipp.idp.service.DqInterveneService;
import com.jiayue.ipp.idp.service.ForecastPowerShortTermService;
import com.jiayue.ipp.idp.service.SysParameterService;
import com.jiayue.ipp.idp.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * idp_inverter_info
 *
 * @author whc
 * @date 2022-03-18 15:49:11
 */
@Service
@Slf4j
public class SendJyDqDataServiceImpl{
    @Autowired
    SysParameterService sysParameterService;
    @Autowired
    ForecastPowerShortTermService forecastPowerShortTermService;
    @Autowired
    DqInterveneService dqInterveneService;
    @Autowired
    VelocityEngine velocityEngine;

    public void sendDqDownloadFile(String stationCode,String ftpAccount){
        try{
            // 获取人工干预下发未来短期数据天数
            int dqForecastDays = Integer.parseInt(sysParameterService.getSysParameterAndAll("SEND_DQ_DAYS", "10"));

            String distPath = "/home"+ File.separator+ftpAccount+File.separator+"download";
            File dirFile = new File(distPath);
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }
            // 获取短期实时数据，开始时间
            Long startTime = DateMomentUtil.getDayStartTime(DateUtils.addDays(new Date(), 1).getTime());
            // 结束时间（开始加24小时再减去1秒）
            Long endTime = DateMomentUtil.getDayLastTime(DateUtils.addDays(new Date(), dqForecastDays).getTime());
            // 查询短期预测功率
            LambdaQueryWrapper<ForecastPowerShortTerm> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ForecastPowerShortTerm::getForecastManufactor, "SYJY");
            queryWrapper.eq(ForecastPowerShortTerm::getStationCode, stationCode);
            queryWrapper.between(ForecastPowerShortTerm::getForecastTime, new Date(startTime), new Date(endTime));

            List<ForecastPowerShortTerm> forecastPowerShortTermList = this.forecastPowerShortTermService.list(queryWrapper);
            Map<Long, ForecastPowerShortTerm> forecastPowerShortMap = forecastPowerShortTermList.stream()
                    .collect(Collectors.toMap(
                            myObject -> myObject.getForecastTime().getTime(), // keyMapper，将Date转换为long
                            myObject -> myObject, // valueMapper，保持原对象
                            (existing, replacement) -> existing // mergeFunction，处理重复key的情况，这里简单地保留现有的value
                    ));

            // 人工干预
            QueryWrapper<DqIntervene> dqInterveneQueryWrapper = new QueryWrapper<>();
            dqInterveneQueryWrapper.between("forecast_time", new Date(startTime), new Date(endTime));
            dqInterveneQueryWrapper.eq("station_code",stationCode);
            List<DqIntervene> dqInterveneList = dqInterveneService.list(dqInterveneQueryWrapper);
            Map<Long, DqIntervene> dqInterveneMap = dqInterveneList.stream()
                    .collect(Collectors.toMap(
                            myObject -> myObject.getForecastTime().getTime(), // keyMapper，将Date转换为long
                            myObject -> myObject, // valueMapper，保持原对象
                            (existing, replacement) -> existing // mergeFunction，处理重复key的情况，这里简单地保留现有的value
                    ));

            List<ForecastData> vList = new ArrayList<>();

            for (Long tempTime = startTime.longValue(); tempTime <= endTime.longValue(); tempTime = tempTime + 15 * 60 * 1000L) {
                ForecastData forecastData = new ForecastData();
                forecastData.setTime(DateFormatUtils.format(tempTime, "yyyy-MM-dd HH:mm:ss"));
                if (dqInterveneMap.get(tempTime)!=null){
                    forecastData.setPower(dqInterveneMap.get(tempTime).getActivePower().toString());
                }
                else if (forecastPowerShortMap.get(tempTime)!=null){
                    forecastData.setPower(forecastPowerShortMap.get(tempTime).getFpValue().toString());
                }
                else{
                    forecastData.setPower("");
                }
                vList.add(forecastData);
            }

            VelocityContext velocityContext = new VelocityContext();
            velocityContext.put("vList", vList);
            // 系统当前日期
            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(FileUtil.getResourceBasePath() + "/templates/send_dq.vm");
            template.merge(velocityContext, writer);
            String dateDir = DateFormatUtils.format(new Date(startTime), "yyyyMMdd");
            String vmFileName = "download_"+ftpAccount+"_dq_"+dateDir+".WPD";
            createSendDqFile(writer,new File(distPath + File.separator+vmFileName));
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 生成上报文件
     *
     * @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);
                }
            }
        }
    }
}
