package com.hzs.member.account.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzs.common.core.constant.msg.FinanceMsgConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.CommonUtil;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.account.CuMemberTrade;
import com.hzs.common.domain.member.account.CuMemberTransfer;
import com.hzs.common.domain.member.account.CuMemberTransferExt;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.ext.CuMemberExt;
import com.hzs.common.domain.system.config.BdTransfer;
import com.hzs.common.core.utils.TransactionUtils;
import com.hzs.member.account.dto.CuMemberAccountParam;
import com.hzs.member.account.mapper.CuMemberTransferMapper;
import com.hzs.member.account.service.ICuMemberAccountService;
import com.hzs.member.account.service.ICuMemberBaseService;
import com.hzs.member.account.service.ICuMemberTradeService;
import com.hzs.member.account.service.ICuMemberTransferService;
import com.hzs.member.account.vo.CuMemberTransferVO;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.ITransferServiceApi;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * <p>
 * 会员转账表 服务实现类
 * </p>
 *
 * @author hzs
 * @since 2022-09-06
 */
@Service
public class CuMemberTransferServiceImpl extends ServiceImpl<CuMemberTransferMapper, CuMemberTransfer> implements ICuMemberTransferService {

    @Autowired
    ICuMemberService cuMemberService;

    @Autowired
    ICuMemberAccountService cuMemberAccountService;

    @Autowired
    ICuMemberTradeService cuMemberTradeService;

    @DubboReference
    ITransferServiceApi transferServiceApi;


    @Autowired
    CuMemberTransferMapper cuMemberTransferMapper;


    @Autowired
    ICuMemberBaseService cuMemberBaseService;


    @Override
    public Boolean isBloodLine(Long pkMember, Long toPkMember) {
        if (Boolean.TRUE.equals(isBloodKinshipOnUmbrella(pkMember, toPkMember))) {
            return true;
        }
        return isBloodKinshipUnderUmbrella(pkMember, toPkMember);
    }

    @Override
    public BdTransfer getBdTransfer(Integer pkCountry) {
        return transferServiceApi.queryTransfer(pkCountry).getData();
    }


    @Override
    public Boolean isBloodKinshipOnUmbrella(Long pkMember, Long toPkMember) {
        //查找血缘伞上，推荐人
        List<CuMemberExt> cuMemberUp = cuMemberService.queryBloodKinshipOnUmbrella(pkMember);
        Optional<CuMemberExt> upOptional = cuMemberUp.stream().filter(up -> toPkMember.equals(up.getPkId())).findFirst();
        return upOptional.isPresent();
    }

    @Override
    public Boolean isBloodKinshipUnderUmbrella(Long pkMember, Long toPkMember) {
        //查找血缘伞下，推荐人
        List<CuMemberExt> cuMemberDown = cuMemberService.queryBloodKinshipUnderUmbrella(pkMember);
        Optional<CuMemberExt> downOptional = cuMemberDown.stream().filter(down -> toPkMember.equals(down.getPkId())).findFirst();
        return downOptional.isPresent();
    }

    @Override
    public Boolean isPlaceSponsorOnline(Long pkMember, Long toPkMember) {
        if (Boolean.TRUE.equals(isPlaceSponsorOnUmbrella(pkMember, toPkMember))) {
            return true;
        }
        return isPlaceSponsorUnderUmbrella(pkMember, toPkMember);
    }

    @Override
    public Boolean isPlaceSponsorOnUmbrella(Long pkMember, Long toPkMember) {
        // TODO 此处会查询整颗树，会出现问题
        List<CuMemberExt> memberPlaceOn = cuMemberService.queryPlaceSponsorOnUmbrella(pkMember);
        Optional<CuMemberExt> onPlaceOptional = memberPlaceOn.stream().filter(placeOn -> toPkMember.equals(placeOn.getPkId())).findFirst();
        return onPlaceOptional.isPresent();
    }

    @Override
    public Boolean isPlaceSponsorUnderUmbrella(Long pkMember, Long toPkMember) {
        List<CuMemberExt> memberPlaceUnder = cuMemberService.queryPlaceSponsorUnderUmbrella(pkMember);
        Optional<CuMemberExt> underPlaceOptional = memberPlaceUnder.stream().filter(placeUnder -> toPkMember.equals(placeUnder.getPkId())).findFirst();
        return underPlaceOptional.isPresent();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer saveMemberTransferInfo(CuMemberTransfer cuMemberTransfer, CuMemberAccount cuMemberAccount, CuMemberAccount toMemberAccount) {
        Integer row = baseMapper.insert(cuMemberTransfer);
        this.updateTradeAndBalancd(cuMemberTransfer, ETransferType.TRANSFER_OUT.getValue());
        this.updateTradeAndBalancd(cuMemberTransfer, ETransferType.TRANSFER_IN.getValue());
       // ChargingBonusDetail(cuMemberTransfer, cuMemberAccount, toMemberAccount);
        return row;
    }

    /**
     * 奖金交易流水扣费
     *
     * @param cuMemberTransfer
     */
    private void ChargingBonusDetail(CuMemberTransfer cuMemberTransfer, CuMemberAccount cuMemberAccount, CuMemberAccount toMemberAccount) {
        Map<Long, Long> idsMap;
        List<CuMemberAccount> memberAccountList;
        Integer pkAccount = cuMemberTransfer.getPkAccount();
        Integer pkToAccount = cuMemberTransfer.getPkToAccount();
        String transferCode = cuMemberTransfer.getTransferCode();
        //转出方
        if (cuMemberBaseService.getAccountValueById(pkAccount).equals(EAccount.BONUS.getValue())) {
            memberAccountList = new ArrayList<>();
            memberAccountList.add(cuMemberAccount);
            idsMap = new HashMap<>();
            idsMap.put(cuMemberTransfer.getPkMember(), cuMemberTransfer.getPkId());
            saveTransferMemberTradeDetailAndBonus(memberAccountList, ETransferType.TRANSFER_OUT.getValue(), transferCode, idsMap);
        }
        //转入方
        if (cuMemberBaseService.getAccountValueById(pkToAccount).equals(EAccount.BONUS.getValue())) {
            memberAccountList = new ArrayList<>();
            memberAccountList.add(toMemberAccount);
            idsMap = new HashMap<>();
            idsMap.put(cuMemberTransfer.getPkMember(), cuMemberTransfer.getPkId());
            saveTransferMemberTradeDetailAndBonus(memberAccountList, ETransferType.TRANSFER_IN.getValue(), transferCode, idsMap);
        }
    }

    /**
     * 插入奖金流水明细
     *
     * @param memberAccountList 账户信息
     * @param type              类型
     * @param businessCode      业务编码
     */
    private void saveTransferMemberTradeDetailAndBonus(List<CuMemberAccount> memberAccountList, Integer type, String businessCode, Map<Long, Long> idsMap) {
        //转出方
        if (type.equals(ETransferType.TRANSFER_OUT.getValue())) {
            cuMemberBaseService.handleMemberTradeDetailAndBonus(memberAccountList, businessCode, idsMap, EConsumeType.TRANSFER.getValue());
        } else {
            cuMemberBaseService.saveMemberTradeDetail(businessCode);
        }
    }


    /**
     * 更新交易流水和余额
     *
     * @param cuMemberTransfer 提现信息
     * @param type             转入类型
     */
    private Integer updateTradeAndBalancd(CuMemberTransfer cuMemberTransfer, int type) {
        CuMemberTrade cuMemberTrade = type == (ETransferType.TRANSFER_OUT.getValue()) ? this.getCuMemberTradeToTransferOut(cuMemberTransfer) : this.getCuMemberTradeToTransferIn(cuMemberTransfer);
        cuMemberTradeService.save(cuMemberTrade);
        //更新余额表
        Long pkMember = cuMemberTransfer.getPkMember();
        Long toPkMember = cuMemberTransfer.getToPkMember();
        //用户
        Long memberId = type == (ETransferType.TRANSFER_OUT.getValue()) ? pkMember : toPkMember;
        int accountType = cuMemberTransfer.getPkAccount();
        int toAccountType = cuMemberTransfer.getPkToAccount();
        //账户类型
        int pkAccount = type == (ETransferType.TRANSFER_OUT.getValue()) ? accountType : toAccountType;

        //转账金额
        BigDecimal transferMoney = type == (ETransferType.TRANSFER_OUT.getValue()) ? cuMemberTransfer.getTransferMoney() : cuMemberTransfer.getIssuedAmount();
        BigDecimal amount = type == (ETransferType.TRANSFER_OUT.getValue()) ? transferMoney.negate() : transferMoney;
        Integer pkAccountValue = cuMemberBaseService.getAccountValueById(pkAccount);

        CuMemberAccountParam param = CuMemberAccountParam.builder().pkMember(memberId)
                .accountType(pkAccountValue).amount(amount).pkModified(cuMemberTransfer.getPkCreator())
                .accountClassify(ETradeClassify.TRANSFER.getValue()).pkCountry(cuMemberTransfer.getPkCountry())
                .transferType(type).build();

        return cuMemberAccountService.updateMemberAccountByMemberCode(param);
    }

    /**
     * 构造转出方交易明细
     *
     * @param cuMemberTransfer 转账信息
     * @return CuMemberTrade
     */
    private CuMemberTrade getCuMemberTradeToTransferOut(CuMemberTransfer cuMemberTransfer) {
        Long pkMember = cuMemberTransfer.getPkMember();
        Long toPkMember = cuMemberTransfer.getToPkMember();
        CuMember member = cuMemberService.getMember(pkMember);
        CuMember toMember = cuMemberService.getMember(toPkMember);
        //提现金额
        BigDecimal tradeAmount = cuMemberTransfer.getTransferMoney();
        BigDecimal amount = tradeAmount.negate();
        int accountType = cuMemberTransfer.getPkAccount();
        String tradeCode = CommonUtil.createSerialNumber(EOrderPrefix.TRANSFER_CODE.getValue());
        //查询余额
        BigDecimal balance = cuMemberAccountService.selectBalanceByMemberCode(pkMember, cuMemberBaseService.getAccountValueById(accountType));
        CuMemberTrade memberTrade = CuMemberTrade.builder().pkMember(pkMember)
                .tradeCode(tradeCode)
                .pkAccount(cuMemberTransfer.getPkAccount())
                .tradeType(ETradeType.TRANSFER.getValue())
                .tradeClassify(ETradeClassify.TRANSFER.getValue())
                .pkRate(cuMemberTransfer.getPkRate())
                .tradeAmount(amount)
                .tradeBeforeBalance(balance)
                .tradeBalance(balance.add(amount))
                .sourceCode(cuMemberTransfer.getTransferCode())
                .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .remarks(member.getMemberCode() + "(" + member.getMemberName() + ") " + TransactionUtils.getContent(FinanceMsgConstants.TRANSFER_ACCOUNTS) + toMember.getMemberCode() + "(" + toMember.getMemberName() + ") " + TransactionUtils.getContent(FinanceMsgConstants.AMOUNT_MONEY)  + tradeAmount)
                .build();
        memberTrade.setPkCountry(cuMemberTransfer.getPkCountry());
        memberTrade.setPkCreator(cuMemberTransfer.getPkCreator());
        return memberTrade;
    }


    /**
     * 构造转出方交易明细
     *
     * @param cuMemberTransfer 转账信息
     * @return CuMemberTrade
     */
    private CuMemberTrade getCuMemberTradeToTransferIn(CuMemberTransfer cuMemberTransfer) {
        Long pkMember = cuMemberTransfer.getPkMember();
        Long toPkMember = cuMemberTransfer.getToPkMember();
        CuMember member = cuMemberService.getMember(pkMember);
        CuMember toMember = cuMemberService.getMember(toPkMember);
        //提现金额
        BigDecimal tradeAmount = cuMemberTransfer.getIssuedAmount();
        int accountType = cuMemberTransfer.getPkToAccount();
        String tradeCode = CommonUtil.createSerialNumber(EOrderPrefix.TRANSFER_CODE.getValue());
        //查询余额
        BigDecimal balance = cuMemberAccountService.selectBalanceByMemberCode(toPkMember, cuMemberBaseService.getAccountValueById(accountType));
        CuMemberTrade memberTrade = CuMemberTrade.builder().pkMember(toPkMember)
                .tradeCode(tradeCode)
                .pkAccount(cuMemberTransfer.getPkToAccount())
                .tradeType(ETradeType.TRANSFER.getValue())
                .tradeClassify(ETradeClassify.TRANSFER.getValue())
                .pkRate(cuMemberTransfer.getPkRate())
                .tradeAmount(tradeAmount)
                .tradeBeforeBalance(balance)
                .tradeBalance(balance.add(tradeAmount))
                .sourceCode(cuMemberTransfer.getTransferCode())
                .tradeStatue(ETradeStatus.TAKE_EFFECT.getValue())
                .remarks(toMember.getMemberCode() + "(" + toMember.getMemberName() + ") " + TransactionUtils.getContent(FinanceMsgConstants.ACCEPT_TRANSFER) + member.getMemberCode() + "(" + member.getMemberName() + ") " + TransactionUtils.getContent(FinanceMsgConstants.AMOUNT_MONEY)  + tradeAmount)
                .build();
        memberTrade.setPkCountry(cuMemberTransfer.getPkCountry());
        memberTrade.setPkCreator(cuMemberTransfer.getPkCreator());
        return memberTrade;
    }


    @Override
    public Object[] selectMemberTransferList(CuMemberTransferVO cuMemberTransferVO) {
        CuMemberTransferVO memberTransferVO;
        List<CuMemberTransferVO> cuMemberTransferVOS = new ArrayList<>();
        List<CuMemberTransferExt> cuMemberTransferExts = baseMapper.selectMemberTransferList(cuMemberTransferVO);
        if (CollUtil.isNotEmpty(cuMemberTransferExts)) {
            for (CuMemberTransferExt cuMemberTransferExt : cuMemberTransferExts) {
                memberTransferVO = new CuMemberTransferVO();
                BeanUtils.copyProperties(cuMemberTransferExt, memberTransferVO);
                this.setPublicParam(memberTransferVO, cuMemberTransferExt);
                cuMemberTransferVOS.add(memberTransferVO);
            }
        }
        Object[] objects = new Object[]{cuMemberTransferExts, cuMemberTransferVOS};
        return objects;
    }


    /**
     * 页面显示公用参数
     *
     * @param cuMemberTransferVO 转账VO
     * @param memberTransfer     转账信息
     */
    private void setPublicParam(CuMemberTransferVO cuMemberTransferVO, CuMemberTransferExt memberTransfer) {
        BigDecimal exchangeRate;
        Integer pkRate = memberTransfer.getPkRate();
        if (null != pkRate) {
            //汇率
            exchangeRate = cuMemberBaseService.getCurrencyById(pkRate).getInExchangeRate();
        } else {
            //取最新的汇率
            CurrencyDTO currencyDTO = cuMemberBaseService.getCurrency(cuMemberTransferVO.getPkCountry());
            exchangeRate = currencyDTO.getInExchangeRate();
        }
        //翻译key键
        Integer pkAccount = cuMemberTransferVO.getPkAccount();
        cuMemberTransferVO.setPkAccount(cuMemberBaseService.translateAccountValue(pkAccount));
        Integer pkToAccount = cuMemberTransferVO.getPkToAccount();
        cuMemberTransferVO.setPkToAccount(cuMemberBaseService.translateAccountValue(pkToAccount));
        //转账本币
        if (null != exchangeRate) {
            BigDecimal settleTransferMoney = memberTransfer.getTransferMoney().divide(exchangeRate, 4, RoundingMode.HALF_UP);
            BigDecimal settleIssuedAmount = memberTransfer.getIssuedAmount().divide(exchangeRate, 4, RoundingMode.HALF_UP);
            BigDecimal settleServiceCharge = memberTransfer.getServiceCharge().divide(exchangeRate, 4, RoundingMode.HALF_UP);
            cuMemberTransferVO.setExchangeRate(exchangeRate);
            cuMemberTransferVO.setSettleTransferMoney(settleTransferMoney);
            cuMemberTransferVO.setSettleIssuedAmount(settleIssuedAmount);
            cuMemberTransferVO.setSettleServiceCharge(settleServiceCharge);
        }
    }

}

