package com.liquidnet.service.account.wallet.service.impl;

import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.account.common.FinConstants;
import com.liquidnet.service.account.funding.dto.FundingQueryBalanceParam;
import com.liquidnet.service.account.funding.dto.FundingQueryBalanceResult;
import com.liquidnet.service.account.funding.service.FundingAPIService;
import com.liquidnet.service.account.funding.vo.FundingAccountInfo;
import com.liquidnet.service.account.util.FinUtil;
import com.liquidnet.service.account.wallet.bo.FinWalletBalanceBo;
import com.liquidnet.service.account.wallet.entity.FinWallet;
import com.liquidnet.service.account.wallet.mapper.FinWalletMapper;
import com.liquidnet.service.account.wallet.service.FinWalletService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * FinWalletServiceImpl.class
 *
 * @author zhanggb
 * Created by IntelliJ IDEA at 2020/10/21
 */
@Service
public class FinWalletServiceImpl implements FinWalletService {
    private static final Logger log = LoggerFactory.getLogger(FinWalletServiceImpl.class);
    @Autowired
    private FinWalletMapper walletMapper;
    @Autowired
    private FundingAPIService fundingAPIService;

    @Override
    public String generateSeqForWalletNo(String currencyCode) {
        return currencyCode.concat(String.format("%07d", FinUtil.nextIncrId(FinConstants.SEQ_WL_NUMBER.concat(currencyCode))));
//        return currencyCode.concat(String.format("%07d", walletMapper.generateSeqNo(FinConstants.SEQ_WL_NUMBER.concat(currencyCode))));
    }

    @Override
    public int addWallet(FinWallet wallet) {
        return walletMapper.insertSelective(wallet);
    }

    @Override
    public FinWallet query(String walletNo) {
        return walletMapper.selectByPrimaryKey(walletNo);
    }

    @Override
    public int updateWallet(FinWallet wallet) {
        return walletMapper.updateByPrimaryKeySelective(wallet);
    }

    @Override
    public List<FinWallet> query(Map<String, Object> parameter) {
        return walletMapper.select(parameter);
    }

//    @Override
//    public List<FinWallet> queryByWalletNoAndAliasAndCurrencyForFuzzy(String fuzzySearch, String finId) {
//        return walletMapper.selectByWalletNoAndAliasAndCurrencyForFuzzy(fuzzySearch, finId);
//    }

    @Override
    public FinWalletBalanceBo queryBalance(String finId, String walletNo) {
        Map<String, List<String>> finIdWithAccNoMap = new HashMap<>();
        List<String> accList = new ArrayList<>();
        String availableAccNo = FinUtil.getAccNo(FinConstants.AccType.AVAILABLE.getVal(), walletNo);
        String pendingAccNo = FinUtil.getAccNo(FinConstants.AccType.PENDING.getVal(), walletNo);
        String frozenAccNo = FinUtil.getAccNo(FinConstants.AccType.FROZEN.getVal(), walletNo);
        accList.add(availableAccNo);
        accList.add(pendingAccNo);
        accList.add(frozenAccNo);
        finIdWithAccNoMap.put(finId, accList);

        FundingQueryBalanceParam fundingQueryBalanceParam = new FundingQueryBalanceParam();
        fundingQueryBalanceParam.setFinIdWithAccNoMap(finIdWithAccNoMap);
        FundingQueryBalanceResult fundingQueryBalanceResult = fundingAPIService.queryBalance(fundingQueryBalanceParam);
        List<FundingAccountInfo> fundingAccountInfoList = null;
        if (fundingQueryBalanceResult.isSuccess()) {
            fundingAccountInfoList = fundingQueryBalanceResult.getFundingAccountInfoList();

            FinWalletBalanceBo bo = FinWalletBalanceBo.getNew();
            bo.setWalletNo(walletNo);
            bo.setBalanceAvailable(BigDecimal.ZERO);
            bo.setBalancePending(BigDecimal.ZERO);
            bo.setBalanceFrozen(BigDecimal.ZERO);

            fundingAccountInfoList.forEach(r -> {
                if (availableAccNo.equals(r.getAccNo())) {
                    bo.setBalanceAvailable(r.getBalance());
                }
                if (pendingAccNo.equals(r.getAccNo())) {
                    bo.setBalancePending(r.getBalance());
                }
                if (frozenAccNo.equals(r.getAccNo())) {
                    bo.setBalanceFrozen(r.getBalance());
                }
            });

            return bo;
        }
        log.info("Failed of queryOne:walletNo:{}:result:{}", walletNo, JsonUtils.toJson(fundingQueryBalanceResult));
        return null;
    }
}
