package com.friday.custody.service.trustService.guosen.service.impl;

import com.alibaba.fastjson.JSON;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.entity.FundNetValueInfoEntity;
import com.friday.custody.entity.FundValuationEntity;
import com.friday.custody.entity.FundValueTableDataInfoEntity;
import com.friday.custody.enums.DataDictionaryTypeEnum;
import com.friday.custody.service.basicService.CustShareInfoService;
import com.friday.custody.service.basicService.impl.*;
import com.friday.custody.service.logicService.DataDictionaryBasicService;
import com.friday.custody.service.trustService.guosen.common.GuosenConstants;
import com.friday.custody.service.trustService.guosen.dto.InvokeGuosenRecordDto;
import com.friday.custody.service.trustService.guosen.service.ProcessGuosenDataService;
import com.friday.custody.utils.BigDecimalUtil;
import com.friday.custody.utils.MatchDataDictionaryKeyUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

@Service(GuosenConstants.VALUATION_LIST_V2_API)
@Slf4j
public class ProcessGuosenFundValueTableDataInfoServiceImpl implements ProcessGuosenDataService {

    @Autowired
    private FundNetValueInfoServiceImpl fundNetValueInfoService;//c

    @Autowired
    private FundInfoServiceImpl fundInfoService;//c
    @Autowired
    private FundValueTableDataInfoServiceImpl fundValueTableDataInfoService;//j
    @Autowired
    private CustShareInfoService custShareInfoService;
    @Autowired
    private DataDictionaryBasicService dataDictionaryBasicService;
    @Autowired
    private DataDictionaryTypeOfFundValuationServiceImpl typeOfFundValuationService;
    @Autowired
    private FundValuationServiceImpl fundValuationService;

    @Override
    public void processData(InvokeGuosenRecordDto dto) {
        if (!CollectionUtils.isEmpty(dto.getRemoteDatas())) {
            //3、封装成标准表的对象
            List<FundValueTableDataInfoEntity> fundValueTableDataInfoEntities = getFundValueTableDataInfoData(dto.getTenant(), dto.getRemoteDatas(), dto.getTrustNo(), dto.getFundInnerCodeAndCodeMap());
            //4、调用 basicservice 的保存数据接口
            fundValueTableDataInfoService.saveData(null, fundValueTableDataInfoEntities);
            //fundValuationEntity
            List<FundValuationEntity> fundValuationEntityList =  getFundValuationInfoData(dto.getTenant(), dto.getTrustNo(), dto.getRemoteDatas(), dto.getFundInnerCodeAndCodeMap());
            fundValuationService.saveData(null, fundValuationEntityList);
            //5 落fundNetValueInfoService表的数据
            Map<String, FundNetValueInfoEntity> fundNetValueInfoData = getFundNetValueInfoData(dto.getTenant(), dto.getNetValueRemoteDatas(), dto.getTrustNo(), dto.getFundInnerCodeAndCodeMap());
            if (fundNetValueInfoData.isEmpty()) {
                //为空 则不落
                return;
            }
            ArrayList<FundNetValueInfoEntity> netValueInfoEntities = new ArrayList<>();
            for (FundValueTableDataInfoEntity fundValueTableDataInfoEntity : fundValueTableDataInfoEntities) {
                if (StringUtils.isEmpty(fundValueTableDataInfoEntity.getKmCode()) || !fundValueTableDataInfoEntity.getKmCode().contains("资产类合计")) {
                    continue;
                }
                FundNetValueInfoEntity fundNetValueInfoEntity = fundNetValueInfoData.get(dto.getTenant().getTenantName() + fundValueTableDataInfoEntity.getInnerFundCode() + fundValueTableDataInfoEntity.getFundName() + fundValueTableDataInfoEntity.getValueDate());
                if (fundNetValueInfoEntity == null) {
                    continue;
                }
                fundNetValueInfoEntity.setTotalAsset(fundValueTableDataInfoEntity.getPortMv());
                netValueInfoEntities.add(fundNetValueInfoEntity);
            }
            fundNetValueInfoService.saveData(null,netValueInfoEntities);
            //4 更改基金持有人信息的基金持有份额比例
//            List<CustShareInfoEntity> updateSharesDto = new ArrayList<>();
//            for (FundNetValueInfoEntity entity : netValueInfoEntities) {
//                List<CustShareInfoEntity> custShareInfoEntities = custShareInfoService.queryByFundInfo(CustShareInfoEntity.builder().innerFundCode(entity.getInnerFundCode()).fundName(entity.getFundName()).netValueDate(entity.getNetValueDate()).build());
//                if (!CollectionUtils.isEmpty(custShareInfoEntities)) {
//                    custShareInfoEntities.forEach(custShareInfoEntity -> {
//                        BigDecimal shareRatio = BigDecimalUtil.getShareRatio(entity.getShares(), custShareInfoEntity.getLastHoldShares());
//                        if (shareRatio != null) {
//                            custShareInfoEntity.setShareRatio(shareRatio);
//                            updateSharesDto.add(custShareInfoEntity);
//                        }
//                    });
//                }
//                if (!CollectionUtils.isEmpty(updateSharesDto)) {
//                    custShareInfoService.updateShares(updateSharesDto);
//                }
//            }
        }
    }

    private List<FundValuationEntity> getFundValuationInfoData(TenantEscrowAuthorizationInfoDto tenant, String trustNo, List<Object> remoteDatas, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        Map<String, String> typeOfFundValuationDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.TYPE_OF_FUND_VALUATION, trustNo);
        Map<String, String> fundValuationKeyValueMap = typeOfFundValuationService.queryKeyValue();
        //2、封装数据
        List<FundValuationEntity> result = new ArrayList<>();
        Map<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            log.info("guosen::getFundValuationInfoData::remoteData{}",JSON.toJSONString(remoteData));
            remoteDataMap = (HashMap<String, String>) remoteData;

//            JSONObject jsonObject = JSONObject.parseObject(remoteData.toString());
//            remoteDataMap = JSONObject.toJavaObject(jsonObject, Map.class);
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"),trustNo);
            String kmCode = MatchDataDictionaryKeyUtil.getKey(typeOfFundValuationDic, remoteDataMap.get("accountCode"));
            String kmName = MatchDataDictionaryKeyUtil.getKey(fundValuationKeyValueMap, kmCode);
            if (StringUtils.isEmpty(kmCode)){
                continue;
            }
            result.add(FundValuationEntity.builder()
                    .kmCode(kmCode)
                    .kmName(kmName)
                    .amount(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("amount")))
                    .portCost(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("cost")))
                    .costBi(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("costRate"), 4))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .vapPrice(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("price")))
                    .mvBl(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("priceRate"), 4))
                    .suspension(remoteDataMap.get("suspension"))
                    .perCost(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("unitCost")))
                    .portIv(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("valuationAppreciation")))
                    .valueDate(remoteDataMap.get("valuationDate"))
                    .portMv(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("value")))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }

    private List<FundValueTableDataInfoEntity> getFundValueTableDataInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        //1、获取字典表数据
        //2、封装数据
        List<FundValueTableDataInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
//            String fundCode = null;
//            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
//                fundCode = StrUtil.getFundCode(fundInnerCodeAndCodeMap, remoteDataMap.get("fundCode"));
//            }
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"),trustNo);
            result.add(FundValueTableDataInfoEntity.builder()
                    .kmCode(remoteDataMap.get("accountCode"))
                    .kmName(remoteDataMap.get("accountName"))
                    .amount(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("amount")))
                    .portCost(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("cost")))
                    .costBi(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("costRate"), 4))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .fundName(remoteDataMap.get("fundName"))
                    .vapPrice(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("price")))
                    .mvBl(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("priceRate"), 4))
                    .suspension(remoteDataMap.get("suspension"))
                    .perCost(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("unitCost")))
                    .portIv(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("valuationAppreciation")))
                    .valueDate(remoteDataMap.get("valuationDate"))
                    .portMv(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("value")))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result;
    }


    private Map<String, FundNetValueInfoEntity> getFundNetValueInfoData(TenantEscrowAuthorizationInfoDto tenant, List<Object> remoteDatas, String trustNo, Map<String, String> fundInnerCodeAndCodeMap) {
        if (CollectionUtils.isEmpty(remoteDatas)) {
            return new HashMap<>();
        }
        //1、获取字典表数据
        //todo 数据字典 复核状态
        Map<String, String> reviewStatusDic = dataDictionaryBasicService.queryWithDetail(DataDictionaryTypeEnum.REVIEW_STATUS_SERVICE, trustNo);
        //2、封装数据
        List<FundNetValueInfoEntity> result = new ArrayList<>();
        HashMap<String, String> remoteDataMap;
        Date now = new Date();
        for (Object remoteData : remoteDatas) {
            remoteDataMap = (HashMap<String, String>) remoteData;
//            String fundCode = null;
//            if (fundInnerCodeAndCodeMap != null && fundInnerCodeAndCodeMap.size() > 0) {
//                fundCode = StrUtil.getFundCode(fundInnerCodeAndCodeMap, remoteDataMap.get("fundCode"));
//            }
            String fundCode = fundInfoService.getFundCodeByInnerFundCode(remoteDataMap.get("fundCode"),trustNo);
            result.add(FundNetValueInfoEntity.builder()
                    .fundName(remoteDataMap.get("fundName"))
                    .innerFundCode(remoteDataMap.get("fundCode"))
                    .netValueDate(remoteDataMap.get("netValueDate"))
                    .checkStatus(MatchDataDictionaryKeyUtil.getKey(reviewStatusDic, remoteDataMap.get("checkStatus")))
                    .netValue(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("netValue"), 4))
                    .totalNetValue(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("totalNetValue"), 4))
                    .assetValue(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("fundAssets")))
                    .shares(BigDecimalUtil.obj2BigDecimal(remoteDataMap.get("fundShares")))
                    .uniqueKey(tenant.getTenantName() + remoteDataMap.get("fundCode") + remoteDataMap.get("fundName") + remoteDataMap.get("netValueDate"))
                    .fundCode(fundCode)
                    .trustNo(trustNo)
                    .admin(tenant.getTenantName())
                    .createTime(now)
                    .updateTime(now)
                    .build());
        }
        return result.stream().collect(Collectors.toMap(FundNetValueInfoEntity::getUniqueKey, x -> x));
    }
}
