package com.simuwang.daq.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.simuwang.base.common.conts.EmailTypeConst;
import com.simuwang.base.common.util.ExcelUtil;
import com.simuwang.base.pojo.dto.EmailContentInfoDTO;
import com.simuwang.base.pojo.dto.EmailFundNavDTO;
import com.simuwang.base.pojo.dto.ValuationPdfTransformToExcelDTO;
import com.simuwang.base.pojo.valuation.AssetsValuationResult;
import com.simuwang.base.pojo.valuation.ParseValuationInfo;
import com.simuwang.base.pojo.valuation.ValuationNeedParseParam;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author mozuwen
 * @date 2024-09-12
 * @description 估值表邮件解析器
 */
@Component
public class ValuationEmailParser extends AbstractEmailParser {

    private final ValuationParseService valuationParseService;
    private final PdfToExcelService pdfToExcelService;

    public ValuationEmailParser(ValuationParseService valuationParseService, PdfToExcelService pdfToExcelService) {
        this.valuationParseService = valuationParseService;
        this.pdfToExcelService = pdfToExcelService;
    }

    @Override
    public boolean isSupport(Integer emailType) {
        return EmailTypeConst.VALUATION_EMAIL_TYPE.equals(emailType);
    }

    @Override
    public List<EmailFundNavDTO> parse(EmailContentInfoDTO emailContentInfoDTO, Map<String, List<String>> emailFieldMap) {
        List<EmailFundNavDTO> emailFundNavDTOList = CollUtil.newArrayList();
        boolean isSatisfiedParse  = emailContentInfoDTO != null && StrUtil.isNotBlank(emailContentInfoDTO.getFilePath())
                && (ExcelUtil.isExcel(emailContentInfoDTO.getFileName()) || ExcelUtil.isPdf(emailContentInfoDTO.getFileName()));
        if (!isSatisfiedParse) {
            return emailFundNavDTOList;
        }
        List<ValuationNeedParseParam> valuationNeedParseParams = buildValuationNeedParseParam(emailContentInfoDTO);
        List<AssetsValuationResult.Record> recordList = valuationParseService.parseValuationExcel(valuationNeedParseParams);
        if (CollUtil.isNotEmpty(recordList)) {
            List<AssetsValuationResult.Record> parseSucessList = recordList.stream()
                    .filter(e -> e.getSuccess() == 1 || (StrUtil.isNotBlank(e.getMsg()) && "未匹配基金".equals(e.getMsg()))).collect(Collectors.toList());
            EmailFundNavDTO fundNavDTO = convertToFundNavDTO(parseSucessList);
            Optional.ofNullable(fundNavDTO).ifPresent(emailFundNavDTOList::add);
        }
        return emailFundNavDTOList;
    }

    private List<ValuationNeedParseParam> buildValuationNeedParseParam(EmailContentInfoDTO emailContentInfoDTO) {
        // pdf格式文件转成excel
        File file = new File(emailContentInfoDTO.getFilePath());
        ValuationNeedParseParam parseParam = new ValuationNeedParseParam();
        parseParam.setFile(file);
        parseParam.setFileUrl(emailContentInfoDTO.getFilePath());
        parseParam.setOriginFileName(emailContentInfoDTO.getFileName());
        parseParam.setFundId(null);
        parseParam.setFromEmail(1);
        transformPdfToExcel(parseParam);
        return ListUtil.toList(parseParam);
    }

    private void transformPdfToExcel(ValuationNeedParseParam valuationNeedParseParam) {
        String originFileName = valuationNeedParseParam.getOriginFileName();
        if (StrUtil.isNotBlank(originFileName) && !ExcelUtil.isPdf(originFileName)) {
            return;
        }
        File file = valuationNeedParseParam.getFile();
        valuationNeedParseParam.setFileUrl(file.getAbsolutePath());
        //将pdf文件转为excel
        List<ValuationPdfTransformToExcelDTO> toExcelDTOList = pdfToExcelService.pdfToExcel(ListUtil.toList(file));
        Map<String, ValuationPdfTransformToExcelDTO> pdfToExcelMap = MapUtil.newHashMap();
        if (CollUtil.isNotEmpty(toExcelDTOList)) {
            pdfToExcelMap = toExcelDTOList.stream().collect(Collectors.toMap(ValuationPdfTransformToExcelDTO::getOriginalFileName, v -> v));
        }
        ValuationPdfTransformToExcelDTO toExcelDTO = pdfToExcelMap.get(originFileName);
        valuationNeedParseParam.setFile(toExcelDTO != null ? toExcelDTO.getExcelFile() : null);
    }

    private EmailFundNavDTO convertToFundNavDTO(List<AssetsValuationResult.Record> parseSucessList) {
        if (CollUtil.isEmpty(parseSucessList)) {
            return null;
        }
        String fundName = parseSucessList.stream().map(AssetsValuationResult.Record::getParseValuationInfo)
                .filter(Objects::nonNull).map(ParseValuationInfo::getFundName).distinct().findFirst().orElse(null);
        String registerNumber = parseSucessList.stream().map(AssetsValuationResult.Record::getParseValuationInfo)
                .filter(Objects::nonNull).map(ParseValuationInfo::getRegisterNumber).distinct().findFirst().orElse(null);
        String valuationDate = parseSucessList.stream().map(AssetsValuationResult.Record::getDate).filter(Objects::nonNull).distinct().findFirst().orElse(null);
        String nav = parseSucessList.stream().map(AssetsValuationResult.Record::getNav).filter(Objects::nonNull).distinct().findFirst().orElse(null);
        String cumulativeNavWithdrawal = parseSucessList.stream().map(AssetsValuationResult.Record::getCumulativeNavWithdrawal).filter(Objects::nonNull).distinct().findFirst().orElse(null);
        String assetNet = parseSucessList.stream().map(AssetsValuationResult.Record::getAssetNet).filter(Objects::nonNull).distinct().findFirst().orElse(null);
        String assetShare = parseSucessList.stream().map(AssetsValuationResult.Record::getAssetShare).filter(Objects::nonNull).distinct().findFirst().orElse(null);
        List<String> fundIdList = parseSucessList.stream().map(AssetsValuationResult.Record::getFundId).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        EmailFundNavDTO fundNavDTO = new EmailFundNavDTO();
        fundNavDTO.setFundName(fundName);
        fundNavDTO.setRegisterNumber(registerNumber);
        fundNavDTO.setPriceDate(valuationDate);
        fundNavDTO.setNav(nav);
        fundNavDTO.setCumulativeNavWithdrawal(cumulativeNavWithdrawal);
        fundNavDTO.setAssetNet(assetNet);
        fundNavDTO.setAssetShare(assetShare);
        fundNavDTO.setFundIdList(fundIdList);
        return fundNavDTO;
    }

}
