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.ipp.common.data.entity.ForecastPowerUltraShortTerm;
import com.jiayue.ipp.common.data.entity.ForecastPowerUltraShortTermHis;
import com.jiayue.ipp.common.data.entity.an.ParsingCdqInfo;
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.ParsingCdqInfoMapper;
import com.jiayue.ipp.idp.service.ForecastPowerUltraShortTermHisService;
import com.jiayue.ipp.idp.service.ForecastPowerUltraShortTermService;
import com.jiayue.ipp.idp.service.an.ParsingCdqInfoService;
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
@AllArgsConstructor
@Slf4j
@Transactional
public class ParsingCdqInfoServiceImpl extends ServiceImpl<ParsingCdqInfoMapper, ParsingCdqInfo> implements ParsingCdqInfoService, ParsingInterface {

//    private final Long intervalTime = 900000l;

    private final ForecastPowerUltraShortTermHisService forecastPowerUltraShortTermHisService;

    private final ForecastPowerUltraShortTermService forecastPowerUltraShortTermService;

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

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

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

        try {
            // 查询ParsingCdqInfo列表
            List<ParsingCdqInfo> parsingCdqInfos = baseMapper.selectList(Wrappers.lambdaQuery(ParsingCdqInfo.class).like(ParsingInfo::getStationCode, parsingUrl.getStationCode()));
            if (!parsingCdqInfos.isEmpty()) {
                ParsingCdqInfo parsingCdqInfo = parsingCdqInfos.get(0);

                if (file.getName().contains(parsingCdqInfo.getFileName())) {

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

                        if (bigDecimals.size() > 0) {
                            Long forecastTime = parsingForecastTime(parsingCdqInfo.getForecastTime(), fileContent);
                            if (forecastTime != 0L) {
                                // 所属产生时刻用第一个点位减去15分钟
                                long genDate = forecastTime-1000*60*15L;

                                int ago = 1;
                                List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisList = new ArrayList<>();
                                List<ForecastPowerUltraShortTerm> forecastPowerUltraShortTermList = new ArrayList<>();

                                for (BigDecimal bigDecimal : bigDecimals) {
                                    // 构造ForecastPowerUltraShortTermHis对象
                                    ForecastPowerUltraShortTermHis forecastPowerUltraShortTermHis = new ForecastPowerUltraShortTermHis();
                                    forecastPowerUltraShortTermHis.setGenDate(new Date(genDate));
                                    forecastPowerUltraShortTermHis.setStationCode(parsingUrl.getStationCode());
                                    forecastPowerUltraShortTermHis.setAbleValue(bigDecimal);
                                    Date localDateTime = new Date(forecastTime);
                                    forecastPowerUltraShortTermHis.setForecastTime(localDateTime);
                                    forecastPowerUltraShortTermHis.setForecastHowLongAgo(ago);
                                    forecastPowerUltraShortTermHis.setForecastManufactor(parsingUrl.getForecastManufactor());
                                    forecastTime += Constant.INTERVALTIME;

                                    // 构造ForecastPowerUltraShortTerm对象
                                    ForecastPowerUltraShortTerm forecastPowerUltraShortTerm = new ForecastPowerUltraShortTerm();
                                    forecastPowerUltraShortTerm.setForecastTime(localDateTime);
                                    forecastPowerUltraShortTerm.setStationCode(parsingUrl.getStationCode());
                                    forecastPowerUltraShortTerm.setFpValue(bigDecimal);
                                    forecastPowerUltraShortTerm.setGenDate(new Date(genDate));
                                    forecastPowerUltraShortTerm.setForecastManufactor(parsingUrl.getForecastManufactor());
                                    forecastPowerUltraShortTermList.add(forecastPowerUltraShortTerm);

                                    forecastPowerUltraShortTermHisList.add(forecastPowerUltraShortTermHis);
                                    ago++;
                                }

                                parsingStatus = FileTypeEnum.CDQ.name();
                                log.info("解析CDQ文件：{} 成功！ O(∩_∩)O", file.getName());

                                // 删除之前的ForecastPowerUltraShortTerm记录
                                LambdaQueryWrapper<ForecastPowerUltraShortTerm> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                                lambdaQueryWrapper.eq(ForecastPowerUltraShortTerm::getStationCode, parsingUrl.getStationCode());
                                lambdaQueryWrapper.eq(ForecastPowerUltraShortTerm::getForecastManufactor, parsingUrl.getForecastManufactor());
                                lambdaQueryWrapper.between(ForecastPowerUltraShortTerm::getForecastTime, forecastPowerUltraShortTermList.get(0).getForecastTime(), forecastPowerUltraShortTermList.get(forecastPowerUltraShortTermList.size() - 1).getForecastTime());
                                forecastPowerUltraShortTermService.remove(lambdaQueryWrapper);
                                // 批量保存新的ForecastPowerUltraShortTerm记录
                                forecastPowerUltraShortTermService.saveBatch(forecastPowerUltraShortTermList);

                                // 删除当天的ForecastPowerUltraShortTermHis记录
                                LambdaQueryWrapper<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisLambdaQueryWrapper = new LambdaQueryWrapper<>();
                                forecastPowerUltraShortTermHisLambdaQueryWrapper.eq(ForecastPowerUltraShortTermHis::getGenDate, new Date(genDate));
                                forecastPowerUltraShortTermHisLambdaQueryWrapper.eq(ForecastPowerUltraShortTermHis::getStationCode, parsingUrl.getStationCode());
                                forecastPowerUltraShortTermHisLambdaQueryWrapper.eq(ForecastPowerUltraShortTermHis::getForecastManufactor, parsingUrl.getForecastManufactor());
                                forecastPowerUltraShortTermHisService.remove(forecastPowerUltraShortTermHisLambdaQueryWrapper);
                                // 批量保存新的ForecastPowerUltraShortTermHis记录
                                forecastPowerUltraShortTermHisService.saveBatch(forecastPowerUltraShortTermHisList);
                            } else {
                                parsingStatus += "解析CDQ文件时间错误";
                                log.error("解析CDQ文件时间错误");
                            }
                        }
                        else {
                            parsingStatus += "解析超短期文件无数据";
                            log.error("解析超短期文件无数据");
                        }

                    }else {
                        parsingStatus += "cdq暂无单行解析方式";
                        log.info("cdq暂无单行解析方式");
                    }
                }
            }
        } catch (Exception e) {
            parsingStatus += "解析超短期数据失败! /(ㄒoㄒ)/~~";
            log.error("解析超短期数据失败", e);
        } finally {
            return parsingStatus;
        }

    }


    //目前所知该类型在文件中只有s一种形式，暂不支持m
    protected Date parsingGenDate(String sign, List<String> fileContent) {
        Date genDate = new Date();
        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 = DateUtil.parse(result, fmt.toString());
                    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;
        }
    }


}
