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

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
import com.jiayue.ipfcst.common.core.util.DateTimeUtil;
import com.jiayue.ipp.common.data.entity.ForecastPowerShortTerm;
import com.jiayue.ipp.common.data.entity.ForecastPowerShortTermHis;
import com.jiayue.ipp.common.data.entity.an.ParsingDqInfo;
import com.jiayue.ipp.common.data.entity.an.ParsingInfo;
import com.jiayue.ipp.common.data.entity.an.ParsingUrl;
import com.jiayue.ipp.common.data.enums.FileTypeEnum;
import com.jiayue.ipp.idp.config.Constant;
import com.jiayue.ipp.idp.dto.FileParsingConfig;
import com.jiayue.ipp.idp.dto.ParsingConstant;
import com.jiayue.ipp.idp.mapper.an.ParsingDqInfoMapper;
import com.jiayue.ipp.idp.service.ForecastPowerShortTermHisService;
import com.jiayue.ipp.idp.service.ForecastPowerShortTermService;
import com.jiayue.ipp.idp.service.an.ParsingDqInfoService;
import com.jiayue.ipp.idp.service.an.ParsingInterface;
import com.jiayue.ipp.idp.util.FieldUtil;
import com.jiayue.ipp.idp.util.FileUtil;
import com.jiayue.ipp.idp.util.PUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 短期解析业务层实现类
 *
 * @author tl
 * @date 2022-05-11 18:07:03
 */
@Service
@Slf4j
@AllArgsConstructor
@Transactional
public class ParsingDqInfoServiceImpl extends ServiceImpl<ParsingDqInfoMapper, ParsingDqInfo> implements ParsingDqInfoService, ParsingInterface {

    private final ForecastPowerShortTermHisService forecastPowerShortTermHisService;

    private final ForecastPowerShortTermService forecastPowerShortTermService;

    @Override
    public boolean save(ParsingInfo parsingInfo) {
        return save((ParsingDqInfo) parsingInfo);
    }

    @Override
    public boolean deleteById(String id) {
        return removeById(id);
    }

    @Override
    public String parsing(File file, ParsingUrl parsingUrl) {
        String parsingStatus = ParsingConstant.FAIL;

        try {
            List<ForecastPowerShortTermHis> forecastPowerShortTermHisList = new ArrayList<>();
            List<ForecastPowerShortTerm> forecastPowerShortTermList = new ArrayList<>();
            List<ParsingDqInfo> parsingDqInfos = baseMapper.selectList(Wrappers.lambdaQuery(ParsingDqInfo.class).like(ParsingInfo::getStationCode, parsingUrl.getStationCode()));
            if (!parsingDqInfos.isEmpty()) {
                ParsingDqInfo parsingDqInfo = parsingDqInfos.get(0);

                    //判断文件名是否符合配置
                    if (file.getName().contains(parsingDqInfo.getFileName())) {

                        List<String> fileContent = FileUtil.getFileContent(file);
                        if (parsingDqInfo.getDataType().equals(FieldUtil.MULTI)) {
                            List<BigDecimal> bigDecimals;
                            if (parsingDqInfo.getFpValue() != null) ;
                            bigDecimals = parsingFpValue(parsingDqInfo.getFpValue(), fileContent);

                            if (bigDecimals.size() > 0) {

//                                LocalDate genDate = parsingGenDate(parsingDqInfo.getGenDate(), fileContent);
                                Long forecastTime = parsingForecastTime(parsingDqInfo.getForecastTime(), fileContent);
                                long secondDayTime = com.jiayue.ipp.idp.util.DateMomentUtil.getDayStartTime(System.currentTimeMillis())+1000*60*60*24;
                                if (forecastTime==secondDayTime){
                                    if (forecastTime != 0l) {
                                        Long systemTime = System.currentTimeMillis();
                                        for (BigDecimal bigDecimal : bigDecimals) {
                                            Date forecastDate = new Date(forecastTime);
                                            ForecastPowerShortTermHis forecastPowerShortTermHis = new ForecastPowerShortTermHis();
                                            forecastPowerShortTermHis.setGenDate(new Date());
                                            forecastPowerShortTermHis.setStationCode(parsingUrl.getStationCode());
                                            forecastPowerShortTermHis.setAbleValue(bigDecimal);
                                            forecastPowerShortTermHis.setForecastTime(forecastDate);
                                            forecastPowerShortTermHis.setForecastHowLongAgo(DateMomentUtil.getDaysBetweenTwoDate(systemTime,forecastTime));
                                            forecastPowerShortTermHis.setForecastManufactor(parsingUrl.getForecastManufactor());
                                            forecastPowerShortTermHisList.add(forecastPowerShortTermHis);

                                            ForecastPowerShortTerm forecastPowerShortTerm = new ForecastPowerShortTerm();
                                            forecastPowerShortTerm.setForecastTime(forecastDate);
                                            forecastPowerShortTerm.setStationCode(parsingUrl.getStationCode());
                                            forecastPowerShortTerm.setFpValue(bigDecimal);
                                            forecastPowerShortTerm.setGenDate(new Date());
                                            forecastPowerShortTerm.setForecastManufactor(parsingUrl.getForecastManufactor());
                                            forecastPowerShortTermList.add(forecastPowerShortTerm);

                                            forecastTime += Constant.INTERVALTIME;
                                        }

                                        // 保存短期实时
                                        Date startTime = forecastPowerShortTermList.get(0).getForecastTime();
                                        Date endTime = forecastPowerShortTermList.get(forecastPowerShortTermList.size() - 1).getForecastTime();
                                        LambdaQueryWrapper<ForecastPowerShortTerm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                                        lambdaQueryWrapper.eq(ForecastPowerShortTerm::getStationCode, parsingUrl.getStationCode());
                                        lambdaQueryWrapper.eq(ForecastPowerShortTerm::getForecastManufactor, parsingUrl.getForecastManufactor());
                                        lambdaQueryWrapper.between(ForecastPowerShortTerm::getForecastTime, startTime, endTime);
                                        forecastPowerShortTermService.remove(lambdaQueryWrapper);
                                        forecastPowerShortTermService.saveBatch(forecastPowerShortTermList);

                                        // 保存短期历史
//                                        LocalDate today = LocalDate.now();
                                        LambdaQueryWrapper<ForecastPowerShortTermHis> forecastPowerShortTermHisLambdaQueryWrapper = new LambdaQueryWrapper<>();
                                        forecastPowerShortTermHisLambdaQueryWrapper.eq(ForecastPowerShortTermHis::getStationCode, parsingUrl.getStationCode());
                                        forecastPowerShortTermHisLambdaQueryWrapper.eq(ForecastPowerShortTermHis::getForecastManufactor, parsingUrl.getForecastManufactor());
                                        forecastPowerShortTermHisLambdaQueryWrapper.eq(ForecastPowerShortTermHis::getGenDate, DateUtil.format(new Date(),"yyyy-MM-dd"));
                                        forecastPowerShortTermHisService.remove(forecastPowerShortTermHisLambdaQueryWrapper);
                                        forecastPowerShortTermHisService.saveBatch(forecastPowerShortTermHisList);


                                        log.info("解析DQ文件：{} 成功！ O(∩_∩)O", file.getName());
                                        parsingStatus = FileTypeEnum.DQ.name();
                                    } else {
                                        parsingStatus += "解析DQ文件时间错误";
                                        log.error("解析DQ文件时间错误");
                                    }
                                }
                                else{
                                    parsingStatus += "dq文件里日期不对";
                                    log.info("dq文件里日期不对");
                                }

                            } else {
                                parsingStatus += "解析短期文件无数据";
                                log.error("解析短期文件无数据");
                            }
                        } else {
                            parsingStatus += "dq暂无单行解析方式";
                            log.info("dq暂无单行解析方式");
                        }
                    }
//                }
//                else{
//                    parsingStatus += "dq文件里日期不对";
//                    log.info("dq文件里日期不对");
//                }
            }
        } catch (Exception e) {
            parsingStatus += "解析短期数据失败";
            log.error("解析短期数据失败！ /(ㄒoㄒ)/~~", e);
        } finally {
            return parsingStatus;
        }

    }


    //目前所知该类型在文件中只有s一种形式==》暂不支持m
    protected LocalDate parsingGenDate(String sign, List<String> fileContent) {
        LocalDate genDate = LocalDate.now();

        try {
            if (!sign.equals("")) {
                FileParsingConfig config = FieldUtil.getConfig(sign);

                String s = fileContent.get(PUtil.noParseInt(config.getLineNumber()));
                int signIndex = s.indexOf(config.getDataSign());
                String result;
                if (signIndex > 0) {
                    int startLength = config.getDataSign().length() + signIndex + 1;
                    int length = config.getFormat().length();
                    if (String.valueOf(s.charAt(startLength + 1)).equals("'")) {
                        startLength += 1;
                    }
                    result = s.substring(startLength, startLength + length);

                    DateTimeFormatter fmt = DateTimeFormatter.ofPattern(config.getFormat());
                    genDate = LocalDate.parse(result, fmt);
                    log.info("解析短期【数据生成日期】成功==》日期为：{}", result);
                } else {
                    log.error("解析短期【数据生成日期】时公式标识不存在所在行");
                }
            }
        } catch (RuntimeException e) {
            log.error("解析短期【数据生成日期】失败");
            e.printStackTrace();
        } finally {
            return genDate;
        }
    }

    protected Long parsingForecastTime(String sign, List<String> fileContent) {
        Long forecastTime = 0l;
        try {
            FileParsingConfig config = FieldUtil.getConfig(sign);
            String s = fileContent.get(PUtil.noParseInt(config.getLineNumber()));
            int signIndex = s.indexOf(config.getDataSign());
            String result;
            if (signIndex > 0) {
                int startLength = config.getDataSign().length() + signIndex + 1;
                int length = config.getFormat().length();
                if (String.valueOf(s.charAt(startLength + 1)).equals("'")) {
                    startLength += 1;
                }
                result = s.substring(startLength, startLength + length);

                SimpleDateFormat simpleDateFormat = new SimpleDateFormat(config.getFormat());

                forecastTime = simpleDateFormat.parse(result).getTime();

                log.info("解析短期【预测时间】成功==》开始时间为：{}", result);
            } else {
                log.error("解析短期【预测时间】时公式标识不存在所在行");
            }
        } catch (RuntimeException e) {
            log.error("解析短期【预测时间】失败");
            e.printStackTrace();
        } finally {
            return forecastTime;
        }

    }


    /*
     * 解析配置格式规则：
     *   s=>>1=>>entity=
     *   s：单行标识
     *   1：取值在1行
     *   entity=：键标记标记
     *
     *   m=>>4-20=>>3
     *   m：多行标识
     *   4-20：取值在4-20行
     *   3：第三列
     * */
    protected List<BigDecimal> parsingFpValue(String sign, List<String> fileContent) {
        List<BigDecimal> fpValues = new ArrayList<>();
        try {
            FileParsingConfig config = FieldUtil.getConfig(sign);


            String[] lineNumber = config.getLineNumber().split("-");
            int startLine = PUtil.noParseInt(lineNumber[0]);
            int endLine = PUtil.noParseInt(lineNumber[1]);

            for (int i = startLine; i <= endLine; i++) {
                String[] strings = PUtil.splitLineWithSpace(fileContent.get(i));
                String result = strings[PUtil.noParseInt(config.getRowNumber())];

                fpValues.add(new BigDecimal(result));
            }

            log.info("解析短期【预测数据】成功！！！==》记录数：{}", fpValues.size());
        } catch (RuntimeException e) {
            log.error("解析短期【预测数据】失败");
            e.printStackTrace();
        } finally {
            return fpValues;
        }
    }

}
