package com.friday.custody.service.trustService.mailHandleService.multiVersionService.impl;

import com.alibaba.fastjson.JSON;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.entity.*;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.utils.*;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.service.basicService.DataDictionaryTypeCertificateCsdcService;
import com.friday.custody.service.basicService.TenantEmailFieldConfigService;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.trustService.gtja.utils.RandomStrUtil;
import com.friday.custody.service.trustService.mailHandleService.common.FieldConstants;
import com.friday.custody.service.trustService.mailHandleService.logicService.OutSourceMailServiceImpl;
import com.friday.custody.service.trustService.mailHandleService.multiVersionService.IHandlerTxtService;
import com.friday.custody.service.trustService.mailHandleService.util.ByteUtils;
import com.friday.custody.service.trustService.mailHandleService.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.friday.custody.service.trustService.mailHandleService.common.FieldConstants.FUND_OPEN_INFO_OPEN_TYPE_ZQ;

/**
 * @Description
 * @Author k0051745
 * @Date: 2022/11/21
 */
@Service
@Slf4j
public class HandlerVersionTxtServiceImpl implements IHandlerTxtService {

    @Autowired
    private FundInfoServiceImpl fundInfoService;//a

    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryTypeCertificateCsdcService certificateCsdcService;
    @Autowired
    private TenantEmailFieldConfigService tenantEmailFieldConfigService;
    @Autowired
    private InvestorInfoServiceImpl investorInfoService;//b
    @Autowired
    private InvestorBankInfoServiceImpl investorBankInfoService;//b
    @Autowired
    private CustShareDetailInfoServiceImpl custShareDetailInfoService;
    @Autowired
    private DataDictionarySellerServiceImpl sellerService;
    @Autowired
    private FundTradeInfoServiceImpl fundTradeInfoService;//i
    @Autowired
    private CustShareSeqInfoServiceImpl custShareSeqInfoService;
    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c
    @Autowired
    private CustShareInfoServiceImpl custShareInfoService;//d
    @Autowired
    private FundProfitInfoServiceImpl fundProfitInfoService;
    @Autowired
    OutSourceMailServiceImpl outSourceMailService;
    @Autowired
    FundOpenInfoServiceImpl fundOpenInfoService;
    @Autowired
    DataDictionaryOpenStateServiceImpl openStateService;


    @Override
    public IHandlerTxtService getHandlerTxtService(String version) {
        return null;
    }

    /**
     * 全量更新
     *  @param tenant
     * @param file
     * @param flag
     * @param version
     */
    @Override
    public void getAllData(TenantEscrowAuthorizationInfoDto tenant, File file, String flag, String version) {

        String trustNo = tenant.getTrustNo();
        String filename = "";
        if(file!=null){
            filename = file.getAbsolutePath();
        }
        log.info("HandlerVersionTxtServiceImpl:getAllData:tenant={},file={}，flag={},version={}",
                JSON.toJSONString(tenant),
                filename,
                flag,
                version);
        try{
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, file, trustNo, flag,version);//end
            //2 基金出资人信息表（investor_info）
            processInvestorInfoData(tenant, file, trustNo,flag,version);//end
            //2 基金出资人信息表（investeor_bank_info）
            processInvestorBankInfoData(tenant, file, trustNo,flag,version);//end
            //4 基金持有信息表（cust_share_detail_info）
            processCustShareDetailInfoData(tenant,file, trustNo,flag,version);//end
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, file,trustNo, flag,version);//end
            //17 托管⼾流⽔表（custShare_seq_info）
            processCustShareSeqInfoData(tenant,file, trustNo, flag,version);//end
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, file,trustNo, flag,version);//end
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, file,trustNo, flag,version);//end
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant,file, trustNo,flag,version);//end
            // 开放日信息表(fund_open_info)
            processFundOpenInfoData(tenant, file, trustNo, flag, version);

        }catch (Exception e){
            log.error("",e);
        }
    }

    public static final String FUND_OPEN_INFO_PREFIX = "FundOpenDay_";

    private void processFundOpenInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            filePath = file.getAbsolutePath() + File.separator + FUND_OPEN_INFO_PREFIX.toLowerCase() + date + ".txt";
            log.info("processFundOpenInfoData需要读取文件：{}", filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if (!CollectionUtils.isEmpty(bytes)) {
                List<FundOpenInfoEntity> entities = getFundOpenInfo(bytes, tenant, trustNo, version, FUND_OPEN_INFO_PREFIX);
                log.info("读取文件{} processFundOpenInfoData获取数据量为{}",filePath, entities.size());

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

    private List<FundOpenInfoEntity> getFundOpenInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo, String version, String fundOpenInfoPrefix) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version, fundOpenInfoPrefix);

        Map<String, String> typeOfOpenDayDic = null;
        Map<String, Map<String, String>>  openStatusDic = null;
        try {
            typeOfOpenDayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_OPEN_DAY_SERVICE, "54");
            openStatusDic = openStateService.queryOpenStateWithDetail("54");
            log.info("getFundOpenInfo 字典映射:开放状态={}",JSON.toJSONString(openStatusDic));
        }catch (Exception e){
            log.error("getFundOpenInfo获取数据字典异常!", e);
        }

        List<FundOpenInfoEntity> result = new ArrayList<>();
        List<TenantEmailFieldConfigEntity> finalConfigEntities = configEntities;
        Map<String, String> finalTypeOfOpenDayDic = typeOfOpenDayDic;
        Map<String, Map<String, String>> finalOpenStatusDic = openStatusDic;
        for (byte[] e : bytes) {
            try {
                FundOpenInfoEntity entity = new FundOpenInfoEntity();
                String fundOpenDateBegin = "";
                String fundOpenDateEnd = "";
                String openType = "";
                String openStatus = "";
                for (TenantEmailFieldConfigEntity configEntity : finalConfigEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);
                    switch (targetField) {
                        case FieldConstants.FUND_OPEN_INFO_FUND_CODE:
                            String fundName = fundInfoService.getFundNameByFundCode(value, trustNo, tenant.getTenantName());
                            entity.setFundCode(value);
                            entity.setFundName(fundName);
                            entity.setInnerFundCode(value);
                            break;
                        case FieldConstants.FUND_OPEN_INFO_OPEN_TYPE:
                            //开放日类型是由上游周期类型\是否临时开放两个值决定的
                            TenantEmailFieldConfigEntity fieldConfigEntity = tenantEmailFieldConfigService.getConfigByVerdionAndFiled(version, fundOpenInfoPrefix, FUND_OPEN_INFO_OPEN_TYPE_ZQ);
                            //获取周期类型
                            Integer zqStartIndex = fieldConfigEntity.getStartIndex()  - 1;
                            String periodType = ByteUtils.getString(zqStartIndex, zqStartIndex + fieldConfigEntity.getLength(), e);
                            //拼装值
                            value = periodType + "/" + value;
                            openType = MatchDataDictionaryKeyUtil.getKey(finalTypeOfOpenDayDic, value);
                            log.info("getFundOpenInfo trustNo:{} : openType原值:{}, 映射值:{}", trustNo, value, openType);
                            entity.setOpenType(openType);
                            break;
                        case FieldConstants.FUND_OPEN_INFO_OPEN_STATUS:
                            openStatus = value;
                            break;
                        case FieldConstants.FUND_OPEN_INFO_FUND_OPEN_DATE_BEGIN://开放日开始日期
                            fundOpenDateBegin = value;
                            break;
                        case FieldConstants.FUND_OPEN_INFO_FUND_OPEN_DATE_END://开放日结束日期
                            fundOpenDateEnd = value;
                            break;
                        case FieldConstants.FUND_OPEN_INFO_IF_FIXED_TIME:
                            entity.setIfFixedTime(Integer.parseInt(value));
                            break;
                        case FieldConstants.FUND_OPEN_INFO_REMARK:
                            entity.setRemark(value);
                            break;
                        default:
//                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}", fundOpenInfoPrefix, targetField, startIndex, endIndex);
                    }
                }
                //根据openStatus需要根据openType查询映射值
                String finalOpenStatus = MatchDataDictionaryKeyUtil.getKey(openType, finalOpenStatusDic, openStatus);
                log.info("getFundOpenInfo trustNo:{} : openType值:{} ,openStatus原值:{},  映射值:{}", trustNo, openType, openStatus, finalOpenStatus);
                entity.setOpenStatus(finalOpenStatus);
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                //fundOpenDate 从开始日期到结束日期拆分成日，分多行存入数据库，其他字段内容相同.
                SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
                log.info("getFundOpenInfo trustNo:{} : fundOpenDateBegin:{} fundOpenDataDateEnd:{}", trustNo, fundOpenDateBegin, fundOpenDateEnd);
                Date beginDate = format.parse(fundOpenDateBegin);
                Date endDate = format.parse(fundOpenDateEnd);
                //判断开始时间相差天数
                int days = CalanderUtil.differentDays(beginDate, endDate);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(beginDate);
                for (int i = 0; i <= days; i++) {
                    if (i != 0) {
                        calendar.add(Calendar.DATE, 1);
                    }
                    Date fundOpenDate = calendar.getTime();
                    entity.setFundOpenDate(format.format(fundOpenDate));
                    result.add(entity);
                }

            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getFundOpenInfo 发生异常", ex);
            }
        }
        return result;
    }

    public static void main(String[] args) throws ParseException {
        String beginDateStr = "20221227";
        String endDateStr = "20221227";
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMdd");
        Date beginDate = format1.parse(beginDateStr);
        Date endDate = format1.parse(endDateStr);
        //判断开始时间相差天数
        int days = CalanderUtil.differentDays(beginDate, endDate);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginDate);
        for (int i = 0; i <= days; i++) {
            if (i != 0) {
                calendar.add(Calendar.DAY_OF_YEAR, 1);
            }
            Date time = calendar.getTime();
            String fundOpenDate = format1.format(time);
            System.out.println("fundOpenDate" + fundOpenDate);
        }
    }

    /**
     * 每日更新
     *  @param tenant
     * @param file
     * @param flag
     * @param version
     */
    @Override
    public void getUpdateData(TenantEscrowAuthorizationInfoDto tenant, File file, String flag, String version) {
        log.info("HandlerVersionTxtServiceImpl:getUpdateData:tenant={},file={},flag={},version={}",
                JSON.toJSONString(tenant),
                file==null?"null":file.getAbsolutePath(),
                flag,
                version);
        String trustNo = tenant.getTrustNo();
        String filename = "";
        if(file!=null){
            filename = file.getAbsolutePath();
        }
        log.info("getUpdateData:tenant={},file={},flag={}",JSON.toJSONString(tenant),filename,flag);
        try{
            //1 基金产品信息表（fund_info）
            processFundInfoData(tenant, file, trustNo, flag,version);
            //2 基金出资人信息表（investor_info）
            processInvestorInfoData(tenant, file, trustNo,flag,version);
            //2 基金出资人信息表（investeor_bank_info）
            processInvestorBankInfoData(tenant, file, trustNo,flag,version);
            //4 基金持有信息表（cust_share_detail_info）
            processCustShareDetailInfoData(tenant,file, trustNo,flag,version);
            //18 基金交易确认信息表（fund_trade_info）
            processFundTradeInfoData(tenant, file,trustNo, flag,version);
            //17 托管⼾流⽔表（custShare_seq_info）
            processCustShareSeqInfoData(tenant,file, trustNo, flag,version);
            //14 业绩报酬信息表(fund_profit_info)
            processFundProfitInfoData(tenant, file,trustNo, flag,version);
            //3 基金净值信息表（fund_net_value_info）
            processFundNetValueInfoData(tenant, file,trustNo, flag,version);
            //4 基金持有信息表（cust_share_info）
            processCustShareInfoData(tenant,file, trustNo,flag,version);
            // 开放日信息表(fund_open_info)
            processFundOpenInfoData(tenant, file, trustNo, flag, version);

        }catch (Exception e){
            log.error("邮件getUpdateData异常{}",e);
        }
    }

    public static final String FUND_INFO_FILENAME = "TAInfo.Txt";

    /**
     * 1 基金产品信息表（fund_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processFundInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try {
            String filePath = file.getAbsolutePath() + File.separator + FUND_INFO_FILENAME.toLowerCase();
            log.info("processFundInfoData需要读取文件：{}", filePath);
            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)) {
                String partOfFilename = FUND_INFO_FILENAME;
                List<FundInfoEntity> entities = getFundInfo(bytes,tenant,trustNo,version,partOfFilename);
                log.info("读取文件{} processFundInfoData获取数据量为{}", filePath, entities.size());
                fundInfoService.saveData(null, entities);
            } else {
                log.info("文件{}没有具体内容，跳过", filePath);
            }
        } catch (Exception e) {
            log.error("邮件processFundInfoData异常{}", e);
        }
    }

    /**
     * select *  from custody_tenant_email_field_config where version = '3.72'  and file_name like 'TAInfo.Txt%'
      * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param partOfFilename
     * @return
     */
    private List<FundInfoEntity> getFundInfo(List<byte[]> bytes,
                                             TenantEscrowAuthorizationInfoDto tenant,
                                             String trustNo,
                                             String version,
                                             String partOfFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,partOfFilename);
        Map<String, String> status = new HashMap<>();
        Map<String, String> fundTypeDic = new HashMap<>();
        try{
            status = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PRODUCT_STATUS_SERVICE, "54");
            fundTypeDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.FUND_TYPE_SERVICE, "54");
        }catch (Exception e){
            log.error("HandlerVersionTxtServiceImpl:trustNo {}, admin{}:getFundInfo获取字典异常{}",trustNo, tenant.getTenantName(), e);
        }

        List<FundInfoEntity> result = new ArrayList<>();
        Map<String, String> finalStatus = status;
        Map<String, String> finalFundTypeDic = fundTypeDic;
        bytes.stream().forEach(e->{

            try {
                FundInfoEntity entity = new FundInfoEntity();
                for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();

                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    switch (targetField){
                        case FieldConstants.FUND_INFO_FUNDCODE:
                            entity.setFundCode(value);
                            break;
                        case FieldConstants.FUND_INFO_FUNDNAME:
                            entity.setFundName(value);
                            break;
                        case FieldConstants.FUND_INFO_CREATE_DATE:
                            entity.setCreateDate(value);
                            break;
                        case FieldConstants.FUND_INFO_FUND_STATUS:
                            String fundStatus = MatchDataDictionaryKeyUtil.getKey(finalStatus, value);
                            log.info("getFundInfo admin:{} ,trustNo: {}, 字典映射:fundStatus原值为{},映射值为{}", tenant.getTenantName(), tenant.getTrustNo(), value,fundStatus);
                            entity.setFundStatus(fundStatus);
                            break;
                        case FieldConstants.FUND_INFO_DURATION_PERIOD:
                            entity.setDurationPeriod(String.valueOf(Integer.parseInt(value)));
                            break;
                        case FieldConstants.FUND_INFO_FUNDTYPE:
                            String fundType = MatchDataDictionaryKeyUtil.getKey(finalFundTypeDic, value);
                            log.info("getFundInfo admin:{} ,trustNo: {}, 字典映射:fundType原值为{},映射值为{}", tenant.getTenantName(), tenant.getTrustNo(), value,fundType);
                            entity.setFundType(fundType);
                            entity.setPeType(fundType);
                            break;
                        case FieldConstants.FUND_INFO_CONFDAYS:
                            //东方证券截出来是中文
                            boolean matches = value.matches("^[0-9]*$");
                            if(matches && StringUtils.isNotBlank(value)){
                               entity.setConfDays(String.valueOf(Integer.parseInt(value)));
                            }
                            break;
                        default:
                            log.info("trustNo{},admin{},处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",tenant.getTenantName(), tenant.getTrustNo(), partOfFilename,targetField,startIndex,endIndex);
                    }
                }
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getFundInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getFundInfo发生异常{}",ex);
            }
        });
        return result;
    }

    public static final String INVESTOR_PREFIX_FILENAME = "Acco_";

    /**
     * 2 基金出资人信息表（investor_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processInvestorInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(), DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + INVESTOR_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + INVESTOR_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processInvestorInfoData:trustNo{}admin{}需要读取文件：{}",trustNo, tenant.getTenantName(), filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<InvestorInfoEntity> entities = getInvestorInfo(bytes,tenant,trustNo,version,INVESTOR_PREFIX_FILENAME);
                log.info("读取文件{},processInvestorInfoData:trustNo{}admin{}获取数据量为{}",filePath,tenant.getTrustNo(), tenant.getTenantName(), entities.size());
                investorInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processInvestorInfoData异常{}",e);
        }
    }

    /**
     * Acco_yyyymmdd.txt
     * select *  from custody_tenant_email_field_config where version = '3.72'  and file_name like 'Acco_%' and length(file_name) = 17;
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param partOfFilename
     * @return
     */
    private List<InvestorInfoEntity> getInvestorInfo(List<byte[]> bytes,
                                                     TenantEscrowAuthorizationInfoDto tenant,
                                                     String trustNo,
                                                     String version,
                                                     String partOfFilename) {

        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,partOfFilename);
        //Acco_yyyymmdd.txt  长度为17
        if(!CollectionUtils.isEmpty(configEntities)){
            configEntities = configEntities.stream().filter(item-> item.getFileName().length()==17).collect(Collectors.toList());
        }

        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");
        } catch (Exception e) {
            log.error("HandlerVersionTxtServiceImpl:getInvestorInfo:获取字典异常{}",e);
        }
        List<InvestorInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalCustTypeCsdcDic = custTypeCsdcDic;
        Map<String, Map<String, String>> finalIdentityTypeCsdcDic = identityTypeCsdcDic;
        List<TenantEmailFieldConfigEntity> finalConfigEntities = configEntities;
        bytes.stream().forEach(e->{
            try {
                InvestorInfoEntity entity = new InvestorInfoEntity();
                String custType = "";
                for (TenantEmailFieldConfigEntity configEntity : finalConfigEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    switch (targetField){
                        case FieldConstants.INVESTOR_INFO_CUST_TYPE:
                            String key = MatchDataDictionaryKeyUtil.getKey(finalCustTypeCsdcDic, value);
                            custType = key;
                            entity.setCustType(key);
                            break;
                        case FieldConstants.INVESTOR_INFO_IDENTITY_TYPE:
                            String identityType = MatchDataDictionaryKeyUtil.getKey(custType, finalIdentityTypeCsdcDic, value);
                            entity.setIdentityType(identityType);
                            break;
                        case FieldConstants.INVESTOR_INFO_IDENTITY_NO:
                            entity.setIdentityNo(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_CUST_NAME:
                            entity.setCustName(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_ADDRESS:
                            entity.setAddress(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_ZIP_CODE:
                            entity.setZipCode(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_EMAIL:
                            entity.setEmail(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_MOBILE_NO:
                            entity.setMobileNo(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_ACCO_OPEN_DATE:
                            entity.setAccoOpenDate(value);
                            break;
                        case FieldConstants.INVESTOR_INFO_UPDATE_DATE:
                            log.info("getInvestorInfo:updateDate为{}",value);
                            String updateDate = value.substring(0,4)+"-"+value.substring(4,6)+"-"+value.substring(6,8)+" 00:00:00";
                            entity.setUpdateDate(updateDate);
                            break;
                        default:
                            log.info("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",partOfFilename,targetField,startIndex,endIndex);
                    }
                }
                if(StringUtils.isBlank(entity.getIdentityType())){
                    TenantEmailFieldConfigEntity configEntity = finalConfigEntities.stream()
                            .filter(item -> FieldConstants.INVESTOR_INFO_IDENTITY_TYPE.equals(item.getTargetField()))
                            .findAny().orElse(new TenantEmailFieldConfigEntity());

                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    String identityType = MatchDataDictionaryKeyUtil.getKey(custType, finalIdentityTypeCsdcDic, value);
                    entity.setIdentityType(identityType);
                    log.info("HandlerVersionTxtServiceImpl:getInvestorInfo:IdentityType:trustNo{}, admin{},原值为{},映射值为{}",trustNo, tenant.getTrustNo(), value,identityType);
                }

                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getInvestorInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getInvestorInfo 发生异常：{}",ex);
            }
        });
        return result;
    }

    public static final String INVESTOR_BANK_INFO_PREFIX_FILENAME = "Acconet_";

    public static final String DEFAULT_DATE_PATTERN = "yyyyMMdd";

    /**
     * 2 基金出资人信息表（investeor_bank_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processInvestorBankInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + INVESTOR_BANK_INFO_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + INVESTOR_BANK_INFO_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processInvestorBankInfoData:trustNo{},admin{}需要读取文件：{}",trustNo, tenant.getTenantName(), filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<InvestorBankInfoEntity> entities = getInvestorBankInfo(bytes,tenant,trustNo,version,INVESTOR_BANK_INFO_PREFIX_FILENAME);
                log.info("读取文件{}，processInvestorBankInfoData:trustNo{},admin{}获取数据量为{}",trustNo, tenant.getTenantName(),filePath,entities.size());
                investorBankInfoService.saveData(null, entities);
            }else{
                log.info("trustNo{},admin{},文件{}没有具体内容，跳过", trustNo, tenant.getTenantName(), filePath);
            }
        }catch (Exception e){
            log.error("邮件processInvestorBankInfoData异常{}",e);
        }
    }

    /**
     * Acconet_yyyymmdd.txt
     * select *  from custody_tenant_email_field_config where version = '3.72'  and file_name like 'Acconet_%' ;
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param partOfFilename
     * @return
     */
    private List<InvestorBankInfoEntity> getInvestorBankInfo(List<byte[]> bytes,
                                                             TenantEscrowAuthorizationInfoDto tenant,
                                                             String trustNo,
                                                             String version,
                                                             String partOfFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,partOfFilename);

        Map<String, String> bankCodeDir = null;
        try {
            if ("14".equals(trustNo)){
                bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "平安银行TA");
            }else {
                bankCodeDir = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BANK_CODE_SERVICE, "资金清算系统银行编码");
            }
            log.info("getInvestorBankInfo 字典映射:银行编码={}",JSON.toJSONString(bankCodeDir));

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

        List<InvestorBankInfoEntity> result = new ArrayList<>();
        Map<String, String> finalBankCodeDir = bankCodeDir;
        bytes.stream().forEach(e->{
            try {
                InvestorBankInfoEntity entity = new InvestorBankInfoEntity();
                for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    switch (targetField){
                        case FieldConstants.INVESTOR_BANK_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.INVESTOR_BANK_INFO_TRADE_ACCO:
                            entity.setTradeAcco(MailUtil.decodeText(value));
                            break;
                        case FieldConstants.INVESTOR_BANK_INFO_NAME_IN_BANK:
                            entity.setNameInBank(value);
                            break;
                        case FieldConstants.INVESTOR_BANK_INFO_BANK_NO:
                            entity.setBankNo(value);
                            break;
                        case FieldConstants.INVESTOR_BANK_INFO_BANK_CODE:
                            String bankCode = MatchDataDictionaryKeyUtil.getKey(finalBankCodeDir, value);
                            log.info("getInvestorBankInfo trustNo{}字典映射:bankCode原值为{},映射值为{}",trustNo, value,bankCode);
                            entity.setBankCode(bankCode);
                            break;
                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",partOfFilename,targetField,startIndex,endIndex);
                    }
                }
                entity.setBankNoType("银行账号");
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                if(StringUtils.isBlank(entity.getTradeAcco())){
                    log.info("trade_acco字段若为空，则该记录不落库,entity={}",JSON.toJSONString(entity));
                }else{
                    result.add(entity);
                }
                log.info("HandlerVersionTxtServiceImpl:getInvestorBankInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getInvestorBankInfo 发生异常{}",ex);
            }
        });
        return result;
    }

    public static final String CUST_SHARE_DETAIL_INFO_PREFIX_FILENAME = "ShareDetail_";


    /**
     * 4 基金持有信息表（cust_share_detail_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processCustShareDetailInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_DETAIL_INFO_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_DETAIL_INFO_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processCustShareDetailInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<CustShareDetailInfoEntity> entities = getCustShareDetailInfo(bytes,tenant,trustNo,version,CUST_SHARE_DETAIL_INFO_PREFIX_FILENAME);
                log.info("读取文件{}，processCustShareDetailInfoData获取数据量为{}",filePath,entities.size());
                custShareDetailInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processCustShareDetailInfoData异常{}",e);
        }
    }

    public static String DONGFANG_TRUSTNO = "44";
    /**
     * ShareDetail_
     * select *  from custody_tenant_email_field_config where version = '3.72'  and file_name like 'ShareDetail_%' ;
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param prefixFilename
     * @return
     */
    private List<CustShareDetailInfoEntity> getCustShareDetailInfo(List<byte[]> bytes,
                                                                   TenantEscrowAuthorizationInfoDto tenant,
                                                                   String trustNo,
                                                                   String version,
                                                                   String prefixFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,prefixFilename);

        Map<String, String> sellerDic = null;
        Map<String, String> share = null;
        try {
            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "东方证券");
            }else {
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            }
            share = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SHARE_SOURCE_SERVICE, "54");
        } catch (Exception e) {
            log.error("HandlerVersionTxtServiceImpl:getCustShareDetailInfo:获取字典异常{}",e);
        }

        List<CustShareDetailInfoEntity> result = new ArrayList<>();
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalShare = share;
        bytes.stream().forEach(e->{
            try {
                CustShareDetailInfoEntity entity = new CustShareDetailInfoEntity();
                for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);
                    switch (targetField){
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_FUND_CODE:
                            entity.setFundCode(value);

                            String fundName = fundInfoService.getFundNameByFundCode(value, trustNo, tenant.getTenantName());
                            log.info("HandlerVersionTxtServiceImpl 字典映射:fundName原值为{},映射值为{}",value,fundName);
                            entity.setFundName(fundName);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_AGENCY_NO:
                            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, value);
                            log.info("HandlerVersionTxtServiceImpl 字典映射:agencyNo原值为{},映射值为{}",value,agencyNo);
                            entity.setAgencyNo(agencyNo);

                            String agencyName = null;
                            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                                agencyName = sellerService.queryAgencyName("东方证券", value);
                            } else {
                                agencyName = sellerService.queryAgencyName("长江证券", value);
                            }
                            log.info("HandlerVersionTxtServiceImpl 字典映射:agencyName原值为{},映射值为{}",value,agencyName);
                            entity.setAgencyName(agencyName);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_BRANCH_CODE:
                            entity.setBranchCode(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_CONFIRM_DATE:
                            entity.setConfirmDate(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_CSERIAL_NO:
                            entity.setCserialNo(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_SOURCE_TYPE:
                            String sourceType = MatchDataDictionaryKeyUtil.getKey(finalShare, value);
                            log.info("HandlerVersionTxtServiceImpl 字典映射:sourceType原值为{},映射值为{}",value,sourceType);
                            entity.setSourceType(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_REMAIN_SHARES:
                            log.info("getCustShareDetailInfo:{}",FieldConstants.CUST_SHARE_DETAIL_INFO_REMAIN_SHARES);
                            entity.setRemainShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_NET_VALUE:
                            log.info("getCustShareDetailInfo:{}",FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_NET_VALUE);
                            String oriNetValue = "";
                            if (configEntity.getLength() == 6){
                                oriNetValue = getsSubStringFour(value);
                            } else if (configEntity.getLength() == 11){
                                oriNetValue = getSubStringEight(value);
                            }
                            log.info("getCustShareDetailInfo: trustNo :{}, oriNetValue: 原值:{}, 转换后: {}", trustNo, value, oriNetValue);
                            entity.setOriNetValue(BigDecimalUtil.str2BigDecimal(oriNetValue,4));
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_TRADE_ACCO:
                            entity.setTradeAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_REGIST_DATE:
                            entity.setRegistDate(value);
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_BALANCE:
                            log.info("getCustShareDetailInfo:{}",FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_BALANCE);
                            entity.setOriBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_SHARES:
                            log.info("getCustShareDetailInfo:{}",FieldConstants.CUST_SHARE_DETAIL_INFO_ORI_SHARES);
                            entity.setOriShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",prefixFilename,targetField,startIndex,endIndex);
                    }
                }
                entity.setSeqNo(RandomStrUtil.getRandomStr(32));
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getCustShareDetailInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getCustShareDetailInfo 发生异常{}",ex);
            }
        });
        return result;
    }

    public static final String FUND_TRADE_INFO_PREFIX_FILENAME = "Confirm_";

    /**
     * Confirm_yyyymmdd.txt
     * 18 基金交易确认信息表（fund_trade_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processFundTradeInfoData(TenantEscrowAuthorizationInfoDto tenant,
                                         File file,
                                         String trustNo,
                                         String flag,
                                         String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + FUND_TRADE_INFO_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + FUND_TRADE_INFO_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processFundTradeInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<FundTradeInfoEntity> entities = getFundTradeInfo(bytes,tenant,trustNo,version,FUND_TRADE_INFO_PREFIX_FILENAME);
                log.info("读取文件{} processFundTradeInfoData获取数据量为{}",filePath,entities.size());
                fundTradeInfoService.saveData(null, entities);
            }else{
                log.info("文件{}没有具体内容，跳过",filePath);
            }
        }catch (Exception e){
            log.error("邮件processFundTradeInfoData异常{}",e);
        }
    }

    /**
     * Confirm_yyyymmdd.txt
     * select * from custody_tenant_email_field_config where version = '3.72'  and file_name like 'Confirm_%'  and length(file_name) = 20 ;
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param prefixFilename
     * @return
     */
    private List<FundTradeInfoEntity> getFundTradeInfo(List<byte[]> bytes,
                                                       TenantEscrowAuthorizationInfoDto tenant,
                                                       String trustNo,
                                                       String version,
                                                       String prefixFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,prefixFilename);
        log.info("HandlerVersionTxtServiceImpl:getFundTradeInfo，过滤前{}",JSON.toJSONString(configEntities));
        if(!CollectionUtils.isEmpty(configEntities)){
            configEntities =  configEntities.stream().filter(item->item.getFileName().length() ==20).collect(Collectors.toList());
            log.info("HandlerVersionTxtServiceImpl:getFundTradeInfo，过滤后{}",JSON.toJSONString(configEntities));
        }

        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");
            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "东方证券");
            }else {
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            }
            currency = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.CURRENCY_SERVICE, "54");
            bonus = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, "54");

        } catch (Exception e) {
            log.error("HandlerVersionTxtServiceImpl: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;
        List<TenantEmailFieldConfigEntity> finalConfigEntities = configEntities;
        bytes.stream().forEach(e->{
            try {
                FundTradeInfoEntity entity = new FundTradeInfoEntity();
                log.info("HandlerVersionTxtServiceImpl:getFundTradeInfo，trustNo :{}, 使用的配置{}", trustNo, JSON.toJSONString(finalConfigEntities));
                for (TenantEmailFieldConfigEntity configEntity : finalConfigEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);
                    switch (targetField){
                        case FieldConstants.FUND_TRADE_INFO_CONFIRM_DATE:
                            entity.setConfirmDate(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_CSERIAL_NO:
                            entity.setCserialNo(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_BUSINESS_NAME:
                            String businessNameValue = MatchDataDictionaryKeyUtil.getKey(finalBusinessName, value);
                            log.info("getFundTradeInfo trustNo：{}, admin :{}字典映射:businessName 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value,businessNameValue);
                            entity.setBusinessName(businessNameValue);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_FUND_CODE:
                            entity.setFundCode(value);

                            String fundName = fundInfoService.getFundNameByFundCode(value, trustNo, tenant.getTenantName());
                            log.info("getFundTradeInfo trustNo{}字典映射:fundName 原值为{},映射值为{}", trustNo, value,fundName);
                            entity.setFundName(fundName);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_REQUEST_DATE:
                            entity.setRequestDate(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_REQUEST_NO:
                            entity.setRequestNo(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_AGENCY_NO:
                            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic,value);
                            log.info("getFundTradeInfo trustNo{} 字典映射:agencyNo 原值为{},映射值为{}",trustNo, value,agencyNo);
                            entity.setAgencyNo(agencyNo);

                            String agencyName = null;
                            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                                agencyName = sellerService.queryAgencyName("东方证券", value);
                            } else {
                                agencyName = sellerService.queryAgencyName("长江证券", value);
                            }
                            log.info("getFundTradeInfo trustNo{} 字典映射:agencyName 原值为{},映射值为{}",trustNo, value,agencyName);
                            entity.setAgencyName(agencyName);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_CURRENCY:
                            String currencyValue = MatchDataDictionaryKeyUtil.getKey(finalCurrency, value);
                            log.info("getFundTradeInfo trustNo{} 字典映射:currency 原值为{},映射值为{}", trustNo, value,currencyValue);
                            entity.setCurrency(currencyValue);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_CONFIRM_SHARES:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_CONFIRM_SHARES);
                            entity.setConfirmShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_CONFIRM_BALANCE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_CONFIRM_BALANCE);
                            entity.setConfirmBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_TRADE_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_TRADE_FARE);
                            entity.setTradeFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_TA_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_TA_FARE);
                            entity.setTaFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_STAMP_TAX:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_STAMP_TAX);
                            entity.setStampTax(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_BACK_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_BACK_FARE);
                            entity.setBackFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_BONUS_METHOD:
                            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(finalBonus, value);
                            log.info("getFundTradeInfo trustNo{}, admin{}: 字典映射:bonusMethod 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value,bonusMethod);
                            entity.setBonusMethod(bonusMethod);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_TRADE_ACCO:
                            entity.setTradeAcco(value);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_NET_VALUE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_NET_VALUE);
                            String netValue = "";
                            if (configEntity.getLength() == 6){
                                netValue = getsSubStringFour(value);
                            } else if (configEntity.getLength() == 11){
                                netValue = getSubStringEight(value);
                            }
                            entity.setNetValue(BigDecimalUtil.str2BigDecimal(netValue,4));
                            log.info("getFundTradeInfo :trustNo:{}, netValue 原值:{}，处理之后:{}", trustNo, value, netValue);
                            break;
                        case FieldConstants.FUND_TRADE_INFO_FUND_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_FUND_FARE);
                            entity.setFundFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_AGENCY_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_AGENCY_FARE);
                            entity.setAgencyFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_REGIST_FARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_REGIST_FARE);
                            entity.setRegistFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_INTEREST:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_INTEREST);
                            entity.setInterest(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_INTEREST_SHARE:
                            log.info("getFundTradeInfo:{}",FieldConstants.FUND_TRADE_INFO_INTEREST_SHARE);
                            entity.setInterestShare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_TRADE_INFO_SUMMARY:
                            entity.setSummary(value);
                            break;

                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",prefixFilename,targetField,startIndex,endIndex);
                    }
                }
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getFundTradeInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getFundTradeInfo {}",ex);
            }
        });
        return result;
    }

    public static final String CUST_SHARE_SEQ_INFO_PREFIX_FILENAME = "ShareCurrents_";

    /**
     * 17 托管⼾流⽔表（custShare_seq_info）
     * ShareCurrents_yyyymmdd.txt
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processCustShareSeqInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try {
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_SEQ_INFO_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_SEQ_INFO_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processCustShareSeqInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if (!CollectionUtils.isEmpty(bytes)) {
                String partOfFilename = CUST_SHARE_SEQ_INFO_PREFIX_FILENAME;
                List<CustShareSeqInfoEntity> entities = getCustShareSeqInfo(bytes,tenant,trustNo,version,partOfFilename);
                log.info("读取文件{} processCustShareSeqInfoData获取数据量为{}", filePath, entities.size());
                custShareSeqInfoService.saveData(null, entities);
            } else {
                log.info("文件{}没有具体内容，跳过", filePath);
            }
        } catch (Exception e) {
            log.error("邮件processCustShareSeqInfoData异常{}", e);
        }
    }

    public static final String ALL_ZERO_REFEX = "^[0]*$";

    private List<CustShareSeqInfoEntity> getCustShareSeqInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo, String version, String partOfFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version, partOfFilename);
        if (CollectionUtils.isEmpty(configEntities)){
            log.info("version:{}无配置信息!", version);
        }
        //数据字典获取
        Map<String, String> businessNameDic = null;
        Map<String, String> payWayDic = null;
        Map<String, String> sellerDic = null;
        try {
            businessNameDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, "54");
            payWayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, "54");
            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "东方证券");
            }else {
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            }
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getCustShareSeqInfo:获取字典异常{}", e);
        }
        List<CustShareSeqInfoEntity> result = new ArrayList<>();
        Map<String, String> finalBusinessNameDic = businessNameDic;
        Map<String, String> finalPayWayDic = payWayDic;
        Map<String, String> finalSellerDic = sellerDic;
        bytes.stream().forEach(e -> {
                CustShareSeqInfoEntity entity = new CustShareSeqInfoEntity();
                for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();

                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    switch (targetField) {
                        case FieldConstants.CUST_SHARE_SEQ_INFO_CONFIRM_DATE:
                            entity.setConfirmDate(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_CSERIAL_NO:
                            entity.setCserialNo(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_BUSINESS_NAME:
                            String businessName = MatchDataDictionaryKeyUtil.getKey(finalBusinessNameDic, value);
                            log.info("getCustShareSeqInfo trustNo{}, admin{}: 字典映射:businessName 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value, businessName);
                            entity.setBusinessName(businessName);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_REQUEST_DATE:
                            entity.setRequestDate(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_REQUEST_NO:
                            entity.setRequestNo(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_TRADE_ACCO:
                            entity.setTradeAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_FUND_CODE:
                            entity.setFundCode(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_SHARE_TYPE:
                            String shareType = MatchDataDictionaryKeyUtil.getKey(finalPayWayDic, value);
                            log.info("getCustShareSeqInfo trustNo{}, 字典映射:shareType 原值为{},映射值为{}",trustNo, value, shareType);
                            entity.setShareType(shareType);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_AGENCY_NO:
                            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, value);
                            entity.setAgencyNo(agencyNo);
                            log.info("getCustShareSeqInfo trustNo{}, 字典映射:agencyNo 原值为{},映射值为{}",trustNo, value, agencyNo);
                            //根据agencyNo查询agencyName
                            String agencyName = null;
                            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                                agencyName = sellerService.queryAgencyName("东方证券", value);
                            } else {
                                agencyName = sellerService.queryAgencyName("长江证券", value);
                            }
                            entity.setAgencyName(agencyName);
                            log.info("getCustShareSeqInfo trustNo{}字典映射:agencyNo为{},agencyName为{}",trustNo, value, agencyName);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_BRANCH_CODE:
                            entity.setBranchCode(value);
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_OCCUR_SHARES:
                            entity.setOccurShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_OCCUR_BALANCE:
                            entity.setOccurBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_LAST_HOLD_SHARES:
                            entity.setLastHoldShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_SEQ_INFO_SEQ_NO:
                            //如果全是0，则随机生成流水号
                            if (value.matches(ALL_ZERO_REFEX)) {
                                entity.setSeqNo(StrUtil.getRandomStr(32));
                            } else {
                                entity.setSeqNo(value);
                            }
                            break;
                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}", partOfFilename, targetField, startIndex, endIndex);
                    }
                }
                String fundName = fundInfoService.getFundNameByFundCode(entity.getFundCode(), trustNo, tenant.getTenantName());
                log.info("getCustShareSeqInfo 字典映射:fundCode为{}, fundName为{}", entity.getFundCode(), fundName);


                entity.setFundName(fundName);
                entity.setCurrency("156");
                entity.setTrustNo(trustNo);
                entity.setCurrency("156");
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getFundInfo:entity:{}", JSON.toJSONString(entity));
            });

            return result;
        }


    public static final String FUND_PROFIT_INFO_PREFIX_FILENAME = "ProfitCurrent_";
        /**
         * ProfitCurrent_yyyymmdd.txt
         * 14 业绩报酬信息表(fund_profit_info)
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processFundProfitInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + FUND_PROFIT_INFO_PREFIX_FILENAME.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + FUND_PROFIT_INFO_PREFIX_FILENAME.toLowerCase() + date + ".txt";
            }
            log.info("processFundProfitInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if (!CollectionUtils.isEmpty(bytes)) {
                String partOfFilename = FUND_PROFIT_INFO_PREFIX_FILENAME;
                List<FundProfitInfoEntity> entities = getFundProfitInfo(bytes, tenant, trustNo, version, partOfFilename);
                log.info("读取文件{} processFundProfitInfoData :trustNo{}, admin{},获取数据量为{}", filePath, entities.size());
                fundProfitInfoService.saveData(null, entities);
            } else {
                log.info("processFundProfitInfoData:文件{}没有具体内容，跳过", filePath);
            }
        } catch (Exception e) {
            log.error("邮件processFundProfitInfoData异常{}", e);
        }
    }

    private List<FundProfitInfoEntity> getFundProfitInfo(List<byte[]> bytes, TenantEscrowAuthorizationInfoDto tenant, String trustNo, String version, String partOfFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version, partOfFilename);
        if (CollectionUtils.isEmpty(configEntities)){
            log.info("version:{}无配置信息!", version);
        }
        //数据字典待获取
        Map<String, String> businessNameDic = null;
        Map<String, String> payWayDic = null;
        Map<String, String> sellerDic = null;
        Map<String, String> handleTypeDic = null;
        try {
            businessNameDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.BUSINESS_NAME_SERVICE, "54");
            payWayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.PAYMENT_WAY_SERVICE, "54");
            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "东方证券");
            }else {
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            }
            handleTypeDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.HANDLE_TYPE_SERVICE, "54");
        } catch (Exception e) {
            log.error("OutSourceMailServiceImpl:getFundProfitInfo获取字典异常{}", e);
        }

        List<FundProfitInfoEntity> result = new ArrayList<>();
        Date now = new Date();
        Map<String, String> finalBusinessNameDic = businessNameDic;
        Map<String, String> finalPayWayDic = payWayDic;
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalHandleTypeDic = handleTypeDic;
        bytes.stream().forEach(e->{
            FundProfitInfoEntity entity = new FundProfitInfoEntity();
            for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                String targetField = configEntity.getTargetField();
                Integer startIndex = configEntity.getStartIndex() - 1;
                Integer endIndex = startIndex + configEntity.getLength();
                log.info("getFundProfitInfo:开始位置:{}, 结束位置：{}", startIndex, endIndex);
                String value = ByteUtils.getString(startIndex, endIndex, e);
                switch (targetField){
                    case FieldConstants.FUND_PROFIT_INFO_BUSINESS_NAME:
                        String businessName = MatchDataDictionaryKeyUtil.getKey(finalBusinessNameDic, value);
                        entity.setBusinessName(businessName);
                        log.info("getFundProfitInfo trustNo{}, admin{}: 字典映射:businessName 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value, businessName);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_CONFIRM_DATE:
                        log.info("getFundProfitInfo:{}", FieldConstants.FUND_PROFIT_INFO_CONFIRM_DATE);
                        entity.setConfirmDate(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_CSERIAL_NO:
                        log.info("getFundProfitInfo:{}", FieldConstants.FUND_PROFIT_INFO_CSERIAL_NO);
                        entity.setCserialNo(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_FUND_ACCO:
                        log.info("getFundProfitInfo:{}", FieldConstants.FUND_PROFIT_INFO_FUND_ACCO);
                        entity.setFundAcco(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_FUND_CODE:
                        log.info("getFundProfitInfo:{}", FieldConstants.FUND_PROFIT_INFO_FUND_CODE);
                        entity.setFundCode(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_AGENCY_NO:
                        String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, value);
                        entity.setAgencyNo(agencyNo);
                        log.info("getFundProfitInfo trustNo{}, 字典映射:agencyNo 原值为{},映射值为{}",trustNo, value, agencyNo);

                        String agencyName = null;
                        if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                            agencyName = sellerService.queryAgencyName("东方证券", value);
                        } else {
                            agencyName = sellerService.queryAgencyName("长江证券", value);
                        }
                        entity.setAgencyName(agencyName);
                        log.info("getFundProfitInfo trustNo{}, 字典映射:agencyName 原值为{},映射值为{}",trustNo, agencyName);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_BRANCH_CODE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_BRANCH_CODE);
                        entity.setBranchCode(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_TRADE_ACCO:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_TRADE_ACCO);
                        entity.setTradeAcco(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_SHARE_TYPE:
                        String shareType = MatchDataDictionaryKeyUtil.getKey(finalPayWayDic, value);
                        entity.setShareType(shareType);
                        log.info("getFundProfitInfo trustNo{}, admin{}: 字典映射:shareType 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value, shareType);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_REQUEST_DATE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_REQUEST_DATE);
                        entity.setRequestDate(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_ORI_CSERIAL_NO:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_ORI_CSERIAL_NO);
                        entity.setOriCserialNo(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_REGIST_DATE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_REGIST_DATE);
                        entity.setRegistDate(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_SHARES:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_SHARES);
                        entity.setShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_NAV:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_NAV);
                        String nav = "";
                        if (configEntity.getLength() == 7){
                            nav = getsSubStringFour(value);
                        }else if (configEntity.getLength() == 11){
                            nav = getSubStringEight(value);
                        }
                        entity.setNav(BigDecimalUtil.str2BigDecimal(nav, 4));
                        log.info("getFundProfitInfo :trustNo{} nav原值：{}, 处理之后：{}", trustNo, value, nav);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_TOTAL_NAV:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_TOTAL_NAV);
                        String totalNav = "";
                        if (configEntity.getLength() == 7){
                            totalNav = getsSubStringFour(value);
                        }else if (configEntity.getLength() == 11){
                            totalNav = getSubStringEight(value);
                        }
                        entity.setTotalNav(BigDecimalUtil.str2BigDecimal(totalNav, 4));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_CURR_RATIO:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_CURR_RATIO);
                        entity.setCurrRatio(BigDecimalUtil.str2BigDecimal(getSubStringEight(value), 4));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_YEAR_RATIO:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_YEAR_RATIO);
                        entity.setYearRatio(BigDecimalUtil.str2BigDecimal(getSubStringEight(value), 4));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_RETURN_FARE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_RETURN_FARE);
                        entity.setReturnFare(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_ORI_BALANCE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_ORI_BALANCE);
                        entity.setOriBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_FACT_BALANCE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_FACT_BALANCE);
                        entity.setFactBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_FACT_SHARES:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_FACT_SHARES);
                        entity.setFactShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_BONUS_BALANCE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_BONUS_BALANCE);
                        entity.setBonusBalance(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_SORT_FLAG:
                        String sortFlag = MatchDataDictionaryKeyUtil.getKey(finalHandleTypeDic, value);
                        log.info("getFundProfitInfo trustNo{},admin{}: 字典映射:sortFlag 原值为{},映射值为{}",trustNo, tenant.getTenantName(), value, sortFlag);
                        entity.setSortFlag(sortFlag);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_ORI_DATE:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_ORI_DATE);
                        entity.setOriDate(value);
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_HOLD_DAY:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_HOLD_DAY);
                        entity.setHoldDay(value.replaceFirst("0*", ""));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_ORI_NAV:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_ORI_NAV);
                        entity.setOriNav(BigDecimalUtil.str2BigDecimal(getSubStringEight(value), 4));
                        break;
                    case FieldConstants.FUND_PROFIT_INFO_ORI_TOTAL_NAV:
                        log.info("getFundProfitInfo:{} ", FieldConstants.FUND_PROFIT_INFO_ORI_TOTAL_NAV);
                        entity.setOriTotalNav(BigDecimalUtil.str2BigDecimal(getSubStringEight(value), 4));
                        break;
                    default:
                        log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",partOfFilename,targetField,startIndex,endIndex);
                }
            }
            String fundName = fundInfoService.getFundNameByFundCode(entity.getFundCode(), trustNo, tenant.getTenantName());
            log.info("HandlerVersionTxtServiceImpl 字典映射:fundName 原值为{},映射值为{}",entity.getFundCode(),fundName);


            entity.setFundName(fundName);
            entity.setTrustNo(trustNo);
            entity.setAdmin(tenant.getTenantName());
            entity.setCreateTime(new Date());
            entity.setUpdateTime(new Date());
            result.add(entity);
            log.info("HandlerVersionTxtServiceImpl:getFundInfo:entity:{}",JSON.toJSONString(entity));
        });
        return result;
    }

    public static final String FUND_NET_VALUE_INFO_PREFIX = "FundInfo_";

    /**
     * 3 基金净值信息表（fund_net_value_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + FUND_NET_VALUE_INFO_PREFIX.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + FUND_NET_VALUE_INFO_PREFIX.toLowerCase() + date + ".txt";
            }
            log.info("processFundNetValueInfoData需要读取文件：{}",filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if(!CollectionUtils.isEmpty(bytes)){
                List<FundNetValueInfoEntity> entities = getFundNetValueInfo(bytes,tenant,trustNo,version,FUND_NET_VALUE_INFO_PREFIX);
                log.info("读取文件{} processFundNetValueInfoData获取数据量为{}",filePath, entities.size());

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

    /**
     * select * from custody_tenant_email_field_config where version = '3.72' and file_name like 'FundInfo_%';
     * FundInfo_yyyymmdd.txt
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param prefixFilename
     * @return
     */
    private List<FundNetValueInfoEntity> getFundNetValueInfo(List<byte[]> bytes,
                                                             TenantEscrowAuthorizationInfoDto tenant,
                                                             String trustNo,
                                                             String version,
                                                             String prefixFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,prefixFilename);

        List<FundNetValueInfoEntity> result = new ArrayList<>();
        bytes.stream().forEach(e->{
            try {
                FundNetValueInfoEntity entity = new FundNetValueInfoEntity();
                for (TenantEmailFieldConfigEntity configEntity : configEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);

                    switch (targetField){
                        case FieldConstants.FUND_NET_VALUE_INFO_FUND_CODE:
                            entity.setFundCode(value);
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_FUND_NAME:
                            entity.setFundName(value);
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_NET_VALUE:
                            String netValue = "";
                            if (configEntity.getLength() == 6){
                                netValue = getsSubStringFour(value);
                            } else if (configEntity.getLength() == 11){
                                netValue = getSubStringEight(value);
                            }
                            entity.setNetValue(BigDecimalUtil.str2BigDecimal(netValue,4));
                            log.info("getFundTradeInfo :trustNo:{}, netValue 原值:{}，处理之后:{}", trustNo, value, BigDecimalUtil.str2BigDecimal(netValue,4));
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_SHARES:
                            log.info("getFundNetValueInfo:{}",FieldConstants.FUND_NET_VALUE_INFO_SHARES);
                            entity.setShares(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_NET_VALUE_DATE:
                            entity.setNetValueDate(value);
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_TOTAL_NET_VALUE:
                            log.info("getFundNetValueInfo:{}",FieldConstants.FUND_NET_VALUE_INFO_TOTAL_NET_VALUE);
                            String totalNetValue = "";
                            if (configEntity.getLength() == 6){
                                totalNetValue = getsSubStringFour(value);
                            } else if (configEntity.getLength() == 11){
                                totalNetValue = getSubStringEight(value);
                            }
                            entity.setTotalNetValue(BigDecimalUtil.str2BigDecimal(totalNetValue,4));
                            log.info("getFundNetValueInfo: trustNo:{}, totalNetValue原值:{}, 处理之后:{}", trustNo, value, BigDecimalUtil.str2BigDecimal(totalNetValue,4));
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_ETT_FUND_INCOME:
                            log.info("getFundNetValueInfo:{}",FieldConstants.FUND_NET_VALUE_INFO_ETT_FUND_INCOME);
                            String ettFundIncome = "";
                            if (configEntity.getLength() == 9){
                                ettFundIncome = getsSubStringFour(value);
                            } else if (configEntity.getLength() == 10){
                                ettFundIncome = getSubStringFive(value);
                            }
                            entity.setEttFundIncome(BigDecimalUtil.str2BigDecimal(ettFundIncome));
                            log.info("getFundNetValueInfo : trustNo {} ettFundIncome原值：{}， 处理之后：{}", trustNo, value, BigDecimalUtil.str2BigDecimal(ettFundIncome));
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_SEVEN_DAY_RATE:
                            log.info("getFundNetValueInfo:{}",FieldConstants.FUND_NET_VALUE_INFO_SEVEN_DAY_RATE);
                            entity.setSevenDayRate(BigDecimalUtil.str2BigDecimal(getsSubStringFour(value), 4));
                            break;
                        case FieldConstants.FUND_NET_VALUE_INFO_ASSET_VALUE:
                            log.info("getFundNetValueInfo:{}",FieldConstants.FUND_NET_VALUE_INFO_ASSET_VALUE);
                            entity.setAssetValue(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",prefixFilename,targetField,startIndex,endIndex);
                    }
                }
                entity.setCurrency("156");
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());
                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getFundNetValueInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getFundNetValueInfo 发生异常{}",ex);
            }
        });
        return result;
    }

    public static final String CUST_SHARE_INFO_PREFIX = "Share_";


    /**
     * 4 基金持有信息表（cust_share_info）
     *  @param tenant
     * @param file
     * @param trustNo
     * @param flag
     * @param version
     */
    @Override
    public void processCustShareInfoData(TenantEscrowAuthorizationInfoDto tenant, File file, String trustNo, String flag, String version) {
        try{
            String date = StrUtil.getDateStrFromStringByPattern(file.getAbsolutePath(),DEFAULT_DATE_PATTERN);
            String filePath;
            if (StringUtils.isNotBlank(flag)) {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_INFO_PREFIX.toLowerCase() + date + "_all.txt";
            } else {
                filePath = file.getAbsolutePath() + File.separator + CUST_SHARE_INFO_PREFIX.toLowerCase() + date + ".txt";
            }
            log.info("processCustShareInfoData需要读取文件：{}", filePath);
            List<byte[]> bytes = FileUtil.read(filePath);
            if (!CollectionUtils.isEmpty(bytes)) {
                List<CustShareInfoEntity> entities = getCustShareInfo(bytes, tenant, trustNo, version, CUST_SHARE_INFO_PREFIX);
                log.info("读取文件{} processCustShareInfoData获取数据量为{}",filePath, entities.size());

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

    /**
     * select * from custody_tenant_email_field_config where version = '3.72' and file_name like 'Share%' and length(file_name) = 18;
     * Share_yyyymmdd.txt
     * @param bytes
     * @param tenant
     * @param trustNo
     * @param version
     * @param prefixFilename
     * @return
     */
    private List<CustShareInfoEntity> getCustShareInfo(List<byte[]> bytes,
                                                       TenantEscrowAuthorizationInfoDto tenant,
                                                       String trustNo,
                                                       String version,
                                                       String prefixFilename) {
        List<TenantEmailFieldConfigEntity> configEntities = tenantEmailFieldConfigService.getConfigByVersionAndPartOfFilename(version,prefixFilename);

        if(!CollectionUtils.isEmpty(configEntities)){
            configEntities = configEntities.stream().filter(iter -> iter.getFileName().length() == 18).collect(Collectors.toList());
        }

        Map<String, String> sellerDic = null;
        Map<String, String> bonusWayDic = null;
        try {
            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "东方证券");
            }else {
                sellerDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.SELLER_SERVICE, "长江证券");
            }
            bonusWayDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.DIVIDEND_WAY_SERVICE, "54");

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

        List<CustShareInfoEntity> result = new ArrayList<>();
        Map<String, String> finalSellerDic = sellerDic;
        Map<String, String> finalBonusWay = bonusWayDic;
        List<TenantEmailFieldConfigEntity> finalConfigEntities = configEntities;
        bytes.stream().forEach(e->{
            try {
                CustShareInfoEntity entity = new CustShareInfoEntity();
                BigDecimal lastHoldShares = new BigDecimal(0);
                BigDecimal frozenShares = new BigDecimal(0);
                for (TenantEmailFieldConfigEntity configEntity : finalConfigEntities) {
                    String targetField = configEntity.getTargetField();
                    Integer startIndex = configEntity.getStartIndex() - 1;
                    Integer endIndex = startIndex + configEntity.getLength();
                    String value = ByteUtils.getString(startIndex, endIndex, e);
                    switch (targetField){
                        case FieldConstants.CUST_SHARE_INFO_FUND_ACCO:
                            entity.setFundAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_FUND_CODE:
                            String fundName = fundInfoService.getFundNameByFundCode(value, trustNo, tenant.getTenantName());
                            log.info("HandlerVersionTxtServiceImpl 映射:fundName 原值为{},映射值为{}",value,fundName);
                            entity.setFundName(fundName);
                            entity.setFundCode(value);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_AGENCY_NO:
                            String agencyNo = MatchDataDictionaryKeyUtil.getKey(finalSellerDic, value);
                            log.info("HandlerVersionTxtServiceImpl 字典映射:agencyNo 原值为{},映射值为{}",value,agencyNo);
                            entity.setAgencyNo(agencyNo);
                            String agencyName;
                            if (DONGFANG_TRUSTNO.equals(tenant.getTrustNo())){
                                agencyName = sellerService.queryAgencyName("东方证券", value);
                            } else {
                                agencyName = sellerService.queryAgencyName("长江证券", value);
                            }
                            log.info("HandlerVersionTxtServiceImpl 字典映射:agencyName 原值为{},映射值为{}",value,agencyName);
                            entity.setAgencyName(agencyName);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_LAST_HOLD_SHARES:
                            log.info("getCustShareInfo:{}",FieldConstants.CUST_SHARE_INFO_LAST_HOLD_SHARES);
                            lastHoldShares = BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value));
                            entity.setLastHoldShares(lastHoldShares);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_FROZEN_SHARES:
                            log.info("getCustShareInfo:{}",FieldConstants.CUST_SHARE_INFO_FROZEN_SHARES);
                            frozenShares = BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value));
                            entity.setFrozenShares(frozenShares);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_BONUS_METHOD:
                            String bonusMethod = MatchDataDictionaryKeyUtil.getKey(finalBonusWay, value);
                            log.info("getCustShareInfo trustNo:{} 字典映射:bounsMethod 原值为{},映射值为{}",value, bonusMethod);
                            entity.setBonusMethod(bonusMethod);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_TRADE_ACCO:
                            entity.setTradeAcco(value);
                            break;
                        case FieldConstants.CUST_SHARE_INFO_INCOME:
                            log.info("getCustShareInfo:{}",FieldConstants.CUST_SHARE_INFO_INCOME);
                            entity.setIncome(BigDecimalUtil.str2BigDecimal(getsSubStringTwo(value)));
                            break;
                        case FieldConstants.CUST_SHARE_INFO_UPDATE_DATE:
                            entity.setUpdateDate(value.substring(0,4)+"-"+value.substring(4,6)+"-"+value.substring(6,8)+" 00:00:00");
                            break;
                        default:
                            log.error("处理文件{},配置的标准表字段为{},开始下标为{},结束下标为{}",prefixFilename,targetField,startIndex,endIndex);
                    }
                }

                BigDecimal enableShares = lastHoldShares.subtract(frozenShares);
                log.info("HandlerVersionTxtServiceImpl:getCustShareInfo:lastHoldShares={},frozenShares={},enableShares={}",lastHoldShares,frozenShares,enableShares);
                entity.setEnableShares(enableShares);
                entity.setCurrency("156");

                BigDecimal shares = fundNetValueInfoService.getSharesByFundInfo(FundNetValueInfoEntity.builder()
                        .admin(tenant.getTenantName())
                        .fundCode(entity.getFundCode())
                        .fundName(entity.getFundName())
                        .build());

                BigDecimal shareRatio = BigDecimalUtil.getShareRatio(shares, BigDecimalUtil.obj2BigDecimal(entity.getLastHoldShares()));
                entity.setShareRatio(shareRatio);
                log.info("HandlerVersionTxtServiceImpl:getCustShareInfo:shares={},LastHoldShares={},shareRatio={}",shares,entity.getLastHoldShares(),shareRatio);
                entity.setTrustNo(trustNo);
                entity.setAdmin(tenant.getTenantName());
                entity.setCreateTime(new Date());
                entity.setUpdateTime(new Date());

                result.add(entity);
                log.info("HandlerVersionTxtServiceImpl:getCustShareInfo:entity:{}",JSON.toJSONString(entity));
            } catch (Exception ex) {
                log.error("HandlerVersionTxtServiceImpl:getCustShareInfo 发生异常",ex);
            }
        });
        return result;
    }

    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 getSubStringSix(String param){
        String afterParam = param.substring(param.length() - 6);
        String newParam = param.substring(0, param.length() - 6).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;
    }
}
