package com.simuwang.manage.service.impl;

import cn.hutool.core.date.DateUtil;
import com.simuwang.base.common.enums.DeletionType;
import com.simuwang.base.common.enums.DistributeType;
import com.simuwang.base.common.enums.Frequency;
import com.simuwang.base.common.support.MybatisPage;
import com.simuwang.base.common.util.DateUtils;
import com.simuwang.base.common.util.StringUtil;
import com.simuwang.base.mapper.*;
import com.simuwang.base.pojo.dos.*;
import com.simuwang.base.pojo.dto.DeletionDownParam;
import com.simuwang.base.pojo.dto.ExcelDeletionInfoDTO;
import com.simuwang.base.pojo.dto.query.DeletionPageQuery;
import com.simuwang.base.pojo.dto.query.FundDeletionPageQuery;
import com.simuwang.base.pojo.vo.*;
import com.simuwang.manage.service.DeletionService;
import com.simuwang.shiro.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * FileName: DeletionServiceImpl
 * Author:   chenjianhua
 * Date:     2024/9/17 18:54
 * Description: ${DESCRIPTION}
 */
@Service
public class DeletionServiceImpl implements DeletionService {

    @Autowired
    private DeletionInfoMapper deletionInfoMapper;

    @Autowired
    private FundInfoMapper fundInfoMapper;

    @Autowired
    private AssetMapper assetMapper;

    @Autowired
    private FundReportFrequencyMapper fundReportFrequencyMapper;

    @Autowired
    private TradeDateMapper tradeDateMapper;

    @Autowired
    private DistributionMapper distributionMapper;

    @Autowired
    private NavMapper navMapper;
    @Override
    public MybatisPage<DeletionInfoVO> searchDeletionList(DeletionPageQuery deletionPageQuery) {
        List<DeletionInfoDO> deletionInfoDOList = deletionInfoMapper.searchDeletionList(deletionPageQuery);
        long total = deletionInfoMapper.countDeletion(deletionPageQuery);
        List<DeletionInfoVO> dataList = deletionInfoDOList.stream().map(DeletionInfoDO::toVO).collect(Collectors.toList());
        for(DeletionInfoVO vo : dataList){
            String fundId = vo.getFundId();
            String lastDeletionDate = deletionInfoMapper.getLastDeletionDateByFundId(fundId,vo.getDeletionType());
            vo.setLastDeletionDate(lastDeletionDate);
        }
        return MybatisPage.of(total,dataList);
    }

    @Override
    public MybatisPage<FundDeletionInfoVO> searchFundDeletionList(FundDeletionPageQuery fundDeletionPageQuery) {
        List<FundDeletionInfoDO> deletionInfoDOList = deletionInfoMapper.searchFundDeletionList(fundDeletionPageQuery);
        long total = deletionInfoMapper.countFundDeletionList(fundDeletionPageQuery);
        List<FundDeletionInfoVO> dataList = deletionInfoDOList.stream().map(FundDeletionInfoDO::toVO).collect(Collectors.toList());
        for(FundDeletionInfoVO infoVO : dataList){
            infoVO.setFundName(fundInfoMapper.getFundNameByFundId(infoVO.getFundId()));
        }
        return MybatisPage.of(total,dataList);
    }

    @Override
    public void saveFundDeletionList(List<FundDeletionInfoVO> fundDeletionInfoVOList) {
        List<FundDeletionInfoDO> fundDeletionInfoDOList = new ArrayList<>();
        for(FundDeletionInfoVO vo : fundDeletionInfoVOList){
            FundDeletionInfoDO fundDeletionInfoDO = new FundDeletionInfoDO();
            fundDeletionInfoDO.setId(vo.getId());
            fundDeletionInfoDO.setDeletionType(vo.getDeletionType());
            fundDeletionInfoDO.setFundId(vo.getFundId());
            fundDeletionInfoDO.setDeletionDate(vo.getDeletionDate());
            fundDeletionInfoDO.setRemark(vo.getRemark());
            fundDeletionInfoDO.setIsvalid(1);
            fundDeletionInfoDO.setUpdateTime(DateUtils.getNowDate());
            fundDeletionInfoDO.setUpdaterId(UserUtils.getLoginUser().getUserId());
            fundDeletionInfoDOList.add(fundDeletionInfoDO);
        }
        deletionInfoMapper.batchUpdate(fundDeletionInfoDOList);
    }

    @Override
    public void saveBatchDeletionRemark(FundDeletionRemarkVO fundDeletionRemarkVO) {
        String remark = fundDeletionRemarkVO.getRemark();
        Integer userId = UserUtils.getLoginUser().getUserId();
        for(FundDeletionTypeVO remarkVO : fundDeletionRemarkVO.getFundDeletionTypeList()){
            deletionInfoMapper.updateRemark(remarkVO.getFundId(),remarkVO.getDeletionType(),remarkVO.getDeletionDate(),remark,userId);
        }
    }

    @Override
    public List<ExcelDeletionInfoDTO> selectFundDeletionInfoVOList(FundDeletionListVO fundDeletionListVO) {
        List<ExcelDeletionInfoDTO> result = new ArrayList<>();
        List<DeletionDownParam> deletionDownParamList = fundDeletionListVO.getDeletionDownParamList();
        for(DeletionDownParam deletionDownParam : deletionDownParamList){
            List<FundDeletionInfoDO> deletionInfoDOList = deletionInfoMapper.selectFundDeletionInfoVOList(deletionDownParam.getFundId(),deletionDownParam.getDeletionType());
            for(FundDeletionInfoDO infoDO : deletionInfoDOList){
                ExcelDeletionInfoDTO dto = new ExcelDeletionInfoDTO();
                dto.setFundName(fundInfoMapper.getFundNameByFundId(infoDO.getFundId()));
                dto.setCompanyName(fundInfoMapper.getCompanyNameByFundId(infoDO.getFundId()));
                dto.setDeletionType(DeletionType.getDeletionTypeByCode(infoDO.getDeletionType()).getInfo());
                dto.setDeletionDate(infoDO.getDeletionDate());
                dto.setRemark(infoDO.getRemark());
                dto.setFundId(infoDO.getFundId());
                result.add(dto);
            }
        }
        return result;
    }

    @Override
    public void computeDeletion(DeletionDownParam deletionDownParam) {
        String fundId = deletionDownParam.getFundId();
        String liquidateDate = fundInfoMapper.getLiquidateDateByFundId(fundId);
        if(StringUtil.isNotEmpty(liquidateDate)){
            return;
        }
        String inceptionDate = fundInfoMapper.getInceptionDateByFundId(fundId);
        if(StringUtil.isEmpty(inceptionDate)){
            return;
        }
        String today = DateUtils.getAroundToday(0);
        //获取基金对应的净值报送频率
        FundReportFrequencyDO fundReportFrequencyDO = fundReportFrequencyMapper.getFrequencyByFundId(fundId);
        if(StringUtil.isNull(fundReportFrequencyDO)){
            return;
        }
        List<NavDO> navDOList = navMapper.selectNavByFundId(fundId);
        List<AssetDO> assetDOList = assetMapper.selectAssetByFundId(fundId);
        //查询成立日到今天为止的交易日集合
        List<TradeDateDO> tradeDateDOList = tradeDateMapper.selectTradeDate(inceptionDate,today);
        if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.NAV_DELETION.getCode())){
            navDeletion(fundId,navDOList,tradeDateDOList,fundReportFrequencyDO);
        }else if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.ASSET_DELETION.getCode())){
            assetDeletion(fundId,assetDOList,tradeDateDOList,fundReportFrequencyDO);
        }else if(deletionDownParam.getDeletionType() != null && deletionDownParam.getDeletionType().equals(DeletionType.DISTRIBUTION_DELETION.getCode())){
            distributionDeletion(fundId,navDOList);
        }else{
            navDeletion(fundId,navDOList,tradeDateDOList,fundReportFrequencyDO);
            assetDeletion(fundId,assetDOList,tradeDateDOList,fundReportFrequencyDO);
            distributionDeletion(fundId,navDOList);
        }

    }

    private void distributionDeletion(String fundId, List<NavDO> navDOList) {
        if(navDOList.size() < 1){
            return;
        }
        //将现有数据无效掉
        deletionInfoMapper.deleteDistributeDeletion(fundId,DeletionType.DISTRIBUTION_DELETION.getCode());
        //查询是否存在拆分
        List<DistributionDO> distributionDOS = distributionMapper.getDistributionByFundId(fundId, DistributeType.DIVIDENDS_SPLIT);
        if(distributionDOS.size() > 0){
            //存在拆分，不做分红缺失计算，同时把以往的数据添加备注
            deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),null,DeletionType.EXIST_SPLIT.getInfo(),null);
            return;
        }
        BigDecimal threshold = new BigDecimal(0.0035);
        BigDecimal preDifference = new BigDecimal(0);
        for(int navIdx=0;navIdx < navDOList.size() ;navIdx++){
            NavDO navDO = navDOList.get(navIdx);
            //获取当前净值日期下的分红总和
            BigDecimal sumDistribute = distributionMapper.getSumDistributeByFundId(navDO.getFundId(),DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD));
            BigDecimal nav = navDO.getNav();
            BigDecimal cumulativeNavWithdrawal  = navDO.getCumulativeNavWithdrawal();
            if(sumDistribute == null){
                sumDistribute = new BigDecimal(0);
            }
            //不存在分红的时候,判断当前的差值是否符合要求
            BigDecimal difference = cumulativeNavWithdrawal.subtract(nav.add(sumDistribute));
            if(difference.compareTo(threshold) > 0){
                //存在缺失
                String tradeDate = null;
                if(navIdx == 0 || navDOList.size() ==1){
                    //有且仅有一条数据
                    tradeDate = DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD)+"~"+DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                }else{
                    //判断前一条的差值与当前是否一致，一致就不处理
                    if(difference.compareTo(preDifference) == 0){
                        continue;
                    }
                    tradeDate = DateUtils.format(navDOList.get(navIdx-1).getPriceDate(),DateUtils.YYYY_MM_DD)+"~"+DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                }
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.DISTRIBUTION_DELETION.getCode());
            }
            preDifference = difference;
        }
    }

    private void assetDeletion(String fundId, List<AssetDO> assetDOList, List<TradeDateDO> tradeDateDOList, FundReportFrequencyDO fundReportFrequencyDO) {
        //将现有数据无效掉
        deletionInfoMapper.deleteDistributeDeletion(fundId,DeletionType.ASSET_DELETION.getCode());
        if(Frequency.DAY == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
            Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getTradeDate(),DateUtils.YYYY_MM_DD)));
            for(String tradeDate : tradeListMap.keySet()){
                if(navListMap.containsKey(tradeDate)){
                    deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    continue;
                }
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
            }
        }
        if(Frequency.WEEK == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
            Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            TreeMap<Integer,List<AssetDO>> weekNavListMap = new TreeMap<>();
            //按周数整合
            for(String priceDate : navListMap.keySet()){
                Integer weekOfYear = Integer.parseInt(priceDate.substring(0,4)+DateUtil.weekOfYear(DateUtils.parse(priceDate,DateUtils.YYYY_MM_DD)));
                if(weekNavListMap.containsKey(weekOfYear)){
                    List<AssetDO> assetDOS = weekNavListMap.get(weekOfYear);
                    assetDOS.addAll(navListMap.get(priceDate));
                    weekNavListMap.put(weekOfYear,assetDOS);
                }else{
                    List<AssetDO> navDOS = new ArrayList<>();
                    navDOS.addAll(navListMap.get(priceDate));
                    weekNavListMap.put(weekOfYear,navDOS);
                }
            }
            Map<Integer,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearWeek()));
            for(Integer weekOfYear : tradeListMap.keySet()){
                List<AssetDO> assetDOS = weekNavListMap.get(weekOfYear);
                if(weekNavListMap.containsKey(weekOfYear)){
                    for(TradeDateDO tradeDateDO : tradeListMap.get(weekOfYear)){
                        String tradeDate = DateUtils.format(tradeDateDO.getTradeDate(),DateUtils.YYYY_MM_DD);
                        deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    }
                    continue;
                }else{
                    if(StringUtil.isNotEmpty(assetDOS)){
                        for(int idx=0;idx < assetDOS.size()-1 ; idx++){
                            AssetDO assetDO = assetDOS.get(idx);
                            String tradeDate = DateUtils.format(assetDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                            deletionInfoMapper.deleteDeletionRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate);
                        }
                    }

                }
                //不包含的话，默认取每周的最后一个交易日作为周净值日期
                List<TradeDateDO> tradeDateDOS = tradeListMap.get(weekOfYear);
                String tradeDate = null;
                if(tradeDateDOS.size() > 0){
                    tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
                }
                //判断当前缺失交易日是否是近三个交易日
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
            }
        }
        if(Frequency.MONTH == Frequency.getFrequencyByCode(fundReportFrequencyDO.getAssetFrequency())){
            Map<String,List<AssetDO>> navListMap = assetDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            TreeMap<String,List<AssetDO>> monthNavListMap = new TreeMap<>();
            //按周数整合
            for(String priceDate : navListMap.keySet()){
                String yearMonth = priceDate.substring(0,7);
                if(monthNavListMap.containsKey(yearMonth)){
                    List<AssetDO> navDOS = monthNavListMap.get(yearMonth);
                    navDOS.addAll(navListMap.get(priceDate));
                    monthNavListMap.put(yearMonth,navDOS);
                }else{
                    List<AssetDO> navDOS = new ArrayList<>();
                    navDOS.addAll(navListMap.get(priceDate));
                    monthNavListMap.put(yearMonth,navDOS);
                }
            }
            Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearmonth()));
            for(String yearMonth : tradeListMap.keySet()){
                //本月的数据不考虑
                String thisMonth = DateUtils.format(new Date(),DateUtils.YYYY_MM);
                if(yearMonth.equals(thisMonth)){
                    continue;
                }
                List<AssetDO> assetDOS = monthNavListMap.get(yearMonth);
                if(monthNavListMap.containsKey(yearMonth)){
                    for(TradeDateDO tradeDateDO : tradeListMap.get(yearMonth)){
                        String tradeDate = DateUtils.format(tradeDateDO.getTradeDate(),DateUtils.YYYY_MM_DD);
                        deletionInfoMapper.updateRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    }
                    continue;
                }else{
                    if(StringUtil.isNotEmpty(assetDOS)){
                        for(int idx=0;idx < assetDOS.size()-1 ; idx++){
                            AssetDO assetDO = assetDOS.get(idx);
                            String tradeDate = DateUtils.format(assetDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                            deletionInfoMapper.deleteDeletionRemark(fundId,DeletionType.ASSET_DELETION.getCode(),tradeDate);
                        }
                    }

                }
                //不包含的话，默认取每周的最后一个交易日作为周净值日期
                List<TradeDateDO> tradeDateDOS = tradeListMap.get(yearMonth);
                String tradeDate = null;
                if(tradeDateDOS.size() > 0){
                    tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
                }
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.ASSET_DELETION.getCode());
            }
        }
    }

    private void navDeletion(String fundId,List<NavDO> navDOList, List<TradeDateDO> tradeDateDOList,FundReportFrequencyDO fundReportFrequencyDO) {
        //将现有数据无效掉
        deletionInfoMapper.deleteDistributeDeletion(fundId,DeletionType.NAV_DELETION.getCode());
        //只处理日月季频率
        if(Frequency.DAY == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
            Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getTradeDate(),DateUtils.YYYY_MM_DD)));
            for(String tradeDate : tradeListMap.keySet()){
                if(navListMap.containsKey(tradeDate)){
                    deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    continue;
                }
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
            }
        }
        if(Frequency.WEEK == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
            Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            TreeMap<Integer,List<NavDO>> weekNavListMap = new TreeMap<>();
            //按周数整合
            for(String priceDate : navListMap.keySet()){
                Integer weekOfYear = Integer.parseInt(priceDate.substring(0,4)+DateUtil.weekOfYear(DateUtils.parse(priceDate,DateUtils.YYYY_MM_DD)));;
                if(weekNavListMap.containsKey(weekOfYear)){
                    List<NavDO> navDOS = weekNavListMap.get(weekOfYear);
                    navDOS.addAll(navListMap.get(priceDate));
                    weekNavListMap.put(weekOfYear,navDOS);
                }else{
                    List<NavDO> navDOS = new ArrayList<>();
                    navDOS.addAll(navListMap.get(priceDate));
                    weekNavListMap.put(weekOfYear,navDOS);
                }
            }
            Map<Integer,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearWeek()));
            for(Integer weekOfYear : tradeListMap.keySet()){
                List<NavDO> navDOS = weekNavListMap.get(weekOfYear);
                if(weekNavListMap.containsKey(weekOfYear)){
                    for(TradeDateDO tradeDateDO : tradeListMap.get(weekOfYear)){
                        String tradeDate = DateUtils.format(tradeDateDO.getTradeDate(),DateUtils.YYYY_MM_DD);
                        deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    }
                    continue;
                }else{
                    //防止频率变更导致数据异常，需要把当前日期下所在的频率全部无效掉
                    if(StringUtil.isNotEmpty(navDOS)){
                        for(int idx=0;idx < navDOS.size()-1 ; idx++){
                            NavDO navDO = navDOS.get(idx);
                            String tradeDate = DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                            deletionInfoMapper.deleteDeletionRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate);
                        }
                    }
                }
                //不包含的话，默认取每周的最后一个交易日作为周净值日期
                List<TradeDateDO> tradeDateDOS = tradeListMap.get(weekOfYear);
                String tradeDate = null;
                if(tradeDateDOS.size() > 0){
                    tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
                }
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
            }
        }
        if(Frequency.MONTH == Frequency.getFrequencyByCode(fundReportFrequencyDO.getNavFrequency())){
            Map<String,List<NavDO>> navListMap = navDOList.stream().collect(Collectors.groupingBy(e -> DateUtils.format(e.getPriceDate(),DateUtils.YYYY_MM_DD)));
            TreeMap<String,List<NavDO>> monthNavListMap = new TreeMap<>();
            //按周数整合
            for(String priceDate : navListMap.keySet()){
                String yearMonth = priceDate.substring(0,7);
                if(monthNavListMap.containsKey(yearMonth)){
                    List<NavDO> navDOS = monthNavListMap.get(yearMonth);
                    navDOS.addAll(navListMap.get(priceDate));
                    monthNavListMap.put(yearMonth,navDOS);
                }else{
                    List<NavDO> navDOS = new ArrayList<>();
                    navDOS.addAll(navListMap.get(priceDate));
                    monthNavListMap.put(yearMonth,navDOS);
                }
            }
            Map<String,List<TradeDateDO>> tradeListMap = tradeDateDOList.stream().collect(Collectors.groupingBy(e -> e.getYearmonth()));
            for(String yearMonth : tradeListMap.keySet()){
                //本月的数据不考虑
                String thisMonth = DateUtils.format(new Date(),DateUtils.YYYY_MM);
                if(yearMonth.equals(thisMonth)){
                    continue;
                }
                List<NavDO> navDOS = monthNavListMap.get(yearMonth);
                if(monthNavListMap.containsKey(yearMonth)){
                    for(TradeDateDO tradeDateDO : tradeListMap.get(yearMonth)){
                        String tradeDate = DateUtils.format(tradeDateDO.getTradeDate(),DateUtils.YYYY_MM_DD);
                        deletionInfoMapper.updateRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate,DeletionType.NO_DELETION.getInfo(),null);
                    }
                    continue;
                }else{
                    //防止频率变更导致数据异常，需要把当前日期下所在的频率全部无效掉
                    if(StringUtil.isNotEmpty(navDOS)){
                        for(NavDO navDO : navDOS){
                            String tradeDate = DateUtils.format(navDO.getPriceDate(),DateUtils.YYYY_MM_DD);
                            deletionInfoMapper.deleteDeletionRemark(fundId,DeletionType.NAV_DELETION.getCode(),tradeDate);
                        }
                    }

                }
                //不包含的话，默认取每周的最后一个交易日作为周净值日期
                List<TradeDateDO> tradeDateDOS = tradeListMap.get(yearMonth);
                String tradeDate = null;
                if(tradeDateDOS.size() > 0){
                    tradeDate = DateUtils.format(tradeDateDOS.get(tradeDateDOS.size()-1).getTradeDate(),DateUtils.YYYY_MM_DD);
                }
                if(tradeDateDOList.size() <= 3){
                    continue;
                }
                TradeDateDO tradeDateDO = tradeDateDOList.get(tradeDateDOList.size()-3);
                if(tradeDateDO.getTradeDate().compareTo(DateUtils.parse(tradeDate,DateUtils.YYYY_MM_DD)) < 0){
                    continue;
                }
                //写入缺失信息表
                saveDeletionInfoDO(fundId,tradeDate,DeletionType.NAV_DELETION.getCode());
            }
        }
    }

    private void saveDeletionInfoDO(String fundId, String tradeDate, Integer code) {
        if(tradeDate == null){
            return;
        }
        DeletionInfoDO deletionInfoDO = new DeletionInfoDO();
        deletionInfoDO.setFundId(fundId);
        deletionInfoDO.setDeletionDate(tradeDate);
        deletionInfoDO.setDeletionType(code);
        DeletionInfoDO oldDeletionDO = deletionInfoMapper.getDeletionInfoDO(deletionInfoDO);
        if(StringUtil.isNull(oldDeletionDO)){
            deletionInfoDO.setIsvalid(1);
            deletionInfoDO.setIsSend(0);
            deletionInfoDO.setUpdateTime(DateUtils.getNowDate());
            deletionInfoDO.setCreateTime(DateUtils.getNowDate());
            deletionInfoMapper.saveDeletionInfoDO(deletionInfoDO);
        }else{
            oldDeletionDO.setIsvalid(1);
            oldDeletionDO.setUpdateTime(DateUtils.getNowDate());
            deletionInfoMapper.updateDeletionInfoDO(oldDeletionDO);
        }
    }
}
