package com.friday.custody.service.trustService.mailHandleService.logicService;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.friday.base.common.response.DubboResult;
import com.friday.custody.entity.*;
import com.friday.custody.enums.DaasTrustNoEnum;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.service.trustService.mailHandleService.multiVersionService.impl.BaseHandlerTxtServiceImpl;
import com.friday.custody.service.trustService.mailHandleService.multiVersionService.impl.HandlerVersionTxtServiceImpl;
import com.friday.custody.common.CustodyContants;
import com.friday.custody.dto.FundValueEmailDTO;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.utils.*;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.enums.EmailConfigPurposeEnum;
import com.friday.custody.service.basicService.DataDictionaryTypeCertificateCsdcService;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.PullDataFailureLogService;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.trustService.OutsourceService;
import com.friday.custody.service.trustService.citicZhongXin.service.OutsourceZhongXinService;
import com.friday.custody.service.trustService.gtja.utils.RandomStrUtil;
import com.friday.custody.service.trustService.haitong.service.OutsourceHaiTongServiceImpl;
import com.friday.custody.service.trustService.mailHandleService.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.mail.*;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.friday.custody.common.CustodyContants.YEAR_MONTH_DAY_REGEX_WITH_SEPARATOR;
import static com.friday.custody.service.trustService.citicZhongXin.service.OutsourceZhongXinService.getBigDecimalFromCell;
import static com.friday.custody.service.trustService.citicZhongXin.service.OutsourceZhongXinService.getValue;
import static com.friday.custody.service.trustService.mailHandleService.common.FieldConstants.TOTAL_ASSERT_ROW_WITH_COLON;

@Service
@Slf4j
public class OutSourceMailServiceImpl implements OutsourceService {
    @Autowired
    private InvokeRecordService invokeRecordService;
    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private AccountInfoServiceImpl accountInfoService;
    @Autowired
    private FundInfoServiceImpl fundInfoService;//a
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//b
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//b
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;//d
    @Autowired
    private CustShareSeqInfoServiceImpl custShareSeqInfoService;
    @Autowired
    private TgAccountBalanceInfoServiceImpl tgAccountBalanceInfoService;//e
    @Autowired
    private TgAccountSeqInfoServiceImpl tgAccountSeqInfoService;//f
    @Autowired
    private MjAccountBalanceInfoServiceImpl mjAccountBalanceInfoService;//g
    @Autowired
    private MjAccountSeqInfoServiceImpl mjAccountSeqInfoService;//h
    @Autowired
    private FundTradeInfoServiceImpl fundTradeInfoService;//i
    @Autowired
    private FundValueTableDataInfoServiceImpl fundValueTableDataInfoService;//j
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;//j
    @Autowired
    private DataDictionarySellerServiceImpl sellerService;
    @Autowired
    private CustShareDetailInfoServiceImpl custShareDetailInfoService;
    @Autowired
    private TenantEmailAuthorizationInfoServiceImpl tenantEmailAuthorizationInfoService;
    @Autowired
    private BaseHandlerTxtServiceImpl baseHandlerTxtService;
    @Autowired
    private TenantEmailVersionMapServiceImpl tenantEmailVersionMapService;
    @Autowired
    private HandlerVersionTxtServiceImpl handlerVersionTxtService;
    @Autowired
    private DataDictionaryTypeOfFundValuationServiceImpl typeOfFundValuationService;
    @Autowired
    private FundValuationServiceImpl fundValuationService;
    @Autowired
    private OutsourceZhongXinService outsourceZhongXinService;

//    public static final String DEFAULT_MAIL_PARENT_PATH = "/app/work/custody/email/";
    @Value("${custody.email.defalut.parentPath}")
    public String DEFAULT_MAIL_PARENT_PATH;
    public static final String DEFAULT_PATTERN = "yyyyMMdd";
    public static final String DOT = ".";

    public void initByMail(TenantEscrowAuthorizationInfoDto theTrustNo, String date, String flag) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DEFAULT_PATTERN);
        LocalDate now = LocalDate.now();
        LocalDate lastYear = now.minusYears(1L);
        if(StringUtils.isNotBlank(date)){
            lastYear = LocalDate.parse(date,dateTimeFormatter);
        }

        String date1 = dateTimeFormatter.format(lastYear);
        updateDataByEmail(date1,flag,theTrustNo);

        /*while (!now.isBefore(lastYear)){
            String date1 = dateTimeFormatter.format(lastYear);
            flag = updateDataByEmail(date1,flag,theTrustNo);
            lastYear = lastYear.plusDays(1L);
        }*/
    }

    @Override
    public R initTenantData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    /**
     * 单个邮件数据初始化没有意义
     * @param tenant
     * @return
     */
    @Override
    public R initTenantDataSingle(TenantEscrowAuthorizationInfoDto tenant) {
//        log.info("单个邮件数据初始化没有意义...tenant={}",JSON.toJSONString(tenant));
//        updateDataByEmail(null,"initDate",tenant);
//        log.info("邮件数据初始化结束:");
        return R.ok();
    }

    private void getAllData(TenantEscrowAuthorizationInfoDto tenant, File file, String flag) throws Exception {
        log.info("OutSourceMailServiceImpl:getAllData:tenant={},file={},flag={}",
                JSON.toJSONString(tenant),
                file == null ? "null" : file.getAbsolutePath(),
                flag);
        String trustNo = tenant.getTrustNo();
        //根据托管好查询对应的版本号
        String version = tenantEmailVersionMapService.getVersionByTrustNo(trustNo);
        log.info("托管对应邮件版本信息：trustNo={}, version={}", trustNo, version);
        handlerVersionTxtService.getAllData(tenant, file, flag, version);
        String filename = "";
        if(file!=null){
            filename = file.getAbsolutePath();
        }
        log.info("getAllData:tenant={},file={}，flag={}",JSON.toJSONString(tenant),flag,filename);
    }

    private void getUpdateData(TenantEscrowAuthorizationInfoDto tenant, File file, String flag) {
        log.info("OutSourceMailServiceImpl:getUpdateData:tenant={},file={},flag={}",
                JSON.toJSONString(tenant),
                file==null?"null":file.getAbsolutePath(),
                flag);
        String trustNo = tenant.getTrustNo();
        //根据托管好查询对应的版本号
        String version = tenantEmailVersionMapService.getVersionByTrustNo(trustNo);
        handlerVersionTxtService.getUpdateData(tenant, file, flag, version);
        String filename = "";
        if(file!=null){
            filename = file.getAbsolutePath();
        }
        log.info("getUpdateData:tenant={},file={},flag={}",JSON.toJSONString(tenant),filename,flag);
    }

    private void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"Share_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"Share_"+date+".txt";
            }
            log.info("processCustShareInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<CustShareInfoEntity> entities = getCustShareInfo(bytes,tenant,trustNo);
                log.info("读取文件{} processCustShareInfoData获取数据量为{}",filePath,entities.size());

                custShareInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processCustShareInfoData异常{}",e);
        }
    }

    private List<CustShareInfoEntity> getCustShareInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> sellerDic = null;
        Map<String, String> bonus = null;
        try {
            sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            bonus = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, "54");
            log.info("OutSourceMailServiceImpl 字典映射:销售商 ={}",JSON.toJSONString(sellerDic));
            log.info("OutSourceMailServiceImpl 字典映射:分红方式 ={}",JSON.toJSONString(bonus));

        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl：getCustShareInfo获取字典异常{}",e);
        }

        List<CustShareInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalBonus = bonus;
        bytes.stream().forEach(e->{
            String agencyNameOrigin = getString(49, 58, e);
            String agencyName = sellerService.queryAgencyName("长江证券", agencyNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyName 原值为{},映射值为{}",agencyNameOrigin,agencyName);

            String agencyNoOrigin = getString(49, 58, e);
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, agencyNoOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyNo 原值为{},映射值为{}",agencyNoOrigin,agencyNo);

            String fundNameOrigin = getString(40, 48, e);
            String fundName = fundInfoService.getFundNameByFundCode(fundNameOrigin, trustNo, tenant.getTenantName());
            log.info("OutSourceMailServiceImpl 字典映射:fundName 原值为{},映射值为{}",fundNameOrigin,fundName);

            String bonusMethodOrigin = getString(106, 107, e);
            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(finalBonus,bonusMethodOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:bonusMethod 原值为{},映射值为{}",bonusMethodOrigin,bonusMethod);

            BigDecimal shares = fundNetValueInfoService.getSharesByFundInfo(FundNetValueInfoEntity.builder().admin(tenant.getTenantName()).fundCode(getString(40, 48, e)).fundName(fundName).build());
            String date = getString(164, 172, e);
            result.add(CustShareInfoEntity.builder()
                    .fundAcco(getString(20,40,e))
                    .fundCode(getString(40,48,e))
                    .agencyNo(agencyNo)
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(67,83,e))))
                    .frozenShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(83,99,e))))
                    .bonusMethod(bonusMethod)
                    .tradeAcco(getString(107,131,e))
                    .income(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(131,147,e))))
                    .updateDate(date.substring(0,4)+"-"+date.substring(4,6)+"-"+date.substring(6,8)+" 00:00:00")
                    .enableShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(67,83,e))).subtract(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(83,99,e)))))
                    .shareRatio(BigDecimalUtil.getShareRatio(shares, BigDecimalUtil.obj2BigDecimal(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(67,83,e))))))
                    .fundName(fundName)
                    .agencyName(agencyName)
                    .currency("156")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        });
        return result;
    }

    /**
     * 20230216
     *
     * @param tenant
     * @param file
     * @param trustNo
     * @param flag
     */
    @Deprecated
    private void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"FundInfo_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"FundInfo_"+date+".txt";
            }
            log.info("processFundNetValueInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<FundNetValueInfoEntity> entities = getFundNetValueInfo(bytes,tenant,trustNo);
                log.info("读取文件{} processFundNetValueInfoData获取数据量为{}",filePath,entities.size());

                fundNetValueInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processFundNetValueInfoData异常{}",e);
        }
    }

    private List<FundNetValueInfoEntity> getFundNetValueInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        bytes.stream().forEach(e->{
            result.add(FundNetValueInfoEntity.builder()
                    .fundCode(getString(0,8,e))
                    .fundName(getString(8,108,e))
                    .netValue(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(108,119,e)),4))
                    .shares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(119,135,e))))
                    .netValueDate(getString(168,176,e))
                    .totalNetValue(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(177,188,e)),4))
                    .ettFundIncome(BigDecimalUtil.str2BigDecimal(getSubStringFive(getString(204,214,e))))
                    .sevenDayRate(BigDecimalUtil.str2BigDecimal(getsSubStringFour(getString(214,223,e)),4))
                    .assetValue(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(252,268,e))))
                    .currency("156")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        });
        return result;
    }

    private void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"ProfitCurrent_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"ProfitCurrent_"+date+".txt";
            }
            log.info("processFundProfitInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<FundProfitInfoEntity> entities = getFundProfitInfo(bytes,tenant,trustNo);
                log.info("读取文件{} processFundProfitInfoData获取数据量为{}",filePath,entities.size());
                fundProfitInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processFundProfitInfoData异常{}",e);
        }
    }

    private List<FundProfitInfoEntity> getFundProfitInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> businessName = null;
        Map<String, String> pay = null;
        Map<String, String> sellerDic = null;
        Map<String, String> handle = null;
        try {
            businessName = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, "54");
            pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, "54");
            sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            handle = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_SERVICE, "54");
            log.info("OutSourceMailServiceImpl 字典映射:业务类型 ={}",JSON.toJSONString(businessName));
            log.info("OutSourceMailServiceImpl 字典映射:收费方式 ={}",JSON.toJSONString(pay));
            log.info("OutSourceMailServiceImpl 字典映射:销售商 ={}",JSON.toJSONString(sellerDic));
            log.info("OutSourceMailServiceImpl 字典映射:处理类型 ={}",JSON.toJSONString(handle));
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getFundProfitInfo获取字典异常{}",e);
        }

        List<FundProfitInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalBusinessName = businessName;
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalPay = pay;
        Map<String, String> finalHandle = handle;
        bytes.stream().forEach(e->{
            String agencyNameOrigin = getString(78, 87, e);
            String agencyName = sellerService.queryAgencyName("长江证券",agencyNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyName 原值为{},映射值为{}",agencyNameOrigin,agencyName);

            String fundNameOrigin = getString(70, 78, e);
            String fundName = fundInfoService.getFundNameByFundCode(fundNameOrigin, trustNo, tenant.getTenantName());
            log.info("OutSourceMailServiceImpl 字典映射:fundName 原值为{},映射值为{}",fundNameOrigin,fundName);

            String businessNameOrigin = getString(0, 2, e);
            if("24".equals(businessNameOrigin) || "22".equals(businessNameOrigin)){
                businessNameOrigin = "0" + businessNameOrigin;
            }
            String businessNameValue = MatchDataDictionaryKeyUtil.getKey(finalBusinessName, businessNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:businessName 原值为{},映射值为{}",businessNameOrigin,businessNameValue);

            String agencyNoOrigin = getString(78, 87, e);
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, agencyNoOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyNo 原值为{},映射值为{}",agencyNoOrigin,agencyNo);

            String shareTypeOrigin = getString(120, 121, e);
            String shareType = MatchDataDictionaryKeyUtil.getKey(finalPay, shareTypeOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:shareType 原值为{},映射值为{}",shareTypeOrigin,shareType);

            String sortFlagOrigin = getString(459, 460, e);
            String sortFlag = MatchDataDictionaryKeyUtil.getKey(finalHandle, sortFlagOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:sortFlag 原值为{},映射值为{}",sortFlagOrigin,sortFlag);

            result.add(FundProfitInfoEntity.builder()
                    .businessName(businessNameValue)
                    .confirmDate(getString(2,10,e))
                    .cserialNo(getString(10,30,e))
                    .fundAcco(getString(50,70,e))
                    .fundCode(getString(70,78,e))
                    .agencyNo(agencyNo)
                    .branchCode(getString(87,96,e))
                    .tradeAcco(getString(96,120,e))
                    .shareType(shareType)
                    .requestDate(getString(121,129,e))
                    .oriCserialNo(getString(147,167,e))
                    .registDate(getString(167,175,e))
                    .shares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(191,207,e))))
                    .nav(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(319,330,e)),4))
                    .totalNav(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(330,341,e)),4))
                    .currRatio(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(341,352,e)),4))
                    .yearRatio(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(352,363,e)),4))
                    .returnFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(379,395,e))))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(395,411,e))))
                    .factBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(411,427,e))))
                    .factShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(427,443,e))))
                    .bonusBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(443,459,e))))
                    .sortFlag(sortFlag)
                    .oriDate(getString(460,468,e))
                    .holdDay(getString(468,478,e).replaceFirst("0*",""))
                    .oriNav(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(478,489,e)),4))
                    .oriTotalNav(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(489,500,e)),4))
                    .fundName(fundName)
                    .agencyName(agencyName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        });
        return result;
    }

    private void processCustShareSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"ShareCurrents_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"ShareCurrents_"+date+".txt";
            }
            log.info("processCustShareSeqInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<CustShareSeqInfoEntity> entities = getCustShareSeqInfo(bytes,tenant,trustNo);
                log.info("读取文件{} processCustShareSeqInfoData获取数据量为{}",filePath,entities.size());

                custShareSeqInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processCustShareSeqInfoData异常{}",e);
        }
    }

    private List<CustShareSeqInfoEntity> getCustShareSeqInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> businessName = null;
        Map<String, String> pay = null;
        Map<String, String> sellerDic = null;
        try {
            businessName = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, "54");
            pay = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, "54");
            sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            log.info("OutSourceMailServiceImpl 字典映射:业务类型={}",JSON.toJSONString(businessName));
            log.info("OutSourceMailServiceImpl 字典映射:收费方式={}",JSON.toJSONString(pay));
            log.info("OutSourceMailServiceImpl 字典映射:销售商={}",JSON.toJSONString(sellerDic));
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getCustShareSeqInfo:获取字典异常{}",e);
        }

        List<CustShareSeqInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalBusinessName = businessName;
        Map<String, String> finalPay = pay;
        Map<String, String> finalSellerDic = sellerDic;
        bytes.stream().forEach(e->{
            String agencyNameOrigin = getString(116, 125, e);
            String agencyName = sellerService.queryAgencyName("长江证券", agencyNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyName原值为{},映射值为{}",agencyNameOrigin,agencyName);

            String businessNameOrigin = getString(28, 31, e);
            String businessNameValue = MatchDataDictionaryKeyUtil.getKey(finalBusinessName, businessNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:businessName原值为{},映射值为{}",businessNameOrigin,businessNameValue);

            String shareTypeOrigin = getString(115, 116, e);
            String shareType = MatchDataDictionaryKeyUtil.getKey(finalPay, shareTypeOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:shareType 原值为{},映射值为{}",shareTypeOrigin,shareType);

            String agencyNoOrigin = getString(116, 125, e);
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic,agencyNoOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyNo 原值为{},映射值为{}",agencyNoOrigin,agencyNo);

            String fundName = fundInfoService.getFundNameByFundCode(getString(107,115,e), trustNo, tenant.getTenantName());
            result.add(CustShareSeqInfoEntity.builder()
                    .confirmDate(getString(0,8,e))
                    .cserialNo(getString(8,28,e))
                    .businessName(businessNameValue)
                    .requestDate(getString(31,39,e))
                    .requestNo(getString(39,63,e))
                    .fundAcco(getString(63,83,e))
                    .tradeAcco(getString(83,107,e))
                    .fundCode(getString(107,115,e))
                    .shareType(shareType)
                    .agencyNo(agencyNo)
                    .branchCode(getString(125,134,e))
                    .occurShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(134,150,e))))
                    .occurBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(150,166,e))))
                    .lastHoldShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(166,182,e))))
                    .seqNo(getString(190,222,e))
                    .currency("156")
                    .agencyName(agencyName)
                    .fundName(fundName)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        });
        return result;
    }

    private void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"Confirm_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"Confirm_"+date+".txt";
            }
            log.info("processFundTradeInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<FundTradeInfoEntity> entities = getFundTradeInfo(bytes,tenant,trustNo);
                log.info("读取文件{} processFundTradeInfoData获取数据量为{}",filePath,entities.size());
                fundTradeInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processFundTradeInfoData异常{}",e);
        }
    }

    private List<FundTradeInfoEntity> getFundTradeInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> businessName = null;
        Map<String, String> sellerDic = null;
        Map<String, String> currency = null;
        Map<String, String> bonus = null;
        try {
            businessName = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, "54");
            sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, "54");
            bonus = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, "54");
            log.info("OutSourceMailServiceImpl 字典映射:业务类型={}",JSON.toJSONString(businessName));
            log.info("OutSourceMailServiceImpl 字典映射:销售商={}",JSON.toJSONString(sellerDic));
            log.info("OutSourceMailServiceImpl 字典映射:币种={}",JSON.toJSONString(currency));
            log.info("OutSourceMailServiceImpl 字典映射:分红方式={}",JSON.toJSONString(bonus));

        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getFundTradeInfo获取字典异常{}",e);
        }

        List<FundTradeInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalBusinessName = businessName;
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalCurrency = currency;
        Map<String, String> finalBonus = bonus;
        bytes.stream().forEach(e->{
            String agencyName = sellerService.queryAgencyName("长江证券", getString(118,127,e));

            String fundNameOrigin = getString(77, 85, e);
            String fundName = fundInfoService.getFundNameByFundCode(fundNameOrigin, trustNo, tenant.getTenantName());
            log.info("OutSourceMailServiceImpl 字典映射:fundName 原值为{},映射值为{}",fundNameOrigin,fundName);

            String businessNameOrigin = getString(34, 37, e);
            String businessNameValue = MatchDataDictionaryKeyUtil.getKey(finalBusinessName, businessNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:businessName 原值为{},映射值为{}",businessNameOrigin,businessNameValue);

            String agencyNoOrigin = getString(118, 127, e);
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic,agencyNoOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyNo 原值为{},映射值为{}",agencyNoOrigin,agencyNo);

            String currencyOrigin = getString(145, 148, e);
            String currencyValue = MatchDataDictionaryKeyUtil.getKey(finalCurrency, currencyOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:currency 原值为{},映射值为{}",currencyOrigin,currencyValue);

            String bonusMethodOrigin = getString(331, 332, e);
            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(finalBonus, bonusMethodOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:bonusMethod 原值为{},映射值为{}",bonusMethodOrigin,bonusMethod);

            result.add(FundTradeInfoEntity.builder()
                    .agencyName(agencyName)
                    .fundName(fundName)
                    .confirmDate(getString(0,8,e))
                    .cserialNo(getString(14,34,e))
                    .businessName(businessNameValue)
                    .fundAcco(getString(57,77,e))
                    .fundCode(getString(77,85,e))
                    .requestDate(getString(86,94,e))
                    .requestNo(getString(94,118,e))
                    .agencyNo(agencyNo)
                    .currency(currencyValue)
                    .confirmShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(148,164,e))))
                    .confirmBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(164,180,e))))
                    .tradeFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(180,196,e))))
                    .taFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(196,212,e))))
                    .stampTax(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(212,228,e))))
                    .backFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(228,244,e))))
                    .bonusMethod(bonusMethod)
                    .tradeAcco(getString(365,389,e))
                    .netValue(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(389,400,e)),4))
                    .fundFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(586,602,e))))
                    .agencyFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(602,618,e))))
                    .registFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(618,634,e))))
                    .interest(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(634,650,e))))
                    .interestShare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(791,807,e))))
                    .summary(getString(807,1307,e))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        });
        return result;
    }

    private void processInvestorBankInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"Acconet_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"Acconet_"+date+".txt";
            }
            log.info("processInvestorBankInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<InvestorBankInfoEntity> entities = getInvestorBankInfo(bytes,tenant,trustNo);
                log.info("读取文件{}，processInvestorBankInfoData获取数据量为{}",filePath,entities.size());
                investorBankInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processInvestorBankInfoData异常{}",e);
        }
    }

    private List<InvestorBankInfoEntity> getInvestorBankInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> bankCodeDir = null;
        try {
            bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "资金清算系统银行编码");
            log.info("OutSourceMailServiceImpl 字典映射:银行编码={}",JSON.toJSONString(bankCodeDir));

        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getInvestorBankInfo获取字典异常{}",e);
        }

        List<InvestorBankInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalBankCodeDir = bankCodeDir;
        bytes.stream().forEach(e->{
            String bankCodeOrigin = getString(172, 232, e);
            String bankCode = MatchDataDictionaryKeyUtil.getKey(finalBankCodeDir, bankCodeOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:bankCode原值为{},映射值为{}",bankCodeOrigin,bankCode);

            result.add(InvestorBankInfoEntity.builder()
                    .fundAcco(getString(0,20,e))
                    .tradeAcco(getString(58,82,e))
                    .nameInBank(getString(84,144,e))
                    .bankNo(getString(144,172,e))
                    .bankCode(bankCode)
                    .bankNoType("银行账号")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
            log.info("result{}"+ JSON.toJSONString(result));
        });
        return result;
    }

    private void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"Acco_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"Acco_"+date+".txt";
            }
            log.info("processInvestorInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<InvestorInfoEntity> entities = getInvestorInfo(bytes,tenant,trustNo);
                log.info("读取文件{},processInvestorInfoData获取数据量为{}",filePath,entities.size());
                investorInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processInvestorInfoData异常{}",e);
        }
    }

    private List<InvestorInfoEntity> getInvestorInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {

        Map<String, String> custTypeCsdcDic = null;
        Map<String, Map<String, String>> identityTypeCsdcDic = null;
        try {
            custTypeCsdcDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CUST_TYPE_CSDC_SERVICE, "54");
            identityTypeCsdcDic = certificateCsdcService.queryCertificateWithDetail("54");
            log.info("OutSourceMailServiceImpl 字典映射:客户类型 中登={}",JSON.toJSONString(custTypeCsdcDic));
            log.info("OutSourceMailServiceImpl 字典映射:证件类型需={}",JSON.toJSONString(identityTypeCsdcDic));
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getInvestorInfo:获取字典异常{}",e);
        }
        List<InvestorInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalCustTypeCsdcDic = custTypeCsdcDic;
        Map<String, Map<String, String>> finalIdentityTypeCsdcDic = identityTypeCsdcDic;
        bytes.stream().forEach(e->{
            String key2 = getString(21, 22, e);
            String key = MatchDataDictionaryKeyUtil.getKey(finalCustTypeCsdcDic, key2);
            String certiType = getString(22,23,e);
            String identityType = MatchDataDictionaryKeyUtil.getKey(key, finalIdentityTypeCsdcDic, certiType);
            log.info("OutSourceMailServiceImpl 字典映射:custType原值为{}、映射值为{}",key2,key);
            log.info("OutSourceMailServiceImpl 字典映射:identityType原值为{}、{},映射值为{}",key,certiType,identityType);

            String date = getString(754, 762, e);
            result.add(InvestorInfoEntity.builder()
                    .custType(key)
                    .identityType(identityType)
                    .identityNo(getString(23,53,e))
                    .fundAcco(getString(53,73,e))
                    .custName(getString(97,217,e))
                    .address(getString(303,423,e))
                    .zipCode(getString(423,429,e))
                    .email(getString(475,515,e))
                    .mobileNo(getString(515,539,e))
                    .accoOpenDate(getString(746,754,e))
                    .updateDate(date.substring(0,4)+"-"+date.substring(4,6)+"-"+date.substring(6,8)+" 00:00:00")
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
            log.info("result{}"+ JSON.toJSONString(result));
        });
        return result;
    }

    private void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag) {
        try{
            String filePath = file.getAbsolutePath() + File.separator + "TAInfo.Txt";
            log.info("processFundInfoData需要读取文件：{}", filePath);
//            int line = Integer.parseInt(FileUtil.readLine(filePath).replace("FundInfo", "").replace(" ", "").replaceFirst("0*", ""));
            Map<String, String> lineMap = FileUtil.readLine(filePath, "FundInfo");
            if (ObjectUtils.isEmpty(lineMap)){
                return;
            }
            //解析出所在行中的数据条数
            int line = Integer.parseInt(lineMap.get("line").replace("FundInfo", "").replace(" ", "").replaceFirst("0*", ""));
            //所在行
            int lineNum = Integer.parseInt(lineMap.get("lineNum"));
            List<byte[]> bytes = FileUtil.readPointLine(filePath, line, lineNum);
            if (!CollectionUtils.isEmpty(bytes)) {
                List<FundInfoEntity> entities = getFundInfo(bytes, tenant, trustNo);
                log.info("读取文件{} processFundInfoData获取数据量为{}", filePath, entities.size());
                fundInfoService.saveData(null, entities);
            } else {
                log.info("文件{}没有具体内容，跳过", filePath);
            }
        }catch (Exception e){
            log.error("邮件processFundInfoData异常{}",e);
        }
    }

    private List<FundInfoEntity> getFundInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> status = new HashMap<>();
        Map<String, String> type = new HashMap<>();
        Map<String, String> day = new HashMap<>();
        try{
            status = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_SERVICE, "54");
            type = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, "54");
            day= dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TA_TRANSACTION_CONFIRM_ATION_DAYS_SERVICE, "54");
            log.info("OutSourceMailServiceImpl 字典映射:产品状态={}",JSON.toJSONString(status));
            log.info("OutSourceMailServiceImpl 字典映射:基金类型={}",JSON.toJSONString(type));
            log.info("OutSourceMailServiceImpl 字典映射:TA确认天数={}",JSON.toJSONString(day));
        }catch (Exception e){
            log.error("OutSourceMailServiceImpl:getFundInfo获取字典异常{}",e);
        }

        List<FundInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalStatus = status;
        Map<String, String> finalType = type;
        Map<String, String> finalDay = day;
        bytes.stream().forEach(e->{
            String fundTypeOrigin = getString(509, 510, e);
            String fundType = MatchDataDictionaryKeyUtil.getKey(finalType, fundTypeOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:fundType原值为{},映射值为{}",fundTypeOrigin,fundType);

            String finalStatusOrigin = getString(400,401,e);
            String fundStatus = MatchDataDictionaryKeyUtil.getKey(finalStatus, finalStatusOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:fundStatus原值为{},映射值为{}",finalStatusOrigin,fundStatus);

            String confDaysOrigin = getString(747,750,e);
            String confDays = MatchDataDictionaryKeyUtil.getKey(finalDay, confDaysOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:fundStatus原值为{},映射值为{}",confDaysOrigin,confDays);

            String durationPeriod = getString(402, 412, e);
            durationPeriod = "0" + durationPeriod;
            String durationPeriodNew = durationPeriod.replaceAll("^(0+)", "");
            result.add(FundInfoEntity.builder()
                    .fundCode(getString(0,8,e))
                    .fundName(getString(8,108,e))
                    .createDate(getString(141,149,e))
                    .fundStatus(fundStatus)
                    .durationPeriod(durationPeriodNew)
                    .fundType(fundType)
                    .peType(fundType)
                    .confDays(confDays)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
            log.info("result{}", JSON.toJSONString(result));
        });
        return result;
    }

    private void processCustShareDetailInfoData(TenantEscrowAuthorizationInfoDto tenant,File file, String trustNo, String flag) {
        try{
            String date = file.getName().substring(3);
            String filePath;
            if(StringUtils.isNotBlank(flag)){
                filePath= file.getAbsolutePath()+File.separator+"ShareDetail_"+date+"_all.txt";
            }else{
                filePath= file.getAbsolutePath()+File.separator+"ShareDetail_"+date+".txt";
            }
            log.info("processCustShareDetailInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<CustShareDetailInfoEntity> entities = getCustShareDetailInfo(bytes,tenant,trustNo);
                log.info("读取文件{}，processCustShareDetailInfoData获取数据量为{}",filePath,entities.size());
                custShareDetailInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processCustShareDetailInfoData异常{}",e);
        }
    }

    private List<CustShareDetailInfoEntity> getCustShareDetailInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        Map<String, String> sellerDic = null;
        Map<String, String> share = null;
        try {
            sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            share = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SHARE_SOURCE_SERVICE, "54");
            log.info("OutSourceMailServiceImpl 字典映射:销售商={}",JSON.toJSONString(sellerDic));
            log.info("OutSourceMailServiceImpl 字典映射:份额来源={}",JSON.toJSONString(share));
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getCustShareDetailInfo:获取字典异常{}",e);
        }

        List<CustShareDetailInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalShare = share;
        bytes.stream().forEach(e->{
            String agencyNameOrigin = getString(49, 58, e);
            String agencyName = sellerService.queryAgencyName("长江证券", agencyNameOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyName原值为{},映射值为{}",agencyNameOrigin,agencyName);

            String fundNameOrigin = getString(40, 48, e);
            String fundName = fundInfoService.getFundNameByFundCode(fundNameOrigin, trustNo, tenant.getTenantName());
            log.info("OutSourceMailServiceImpl 字典映射:fundName原值为{},映射值为{}",fundNameOrigin,fundName);

            String agencyNoOrigin = getString(49, 58, e);
            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, agencyNoOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:agencyNo原值为{},映射值为{}",agencyNoOrigin,agencyNo);

            String sourceTypeOrigin = getString(95, 96, e);
            String sourceType = MatchDataDictionaryKeyUtil.getKey(finalShare, sourceTypeOrigin);
            log.info("OutSourceMailServiceImpl 字典映射:sourceType原值为{},映射值为{}",sourceTypeOrigin,sourceType);

            result.add(CustShareDetailInfoEntity.builder()
                    .fundCode(getString(40,48,e))
                    .fundName(fundName)
                    .fundAcco(getString(20,40,e))
                    .agencyNo(agencyNo)
                    .agencyName(agencyName)
                    .branchCode(getString(58,67,e))
                    .confirmDate(getString(67,75,e))
                    .cserialNo(getString(75,95,e))
                    .sourceType(sourceType)
                    .remainShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(96,112,e))))
                    .oriNetValue(BigDecimalUtil.str2BigDecimal(getSubStringEight(getString(112,123,e))))
                    .tradeAcco(getString(123,147,e))
                    .registDate(getString(147,155,e))
                    .oriBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(181,197,e))))
                    .oriShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(getString(197,213,e)),4))
                    .seqNo(RandomStrUtil.getRandomStr(32))
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
            log.info("result{}"+ JSON.toJSONString(result));
        });
        return result;
    }

    /**
     * 主要的日常定时任务，每天早7晚7
     * @param tenants
     * @return
     */
    @Override
    public R updateDataDaily(List<TenantEscrowAuthorizationInfoDto> tenants) {
        log.info("使用邮件进行数据日常更新 tenants={}",JSON.toJSONString(tenants));
        tenants.forEach(tenant->{
            CompletableFuture.supplyAsync(()->{
                String format = LocalDate.now().minusMonths(1L).format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
                String s = updateDataByEmail(format, null, tenant);
                log.info("updateDataByEmail返回s={}",s);
                return s;
            });
        });
        return R.ok("使用邮件进行数据初始化结束！");
    }



    private void setDefaultEmailFilePath(TenantEscrowAuthorizationInfoDto tenant, TenantEmailAuthorizationInfoEntity emailConfig) {
        String returnString = "";
        String osName = System.getProperty("os.name");
        log.info("操作系统名字为{}",osName);
        //win系统
        String parentPath = "";
        if (osName.toLowerCase().indexOf("win") != -1) {
            parentPath = "C:\\temp\\";
        }else{
            parentPath = DEFAULT_MAIL_PARENT_PATH;
        }

        returnString = parentPath
                + tenant.getTenantName()
                + File.separator
                + tenant.getTrustNo();
        log.info("setDefaultEmailFilePath 设置默认文件夹存储地址：{}",returnString);
        emailConfig.setDirFilePath(returnString);
        File file = new File(returnString);
        if(!file.exists()){
            if (!file.mkdirs()) {
                log.error("创建文件夹{}失败!",file.getAbsolutePath());
            }
        }
    }

    /**
     * 单个邮件数据初始化没有意义
     * @param tenant
     * @return
     */
    @Override
    public R updateSingleDataDaily(TenantEscrowAuthorizationInfoDto tenant) {
//        log.info("使用邮件进行数据日常更新 tenant={},date={},flag={}",JSON.toJSONString(tenant));
//        String date = LocalDate.now().minusMonths(1L).format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
//        updateDataByEmail(date, null, tenant);
//        log.info("使用邮件进行数据日常更新 trustNO = {},tenant={},date={},flag={}结束!",tenant.getTrustNo(), JSON.toJSONString(tenant), date, null);
        return R.ok();
    }

    @Override
    public R PullRemoteDataFirstQueueJob() {
        return null;
    }

    @Override
    public R initLaterTenantData(String versionStr, List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R initLaterSingleTenantData(String versionStr, TenantEscrowAuthorizationInfoDto tenant) {
        log.info("initLaterSingleTenantData is begin...the versionStr is {} ,the tenant is {}", versionStr, JSON.toJSONString(tenant));
        String trustNo = tenant.getTrustNo();
        Integer loopNum = CustodyContants.INIT_BY_MONTH_LOOP_TIME;
        switch (versionStr) {
            case CustodyContants.R_PT_S_CUSTODY_3_2_0:
                initTenantDataSingle(tenant);
                break;
        }
        return null;
    }

    // initByAppointedTrustNoAndMouth
    @Override
    public R initByAppointedTrustNoAndMouth(TenantEscrowAuthorizationInfoDto tenant, int mouth) {
        log.info("initByAppointedTrustNoAndMouth:OutSourceMailServiceImpl参数tenant={}，mouth={}",JSON.toJSONString(tenant),mouth);
        String date = LocalDate.now().minusMonths(mouth).format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
        String flag = "InitData";
        updateDataByEmail(date,flag,tenant);
        return R.ok();
    }

    @Override
    public R updateData20min(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData20min(TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateData1h(List<TenantEscrowAuthorizationInfoDto> data) {
        return null;
    }

    @Override
    public R updateSingleData1h(TenantEscrowAuthorizationInfoDto tenant) {
        return null;
    }

    @Override
    public R updateDataCJ(String date,String flag,TenantEscrowAuthorizationInfoDto tenant) {

        /*log.info("使用邮件进行数据初始化 tenant={},date={},flag={}",JSON.toJSONString(tenant),date,flag);
        try {
            TenantEmailAuthorizationInfoEntity emailConfig = tenantEmailAuthorizationInfoService.queryByTenantName(tenant.getTenantName(), tenant.getTrustNo());
            log.info("updateDataCJ:tenant={},邮件信息为{}",JSON.toJSONString(tenant),JSON.toJSONString(emailConfig));

            String path = MailUtil.getMail(emailConfig, date);
            String filePath;
            if(StringUtils.isNotBlank(date)){
                filePath = emailConfig.getDirFilePath()
                        + File.separator
                        + date;
            }else{
                filePath = emailConfig.getDirFilePath()
                        + File.separator
                        + new SimpleDateFormat("yyyyMMdd").format(new Date());
            }
            MailUtil.unRar(new File(path),filePath);
            File file = new File(filePath);
            if(!file.exists()||file.length()==0||file==null){
                file.mkdirs();
            }
            if(StringUtils.isNotBlank(flag)){
                getAllData(tenant,file,flag);
            }else{
                getUpdateData(tenant, file, flag);
            }
        } catch (Exception e) {
            log.error("使用邮件进行数据初始化发生异常",e);
        }
        log.info("使用邮件进行数据初始化结束:");
        return R.ok("使用邮件进行数据初始化结束！");*/
        return R.ok();
    }

    public static final String File_Type_RAR = "rar";
    public static final String File_Type_ZIP = "zip";

    /**
     *
     * @param date 查找邮件开始时间,为空默认当天
     * @param flag 不为 blank： 进行初始化。为blank:进行日常更新
     * @param tenant
     * @return
     */
    public String updateDataByEmail(String date, String flag, TenantEscrowAuthorizationInfoDto tenant) {
        if(StringUtils.isBlank(date)){
            date = LocalDate.now().minusYears(1L).format(DateTimeFormatter.ofPattern(DEFAULT_PATTERN));
        }
        log.info("使用邮件进行数据初始化 tenant={},date={},flag={}",JSON.toJSONString(tenant),date,flag);
        try {
            List<TenantEmailAuthorizationInfoEntity> tenantEmailAuthorizationInfoEntities = tenantEmailAuthorizationInfoService.queryByTenantName(tenant.getTenantName(), tenant.getTrustNo());
            log.info("email：tenantName{}，trustNo={}时，查询出邮件授权结果：{}", tenant.getTenantName(), tenant.getTrustNo(), tenantEmailAuthorizationInfoEntities);
            if (CollectionUtils.isEmpty(tenantEmailAuthorizationInfoEntities)) {
                return "";
            }
            // 遍历邮件配置
            for (TenantEmailAuthorizationInfoEntity emailConfig : tenantEmailAuthorizationInfoEntities) {
                String allPurpose = EmailConfigPurposeEnum.ALL.getPurpose();
                String fundValuePurpose = EmailConfigPurposeEnum.FUND_VALUE.getPurpose();
                log.info("邮件配置purpose={}", emailConfig.getPurpose());
                if(!allPurpose.equals(emailConfig.getPurpose()) && !fundValuePurpose.equals(emailConfig.getPurpose())){
                    log.info("邮件配置{},purpose不为all或fundValue,跳过",JSON.toJSONString(emailConfig));
                    continue;
                }
                log.info("updateDataByEmail:tenant={},邮件信息为{}",JSON.toJSONString(tenant),JSON.toJSONString(emailConfig));
                if(StringUtils.isBlank(emailConfig.getDirFilePath())){
                    setDefaultEmailFilePath(tenant,emailConfig);
                    log.info("没有配置邮件附件下载地址，默认下载到{}",emailConfig.getDirFilePath());
                }
                // 下载txt文件到/filePath/ABDsentdate/目录下 其他文件到/filePath目录下 filePath为config对象的参数
                List<Message> mail;
                try {
                    mail = MailUtil.getMail(emailConfig, date);
                } catch (Exception e) {
                    log.error("当前邮件配置：{}，获取邮件并下载附件异常", JSON.toJSONString(emailConfig), e);
                    continue;
                }
                if (CollectionUtils.isEmpty(mail)) {
                    continue;
                }
                File dirFile = new File(emailConfig.getDirFilePath());
                //整理RAR文件名称
//                MailUtil.handleRARFile(dirFile);
                if (allPurpose.equals(emailConfig.getPurpose())) {
                    log.info("当前配置为TA解析：" + JSON.toJSONString(emailConfig));
                    String[] list = dirFile.list();
                    if (list == null) {
                        log.info("当前配置文件下载路径配置有误！配置为：" + JSON.toJSONString(emailConfig));
                        continue;
                    }
                    List<String> paths = Arrays.stream(list).map(item-> emailConfig.getDirFilePath() + File.separator + item).collect(Collectors.toList());
                    log.info("排序前paths为{}",paths);
                    paths = paths.stream().sorted().collect(Collectors.toList());
                    log.info("排序后paths为{}",paths);
                    for (String path : paths) {
                        File file;
                        try{
                            String filePath = StringUtils.substringBeforeLast(path,DOT);
                            String fileType = StringUtils.substringAfterLast(path, DOT);
                            if (File_Type_RAR.equalsIgnoreCase(fileType)){
                                log.info("rar:path={}，filePath={}",path,filePath);
                                MailUtil.unRar(new File(path),filePath);
                            } else if (File_Type_ZIP.equalsIgnoreCase(fileType)) {
    //                            String filename = StringUtils.substringAfterLast(filePath,File.separator);
    //                            filePath =emailConfig.getDirFilePath() + File.separator + "ABD" + filename.substring(0,8);
                                log.info("zip:path={}，targetDir={}", path, filePath);
                                UnZipFile.unZipFiles(path, filePath);
                            } else {
                                log.info("下载的当前文件：{}不是压缩文件，TA解析跳过", path);
                                continue;
                            }
                            String lastDir = FileUtil.findLastDir(filePath);
                            log.info("最底层文件夹:{}", lastDir);
                            File tarFile = new File(lastDir);
                            log.info("tarFile:{},space:{}", tarFile.getName(), tarFile.getTotalSpace());
                            String[] tarExtension = {"txt", "TXT", "Txt"};
                            //最底层文件夹所有文件
                            Collection<File> files = FileUtils.listFiles(tarFile, tarExtension, true);
                            for (File file1 : files) {
                                try {
                                    File file2 = new File(
                                            StringUtils.substringBeforeLast(file1.getAbsolutePath(), "/")
                                                    + "/" + StringUtils.substringAfterLast(file1.getAbsolutePath(), "/").toLowerCase());
                                    file1.renameTo(file2);
                                } catch (Exception e) {
                                    log.error("文件名转为小写异常!", e);
                                }
                            }
                            file = new File(lastDir);
                            if(!file.exists() || file.length() == 0){
                                continue;
                            }
                            //没有实际文件
                            if(file.list() == null || Objects.requireNonNull(file.list()).length < 1){
                                continue;
                            }
                        } catch (Exception e){
                            log.error("updateDataDaily文件路径为：{}，解压文件失败:", path, e);
                            continue;
                        }
                        try{
                            if(StringUtils.isNotBlank(flag)){
                                log.info("初始化一次：目录为{}",file.getAbsolutePath());
                                String[] filenameList = file.list();
                                if(filenameList == null || filenameList.length == 0){
                                    log.info("tenantName{},trustNo:{},筛选后文件为空！", tenant.getTenantName(), tenant.getTrustNo());
                                    continue;
                                }
                                long all = Arrays.stream(filenameList).filter(item -> item.toLowerCase().contains("_all")).count();
                                if(all < 1L){
                                    log.info("tenantName{},trustNo:{},筛选后含有_all文件为空！", tenant.getTenantName(), tenant.getTrustNo());
                                    continue;
                                }
                                getAllData(tenant,file,flag);
                                flag = null;
                            }else{
                                log.info("更新一次，目录为{}",file.getAbsolutePath());
                                getUpdateData(tenant, file, flag);
                            }
                        } catch (Exception e) {
                            log.error("解析文件夹：{}下TA文本文件异常", file, e);
                        }
                    }
                // 目前发现只有海通的是符合下面逻辑，其余不符合，走各自实现类下面的解析逻辑
                } else if (fundValuePurpose.equals(emailConfig.getPurpose()) && DaasTrustNoEnum.HTSC.getCode().equals(emailConfig.getTrustNo())) {
                    log.info("当前配置为估值表解析：" + JSON.toJSONString(emailConfig));
                    String[] list = dirFile.list();
                    if (list == null) {
                        log.info("当前配置文件下载路径配置有误！配置为：" + JSON.toJSONString(emailConfig));
                        continue;
                    }
                    List<String> paths = Arrays.stream(list)
                            .filter(item -> StringUtils.isNotBlank(item) && (item.contains(".xlsx") || item.contains(".xls")))
                            .map(item-> emailConfig.getDirFilePath() + File.separator + item)
                            .collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(paths)) {
                        log.info("当前邮件配置获取的邮件中没有估值表解析文件，托管配置为：" + JSON.toJSONString(emailConfig));
                        continue;
                    }
                    try {
                        handleFundValueByFile(paths, tenant);
                    } catch (Exception e) {
                        log.error("估值表解析异常", e);
                    }
                }

                // 当前下载过文件的文件夹修改名称
                File oldFile = new File(emailConfig.getDirFilePath());
                String newFileName;
                int fileNum = 1;
                File newFile;
                while (true) {
                    newFileName = emailConfig.getDirFilePath() + "_" + LocalDate.now() + "_" + fileNum;
                    newFile = new File(newFileName);
                    if (newFile.exists()) {
                        fileNum++;
                        continue;
                    }
                    if (oldFile.renameTo(newFile)) {
                        break;
                    }
                }
            }
//            log.info("OutSourceMailServiceImpl 开始处理processFundValueTableAndFundNetValueByEmail");
//
//            int loopTime = 1;
//            if(StringUtils.isNotBlank(flag) || StringUtils.isBlank(date)){
//                loopTime = 12;
//            }
//            // 2.根据邮件附件落fund_value_table, fune_net_value_info
//            processFundValueTableAndFundNetValueByEmail(tenant,tenant.getTrustNo(),loopTime);
        } catch (Exception e) {
            log.error("使用邮件进行数据初始化发生异常",e);
            return "AUTO";
        }
        log.info("使用邮件进行数据初始化结束:");
        return null;
    }


    /**
     * 估值表代码解析整理（新）
     * @param filePathList 估值表文件路径集合
     * @param tenant 托管信息
     */
    public void handleFundValueByFile(List<String> filePathList, TenantEscrowAuthorizationInfoDto tenant) {
        log.info("解析下载的估值表附件，文件为：{}, 当前托管信息为:{}", JSON.toJSONString(filePathList), JSON.toJSONString(tenant));
        String fileName;
        // origin_value - key_str
        Map<String, String> typeOfFundValuation = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_FUND_VALUATION, tenant.getTrustNo());
        // key_str - value
        Map<String, String> fundValuationMap = typeOfFundValuationService.queryKeyValue();
        for (String filePath : filePathList) {
            try {
                File file = new File(filePath);
                if (!file.exists()) {
                    log.info("估值表文件：{}不存在", filePath);
                    continue;
                }
                fileName = file.getName();
                // 开始解析excel
                Workbook workbook;
                try {
                    if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
                        workbook = new XSSFWorkbook(new FileInputStream(file));
                    } else if (fileName.matches("^.+\\.(?i)(xls)$")) {
                        workbook = new HSSFWorkbook(new FileInputStream(file));
                    } else {
                        log.info("当前文件非excel:" + filePath);
                        continue;
                    }
                } catch (IOException e) {
                    log.error("file获取输入流异常！", e);
                    continue;
                }
                Sheet sheet = workbook.getSheetAt(0);
                FundValueEmailDTO fundValueEmailDTO = parseFundValueExcel(sheet, fileName, typeOfFundValuation, fundValuationMap);
                log.info("fundValueEmailDTO:{}",fundValueEmailDTO);
                FundNetValueInfoEntity fundNetValueInfo = fundValueEmailDTO.getFundNetValueInfoEntity();
                fundNetValueInfo.setAdmin(tenant.getTenantName());
                fundNetValueInfo.setTrustNo(tenant.getTrustNo());
                fundNetValueInfo.setUpdateTime(new Date());
                //更新资产合计
                log.info("邮件解析{}更新资产合计:{}", tenant.getTrustNo(),fundNetValueInfo);
                fundNetValueInfoService.updateTotalAsset(fundNetValueInfo);
                //更新估值表
                List<FundValueTableDataInfoEntity> fundValueTableDataInfoList = fundValueEmailDTO.getFundValueTableDataInfoEntity();
                if (!CollectionUtils.isEmpty(fundValueTableDataInfoList)){
                    for (FundValueTableDataInfoEntity entity: fundValueTableDataInfoList
                    ) {
                        entity.setAdmin(tenant.getTenantName());
                        entity.setTrustNo(tenant.getTrustNo());
                        entity.setCreateTime(new Date());
                        entity.setUpdateTime(new Date());
                    }
                }
                fundValueTableDataInfoService.saveData(null,fundValueTableDataInfoList);
                // fundValuation
                List<FundValuationEntity> fundValuationEntityList = fundValueEmailDTO.getFundValuationEntityList();
                if (!CollectionUtils.isEmpty(fundValuationEntityList)){
                    for (FundValuationEntity entity: fundValuationEntityList
                    ) {
                        entity.setAdmin(tenant.getTenantName());
                        entity.setTrustNo(tenant.getTrustNo());
                        entity.setCreateTime(new Date());
                        entity.setUpdateTime(new Date());
                    }
                }
                fundValuationService.saveData(null, fundValuationEntityList);
            } catch (Exception e) {
                log.error("当前文件：{}，解析异常", filePath, e);
            }
        }
    }


    @Autowired
    MailNewUtils mailNewUtils;

    /**
     * 邮件主题eg： 20221013通怡明曦2号私募证券投资基金估值表
     * @param tenant
     * @param trustNo
     * @param loopNum
     */
    private void processFundValueTableAndFundNetValueByEmail(TenantEscrowAuthorizationInfoDto tenant, String trustNo, int loopNum) {
        log.info("processFundValueTableAndFundNetValueByEmail入参tenant={},trustNo={},loopNum={}",tenant,trustNo,loopNum);
        List<TenantEmailAuthorizationInfoEntity> tenantEmailAuthorizationInfoEntities = tenantEmailAuthorizationInfoService.queryByTenantName(tenant.getTenantName(), tenant.getTrustNo());
        log.info("processFundValueTableAndFundNetValueByEmail 查到的邮件配置有：{}",JSON.toJSONString(tenantEmailAuthorizationInfoEntities));
        for (TenantEmailAuthorizationInfoEntity tenantEmail : tenantEmailAuthorizationInfoEntities) {
            //只要更新估值表的邮件配置数据
            String purpose = EmailConfigPurposeEnum.ALL.getPurpose();
            log.info("enum:all:purpose={},邮件配置purpose={}",purpose,tenantEmail.getPurpose());
            if(purpose.equals(tenantEmail.getPurpose())){
                log.info("processFundValueTableAndFundNetValueByEmail:跳过配置：{}",JSON.toJSONString(tenantEmail));
                continue;
            }
            if (!ObjectUtils.isEmpty(tenantEmail)) {
                try {
                    log.info("processFundValueTableAndFundNetValueByEmail 确认邮箱：tenantEmail={}",JSON.toJSONString(tenantEmail));
                    //获取邮件
                    LocalDate localDate = LocalDate.now();
                    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                    String startTime = dateTimeFormatter.format(localDate.minusMonths(loopNum));
                    //拿到所有邮件
                    //Message[] weMessage = MailUtil.getWEMessage(tenantEmail.getEmailHost(), tenantEmail.getEmailAddress(), tenantEmail.getEmailSecret(), ZhongXinConstants.PROTOCOL);
                    Message[] weMessage = MailUtil.getMessageByTenantEmail(tenantEmail);

                    mailNewUtils.printMessageInfo(weMessage,500);

                    //过滤符合条件的邮件
                    List<Message> messages = MailUtil.filterMessage(weMessage,
                            tenantEmail.getFromEmail(),
                            startTime,
                            tenantEmail.getEmailSubject(),
                            Boolean.TRUE);
                    //打印邮件相关信息 并且更新（ todo ）
                    if(!CollectionUtils.isEmpty(messages)){
                        log.info("processFundValueTableAndFundNetValueByEmail_拿到的messages数量为{}",messages.size());


                        //生产且没有配置附件路径 就不保存
                        Profiles profiles = Profiles.of(OFFICIAL_PROFILES);
                        boolean isOfficial = env.acceptsProfiles(profiles);
                        String dirFilePath = tenantEmail.getDirFilePath();
                        if(StringUtils.isBlank(dirFilePath) && isOfficial){
                            log.info("生产环境且没有配置路径，不报错附件！");
                        }else{
                            if(StringUtils.isBlank(dirFilePath)){
                                dirFilePath = mailNewUtils.getDefaultAttachmentParentPath(tenantEmail);
                            }
                        }
                        for (Message message : messages) {
                            if (StringUtils.isNotBlank(dirFilePath)) {
                                mailNewUtils.saveAttachment(message, dirFilePath);
                            }
                        }
                        for (Message message : messages) {
                            try {
                                MailUtil re = new MailUtil((MimeMessage) message);
                                handleFundValueEmailMessage(message, tenant, re.getSubject());
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                    }else{
                        log.error("OutSourceMailServiceImpl processFundValueTableAndFundNetValueByEmail 过滤后messages信息为空");
                    }
                } catch (ParseException pe) {
                    pe.printStackTrace();
                    log.error("时间转化异常！", pe);
                    MailNewUtils.saveMailFailureLog(tenant.getTenantName(),trustNo,"时间转化异常！"+pe);
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                    log.error("分析邮件异常！", ioe);
                    MailNewUtils.saveMailFailureLog(tenant.getTenantName(),trustNo,"分析邮件异常！"+ioe);
                } catch (MessagingException me) {
                    me.printStackTrace();
                    log.error("获取邮件异常！", me);
                    MailNewUtils.saveMailFailureLog(tenant.getTenantName(),trustNo,"获取邮件异常！"+me);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("更新中信totalAsset异常！", e);
                    MailNewUtils.saveMailFailureLog(tenant.getTenantName(),trustNo,"更新totalAsset异常！"+e);
                }
            }
        }
    }

    public static final String[]  OFFICIAL_PROFILES= {"prod","ty-prod"};

    @Autowired
    public Environment env;

    @Value("${file.parentPath.realPath}")
    private String realPath;

    public  void printMailInfo(Message message, String filePath, TenantEscrowAuthorizationInfoDto tenant) throws IOException, MessagingException {
        MailUtil re;

        if(StringUtils.isBlank(filePath)){
            filePath = realPath
                    + "email_fund_value" + File.separator
                    + tenant.getTenantName() + File.separator
                    + tenant.getTrustNo() + File.separator;
        }

        re = new MailUtil((MimeMessage) message);
        log.info("邮件主题:" + re.getSubject());
        log.info("邮件是否包含附件:" + re.isContainAttach(message));
        log.info("邮件发送人地址:" + re.getFrom());
        re.getMailContent(message);
        // todo 原来是注解 ,这是保存附近到本地的方法
        Profiles profiles = Profiles.of(OFFICIAL_PROFILES);
        boolean isOfficial = env.acceptsProfiles(profiles);

        if(!isOfficial){
            re.setAttachPath(filePath);
            re.saveAttachMent(message, null);
        }

    }

    public static final Pattern pattern = Pattern.compile("[^\\u4e00-\\u9fa5]+");

    /**
     * 这里要改
     *
     * @param part
     * @throws MessagingException
     * @throws IOException
     */
    public void handleEmailMessage(Part part, TenantEscrowAuthorizationInfoDto tenant, String subject) throws MessagingException, IOException, ParseException {
        log.info("OutSourceMailServiceImpl:handleEmailMessage:tenant={},subject={}",JSON.toJSONString(tenant),subject);
        String fileName;
        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            BodyPart mPart;
            for (int i = 0; i < mp.getCount(); i++) {
                try{
                    mPart = mp.getBodyPart(i);
                    fileName = mPart.getFileName();
                    // eg:SEL682_林园投资41号私募投资基金_2022-11-29估值表.xls
                    if ((fileName != null)) {
                        fileName = MailUtil.decodeText(fileName);
                        log.info("temp:subject={}",subject);
                        String date = StrUtil.getDateStrFromStringByPattern(subject, MailUtil.DATE_PATTERN);
                        log.info("fileName:{}", fileName);
                        //fundCode
                        String fundCode = fileName.substring(0, fileName.indexOf("_"));

                        //date
                        String suffixName = StringUtils.substringAfterLast(fileName, "_");
                        String fundNetDate = StringUtils.substringBefore(suffixName, OutsourceHaiTongServiceImpl.NET_VALUE_TABLE);
                        String valueDate = fundNetDate.replace("-", "");
                        //取前一天日期
                        //valueDate = minusDays(valueDate,DEFAULT_PATTERN,1);

                        //fundName
                        String fundNameWithPreffix = StringUtils.substringBeforeLast(fileName, "_");
                        String fundName = StringUtils.substringAfter(fundNameWithPreffix, "_");

                        Workbook workbook = ExcelWriteUtil.getWorkbook(mPart.getInputStream());
                        Sheet sheetAt = workbook.getSheetAt(0);
                        boolean flag = false;
                        int rowNum = 0;
                        List<FundValueTableDataInfoEntity> entities = new ArrayList<>();
                        for (Row row : sheetAt) {
                            rowNum ++;
                            try{
                                if(Objects.isNull(row) || Objects.isNull(row.getCell(0))){
                                    flag = false;
                                    continue;
                                }
                                if(row.getCell(0).getCellTypeEnum().equals(CellType.STRING) && OutsourceHaiTongServiceImpl.START_ROW_FLAG.equals(ExcelUtils.getStringValue(row.getCell(0)))){
                                    flag = true;
                                    continue;
                                }

                                //更新数据 fundNetValueInfo 更新资产合计
                                if (ExcelUtils.getStringValue(row.getCell(0)).contains(OutsourceHaiTongServiceImpl.TOTAL_ASSERT_ROW)) {
                                    Cell cell = row.getCell(7);
                                    String stringCellValue = ExcelUtils.getStringValue(cell);

                                    FundNetValueInfoEntity build = FundNetValueInfoEntity.builder()
                                            .totalAsset(StringUtils.isBlank(stringCellValue) ? null : new BigDecimal(stringCellValue))
                                            .updateTime(new Date())
                                            .trustNo(tenant.getTrustNo())
                                            .admin(tenant.getTenantName())
                                            .fundCode(fundCode)
                                            .netValueDate(valueDate)
                                            .build();

                                    log.info("OutSourceMailServiceImpl 更新资产合计字段{}",JSON.toJSONString(build));

                                    fundNetValueInfoService.updateTotalAsset(build);
                                }

                                //更新数据 fundValueDataInfo
                                if(flag){
                                    String cellx0 = ExcelUtils.getStringValue(row.getCell(0));
                                    boolean matches = pattern.matcher(cellx0).matches();
                                    if(!matches){
                                        log.info("该行第一个单元格内容为{},含有中文，跳过查询下一行",cellx0);
                                        flag = false;
                                        continue;
                                    }

                                    if(StringUtils.isBlank(cellx0)){
                                        log.info("该行第一个单元格内容为空,含有中文，跳过查询下一行",cellx0);
                                        flag = false;
                                        continue;
                                    }

                                    char keyChar = 'a';
                                    HashMap<Character,String> dataMap = new HashMap<>();
                                    for (int j = 0; j < 11; j++) {
                                        Cell cell = row.getCell(j);
                                        String stringValue = ExcelUtils.getStringValue(cell);
                                        dataMap.put(keyChar,stringValue);
                                        keyChar ++;
                                    }
                                    log.info("国金道富估值表邮件解析第{}行，拿到的内容{}",rowNum,JSON.toJSONString(dataMap));

                                    FundValueTableDataInfoEntity build = FundValueTableDataInfoEntity.builder()
                                            .fundCode(fundCode)
                                            .fundName(fundName)
                                            .valueDate(valueDate)
                                            .kmCode(StringUtils.isBlank(dataMap.get('a'))?null:dataMap.get('a'))
                                            .kmName(StringUtils.isBlank(dataMap.get('b'))?null:dataMap.get('b'))
                                            .currency("156")
                                            .amount(StringUtils.isBlank(dataMap.get('c'))?null:new BigDecimal(dataMap.get('c')))  //  c列
                                            .perCost(StringUtils.isBlank(dataMap.get('d'))?null:new BigDecimal(dataMap.get('d')))  // d列
                                            .portCost(StringUtils.isBlank(dataMap.get('e'))?null:new BigDecimal(dataMap.get('e')))  // e列
                                            .costBi(StringUtils.isBlank(dataMap.get('f'))?null:new BigDecimal(dataMap.get('f')))  // f列
                                            .vapPrice(StringUtils.isBlank(dataMap.get('g'))?null:new BigDecimal(dataMap.get('g')))  // g列
                                            .portMv(StringUtils.isBlank(dataMap.get('h'))?null:new BigDecimal(dataMap.get('h')))  // h列
                                            .mvBl(StringUtils.isBlank(dataMap.get('i'))?null:new BigDecimal(dataMap.get('i')))  // i列
                                            .portIv(StringUtils.isBlank(dataMap.get('j'))?null:new BigDecimal(dataMap.get('j')))  // j列
                                            .suspension(StringUtils.isBlank(dataMap.get('k'))?null:dataMap.get('k'))  // k列
                                            .trustNo(tenant.getTrustNo())
                                            .admin(tenant.getTenantName())
                                            .updateTime(new Date())
                                            .build();

                                    log.info("拿到的fundValueTableDataInfoEntity为{}",JSON.toJSONString(build));

                                    entities.add(build);
                                }
                            }catch (Exception e){
                                log.error("国金道富估值表邮件解析第{}行异常,尝试解析下一行",rowNum,e);

                                continue;
                            }
                        }
                        if(!CollectionUtils.isEmpty(entities)){
                            log.info("从subject:{}中获取fundValueTableData 共计{}条",subject,entities.size());
                            fundValueTableDataInfoService.saveData(null,entities);
                        }else{
                            log.error("从subject:{}中未获得fundValueTableData",subject);
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    continue;
                }

            }
        }
    }

    public void handleFundValueEmailMessage(Part part, TenantEscrowAuthorizationInfoDto tenant, String subject) throws MessagingException, IOException, ParseException {
        log.info("处理邮件 handleFundValueEmailMessage tenant={} subject={}, trustNo={}",JSON.toJSONString(tenant),subject);
        String fileName;
        // origin_value - key_str
        Map<String, String> typeOfFundValuation = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_FUND_VALUATION, tenant.getTrustNo());
        // key_str - value
        Map<String, String> fundValuationMap = typeOfFundValuationService.queryKeyValue();

        if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            BodyPart mPart;
            for (int i = 0; i < mp.getCount(); i++) {
                try{
                    mPart = mp.getBodyPart(i);
                    fileName = mPart.getFileName();
                    if ((fileName != null)) {
                        fileName = MailUtil.decodeText(fileName);
                        HSSFWorkbook hssfWorkbook = new HSSFWorkbook(mPart.getInputStream());
                        HSSFSheet sheet = hssfWorkbook.getSheetAt(0);
                        FundValueEmailDTO fundValueEmailDTO = parseFundValueExcel(sheet, fileName, typeOfFundValuation, fundValuationMap);
                        log.error("fundValueEmailDTO:{}",fundValueEmailDTO);
                        FundNetValueInfoEntity fundNetValueInfo = fundValueEmailDTO.getFundNetValueInfoEntity();
                        fundNetValueInfo.setAdmin(tenant.getTenantName());
                        fundNetValueInfo.setTrustNo(tenant.getTrustNo());
                        fundNetValueInfo.setUpdateTime(new Date());
                        //更新资产合计
                        log.error("邮件解析{}更新资产合计:{}", tenant.getTrustNo(),fundNetValueInfo);
                        fundNetValueInfoService.updateTotalAsset(fundNetValueInfo);

                        //更新估值表
                        List<FundValueTableDataInfoEntity> fundValueTableDataInfoList = fundValueEmailDTO.getFundValueTableDataInfoEntity();

                        if (!CollectionUtils.isEmpty(fundValueTableDataInfoList)){
                            for (FundValueTableDataInfoEntity entity: fundValueTableDataInfoList
                            ) {
                                entity.setAdmin(tenant.getTenantName());
                                entity.setTrustNo(tenant.getTrustNo());
                                entity.setCreateTime(new Date());
                                entity.setUpdateTime(new Date());
                            }
                        }
                        fundValueTableDataInfoService.saveData(null,fundValueTableDataInfoList);

                        // fundValuation
                        List<FundValuationEntity> fundValuationEntityList = fundValueEmailDTO.getFundValuationEntityList();
                        if (!CollectionUtils.isEmpty(fundValuationEntityList)){
                            for (FundValuationEntity entity: fundValuationEntityList
                            ) {
                                entity.setAdmin(tenant.getTenantName());
                                entity.setTrustNo(tenant.getTrustNo());
                                entity.setCreateTime(new Date());
                                entity.setUpdateTime(new Date());
                            }
                        }
                        fundValuationService.saveData(null, fundValuationEntityList);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    log.error("处理估值表邮件失败!", e);
                }
            }
        }
    }

    /**
     * 估值表解析
     * @param sheet
     * @param fileName
     * @param typeOfFundValuation origin_value - key_str
     * @param fundValuationMap key_str - value
     * @return
     */
    public FundValueEmailDTO parseFundValueExcel(Sheet sheet, String fileName, Map<String, String> typeOfFundValuation, Map<String, String> fundValuationMap) {
        String fundName = null;
        String fundCode = null;
        String fundValueDate = null;
        BigDecimal totalAsset = new BigDecimal(0);
        FundValueEmailDTO result = new FundValueEmailDTO();
        int LAST_ROW_OF_SUBJECT_CODE = outsourceZhongXinService.getLastRowOfSubjectCode(sheet);
        List<FundValueTableDataInfoEntity> fundValueTableDataInfoEntityList = new ArrayList<>();
        List<FundValuationEntity> fundValuationEntityList = new ArrayList<>();
        Pattern yyyyMMddPattern = Pattern.compile(YEAR_MONTH_DAY_REGEX_WITH_SEPARATOR);

        //通过文件名获取基金编码,估值日期  SVH298_凌顶揽月一号私募证券投资基金_2023-03-28估值表.xls
        Matcher matcher = yyyyMMddPattern.matcher(fileName);
        if (matcher.find()) {
            fundValueDate = matcher.group().replaceAll("-", "");
        } else {
            log.error("邮件解析上游excel文件名格式变化fundValueDate无法解析，fundValueDate:{}", fileName);

        }
        if (fileName.contains("_")) {
            String[] strings = fileName.trim().split("_");
            fundCode = strings[0];
            fundName = strings[1];
        } else {
            log.error("邮件解析上游excel文件名格式变化fundCode/fundName无法解析，fundCode:{}", fileName);
        }
        for (int rowNum=0; rowNum <=sheet.getLastRowNum(); rowNum++){
            Row sheetRow = sheet.getRow(rowNum);
            if (sheetRow == null){
                continue;
            }
            for (int cellNum = 0; cellNum <= sheetRow.getLastCellNum(); cellNum++) {
                Cell cell = sheetRow.getCell(cellNum);
                if (cell == null){
                    continue;
                }
                //获取资产合计
                if (TOTAL_ASSERT_ROW_WITH_COLON.equals(getValue(cell))) {
                    Cell totalAssetCell = sheetRow.getCell(7);
                    if (totalAssetCell == null) {
                        log.error("邮件解析上游excel格式变化,资产合计无法解析，fundName:{}", fundName);
                    }else {
                        double totalAssetDouble = totalAssetCell.getNumericCellValue();
                        totalAsset = BigDecimalUtil.obj2BigDecimalTrunToZero(totalAssetDouble);
                    }
                }
                //解析估值表数据 获取A列非中文字段
                if (cell.getColumnIndex() == 0
                        && !CellType.BLANK.equals(cell.getCellTypeEnum())
                        && !"".equals(getValue(cell))
                        && cell.getRowIndex() > LAST_ROW_OF_SUBJECT_CODE) {
                    String kmCode = getValue(cell);
                    String kmName = sheetRow.getCell(1) != null ? getValue(sheetRow.getCell(1)) : null;
                    BigDecimal amount = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(2)));
                    BigDecimal perCost = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(3)));
                    BigDecimal portCost = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(4)));
                    BigDecimal costBi = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(5)));
                    BigDecimal vapPrice = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(6)));
                    BigDecimal portMv = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(7)));
                    BigDecimal mvBl = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(8)));
                    BigDecimal portIv = getBigDecimalFromCell(ExcelUtils.getStringValue(sheetRow.getCell(9)));
                    String suspension = sheetRow.getCell(10) != null ? getValue(sheetRow.getCell(10)) : null;

                    FundValueTableDataInfoEntity entity = FundValueTableDataInfoEntity.builder()
                            .fundCode(fundCode)
                            .fundName(fundName)
                            .valueDate(fundValueDate)
                            .kmCode(kmCode)
                            .kmName(kmName)
                            .currency("156")
                            .amount(amount)
                            .perCost(perCost)
                            .portCost(portCost)
                            .costBi(costBi)
                            .vapPrice(vapPrice)
                            .portMv(portMv)
                            .mvBl(mvBl)
                            .portIv(portIv)
                            .suspension(suspension)
                            .build();
                    fundValueTableDataInfoEntityList.add(entity);
                    // 新增估值表
                    //获取估值表kmCode映射值
                    String targetKmCode = MatchDataDictionaryKeyUtil.getKey(typeOfFundValuation, kmCode);
                    String targetKmName = fundValuationMap.get(targetKmCode);
                    if (StringUtils.isNotBlank(targetKmCode)) {
                        FundValuationEntity fundValuationEntity = FundValuationEntity.builder()
                                .fundCode(fundCode)
                                .fundName(fundName)
                                .valueDate(fundValueDate)
                                .kmCode(targetKmCode)
                                .kmName(targetKmName)
                                .currency("156")
                                .amount(amount)
                                .perCost(perCost)
                                .portCost(portCost)
                                .costBi(costBi)
                                .vapPrice(vapPrice)
                                .portMv(portMv)
                                .mvBl(mvBl)
                                .portIv(portIv)
                                .suspension(suspension)
                                .build();
                        fundValuationEntityList.add(fundValuationEntity);
                    }
                }
            }

        }
        FundNetValueInfoEntity fundNetValueInfo = FundNetValueInfoEntity.builder()
                .fundCode(fundCode)
                .totalAsset(totalAsset)
                .netValueDate(fundValueDate)
                .build();
        result.setFundNetValueInfoEntity(fundNetValueInfo);
        result.setFundValueTableDataInfoEntity(fundValueTableDataInfoEntityList);
        result.setFundValuationEntityList(fundValuationEntityList);
        return result;
    }

    private  String minusDays(String valueDate, String defaultPattern, int i) {
        log.info("minusDays:valueDate={},defaultPattern={},i={}",valueDate,defaultPattern,i);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(defaultPattern);
        LocalDate localDate = LocalDate.parse(valueDate,dateTimeFormatter );
        LocalDate localDate1 = localDate.minusDays(i);
        String format = dateTimeFormatter.format(localDate1);
        return format;
    }

    @Override
    public R updateNetValueData(List<TenantEscrowAuthorizationInfoDto> tenants) {
        return null;
    }

    @Override
    public R updateSingleNetValueData(TenantEscrowAuthorizationInfoDto tenant) {
//        log.info("使用邮件进行托管数据每8点、12点、20点更新开始,tenant={}",JSON.toJSONString(tenant));
//        String date = "20210101";
//        String flag = null;
//        List<TenantEmailAuthorizationInfoEntity> tenantEmailAuthorizationInfoEntities = tenantEmailAuthorizationInfoService.queryByTenantName(tenant.getTenantName(), tenant.getTrustNo());
//        for (TenantEmailAuthorizationInfoEntity emailConfig : tenantEmailAuthorizationInfoEntities) {
//            String purpose = EmailConfigPurposeEnum.ALL.getPurpose();
//            if(!purpose.equals(emailConfig.getPurpose())){
//                log.info("updateSingleNetValueData 邮件配置为{}，不为all",JSON.toJSONString(emailConfig));
//                continue;
//            }
//            if(StringUtils.isBlank(emailConfig.getDirFilePath())){
//                setDefaultEmailFilePath(tenant,emailConfig);
//            }
//            String trustNo = tenant.getTrustNo();
//            try {
//                MailUtil.getMail(emailConfig, date);
//                File dirFile = new File(emailConfig.getDirFilePath());
//                String[] list = dirFile.list();
//                List<String> paths = Arrays.stream(list).map(item-> emailConfig.getDirFilePath() + File.separator + item).collect(Collectors.toList());
//
//                log.info("排序前paths为{}",paths);
//                paths = paths.stream().sorted().collect(Collectors.toList());
//                log.info("排序后paths为{}",paths);
//                for (String path : paths) {
//                    File file = null;
//                    try{
//                        String filePath = StringUtils.substringBeforeLast(path,DOT);
//                        String fileType = StringUtils.substringAfterLast(path, DOT);
//                        if (File_Type_RAR.equalsIgnoreCase(fileType)) {
//                            log.info("rar:path={}，filePath={}",path,filePath);
//                            MailUtil.unRar(new File(path), filePath);
//                        }else if (File_Type_ZIP.equalsIgnoreCase(fileType)){
//                            String filename = StringUtils.substringAfterLast(filePath,File.separator);
//                            filePath =emailConfig.getDirFilePath() + File.separator + "ABD" + filename.substring(0,8);
//                            log.info("zip:path={}，targetDir={}",path,filePath);
//                            UnZipFile.unZipFiles(path,filePath);
//                        }
//                        String lastDir = FileUtil.findLastDir(filePath);
//                        log.info("最底层文件夹:{}", lastDir);
//                        File tarFile = new File(lastDir);
//                        log.info("tarFile:{},space:{}", tarFile.getName(), tarFile.getTotalSpace());
//                        String[] tarExtension = {"txt", "TXT", "Txt"};
//                        //最底层文件夹所有文件
//                        Collection<File> files = FileUtils.listFiles(tarFile, tarExtension, true);
//                        for (File file1 : files) {
//                            try {
//                                File file2 = new File(
//                                        StringUtils.substringBeforeLast(file1.getAbsolutePath(), "/")
//                                                + "/" + StringUtils.substringAfterLast(file1.getAbsolutePath(), "/").toLowerCase());
//                                file1.renameTo(file2);
//                            } catch (Exception e) {
//                                log.error("文件名转为小写异常!", e);
//                            }
//                        }
//                        file = new File(lastDir);
//                        if(!file.exists()||file.length()==0||file==null){
////                            file.mkdirs();
//                            continue;
//                        }
//                        //没有实际文件
//                        if(file.list() == null || file.list().length < 1){
//                            continue;
//                        }
//                    }catch (Exception e){
//                        log.error("updateDataDaily解压文件失败:",e);
//                        continue;
//                    }
//                    try{
//                        String version = tenantEmailVersionMapService.getVersionByTrustNo(trustNo);
//                        handlerVersionTxtService.processFundNetValueInfoData(tenant,file,trustNo,flag,version);
//                    }catch (Exception e){
//                        log.error("",e);
//                    }
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//        log.info("使用邮件进行托管数据每8点、12点、20点更新结束:");
        return R.ok();
    }

    @Override
    public DubboResult updateMJBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateMJSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateTGBalanceData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    @Override
    public DubboResult updateTGSeqData(TenantEscrowAuthorizationInfoDto tenant) {
        return DubboResult.newFailure(DubboResult.SERVER_EXCEPTION, "暂不支持");
    }

    private String getsSubStringTwo(String param){
        String afterParam = param.substring(param.length() - 2);
        String newParam = param.substring(0, param.length() - 2).replaceFirst("0*", "");
        if(StringUtils.isNotBlank(newParam)){
            param = newParam+"."+afterParam;
        }else{
            param = "0."+afterParam;
        }
        return param;
    }
    private String getSubStringEight(String param){
        String afterParam = param.substring(param.length() - 8);
        String newParam = param.substring(0, param.length() - 8).replaceFirst("0*", "");
        if(StringUtils.isNotBlank(newParam)){
            param = newParam+"."+afterParam;
        }else{
            param = "0."+afterParam;
        }
        return param;
    }
    private String getsSubStringFour(String param){
        String afterParam = param.substring(param.length() - 4);
        String newParam = param.substring(0, param.length() - 4).replaceFirst("0*", "");
        if(StringUtils.isNotBlank(newParam)){
            param = newParam+"."+afterParam;
        }else{
            param = "0."+afterParam;
        }
        return param;
    }
    private String getSubStringFive(String param){
        String afterParam = param.substring(param.length() - 5);
        String newParam = param.substring(0, param.length() - 5).replaceFirst("0*", "");
        if(StringUtils.isNotBlank(newParam)){
            param = newParam+"."+afterParam;
        }else{
            param = "0."+afterParam;
        }
        return param;
    }

    public String getString(int offSet, int lastSet, byte[] bytes){
        byte[] bytes1 = new byte[lastSet-offSet];
        for (int j = offSet; j < lastSet; j++) {
            bytes1[j - offSet] = bytes[j];
        }
        String s = null;
        try {
            s = new String(bytes1,"gbk").replace(" ","");
            s = new String(s.getBytes("UTF-8"),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return s;
    }


}
