package com.hzs.member.account.controller.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.json.JSONUtil;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.constant.CountryConstants;
import com.hzs.common.core.constant.MemberFieldConstants;
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.core.utils.StringUtils;
import com.hzs.common.core.utils.reflect.ReflectUtils;
import com.hzs.common.core.web.controller.BaseController;
import com.hzs.common.core.web.domain.AjaxResult;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.account.CuMemberTransfer;
import com.hzs.common.domain.member.base.CuMember;
import com.hzs.common.domain.member.detail.CuMemberServiceLog;
import com.hzs.common.domain.member.detail.CuMemberServiceLogExt;
import com.hzs.common.domain.member.ext.CuMemberExt;
import com.hzs.common.domain.system.config.BdAccount;
import com.hzs.common.domain.system.config.BdTransfer;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.util.TransactionUtils;
import com.hzs.member.account.dto.CuMemberRechargeAccountParam;
import com.hzs.member.account.dto.CuMemberTransferParam;
import com.hzs.member.account.service.ICuMemberAccountService;
import com.hzs.member.account.service.ICuMemberBaseService;
import com.hzs.member.account.service.ICuMemberTransferService;
import com.hzs.member.account.vo.BdAccountVO;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.member.base.vo.UpPolicyCurrencyVO;
import com.hzs.member.detail.service.ICuMemberServiceLogService;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IAccountServiceApi;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.ITradeConfigServiceApi;
import com.hzs.system.config.dto.GradeDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 会员提现表 前端控制器
 */
@RestController
@RequestMapping("/api/transfer")
public class ApiCuMemberTransferController extends BaseController {

    @Autowired
    private ICuMemberService iCuMemberService;
    @Autowired
    private ICuMemberTransferService iCuMemberTransferService;
    @Autowired
    private ICuMemberBaseService iCuMemberBaseService;
    @Autowired
    private ICuMemberAccountService iCuMemberAccountService;
    @Autowired
    private ICuMemberServiceLogService iCuMemberServiceLogService;

    @DubboReference
    IAccountServiceApi iAccountServiceApi;
    @DubboReference
    IGradeServiceApi iGradeServiceApi;
    @DubboReference
    ITradeConfigServiceApi iTradeConfigServiceApi;


    /**
     * 根据用户编号查询中文脱敏
     *
     * @return
     */
    @GetMapping("/chinese-name")
    public AjaxResult chineseDesensitization(String memberCode) {
        if (StringUtils.isEmpty(memberCode)) {
            return AjaxResult.error("编号不能为空");
        }

        CuMember member = iCuMemberService.getMemberByCode(memberCode);
        if (member != null) {
            //转出账户会员
            Long pk_member = SecurityUtils.getUserId();

            String memberName = member.getMemberName();
            //如果是转入会员显示昵称
            if (!pk_member.equals(member.getPkId())) {
                memberName = iCuMemberBaseService.getMemberNameByVertex(member);
            } else {
                memberName = DesensitizedUtil.chineseName(memberName);
            }
            return AjaxResult.success().put("memberName", memberName);
        } else {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.RECHAGER_USER_NOT_EXIST));
        }
    }

    /**
     * 查询可转账币种
     */
    @GetMapping("/transfer-account")
    public AjaxResult getAccount() {
        Integer pkCountry = SecurityUtils.getPkCountry();
        Long pkMember = SecurityUtils.getUserId();
        List<BdAccount> accountList = iCuMemberBaseService.getAccountByCountry(EAccountProperty.IS_TRANSFER.getValue(), pkCountry);
        //查询用户、体系是否开通政策币
        List<CuMemberServiceLog> logList = getServiceLogValue(pkCountry, pkMember);
        if (CollUtil.isNotEmpty(logList)) {
            //同时配置会员、体系以会员为准
            if (logList.size() >= 2) {
                logList = logList.stream().filter(data -> data.getBusinessScope().equals(EBusinessScope.MEMBER.getValue())).collect(Collectors.toList());
            }
            UpPolicyCurrencyVO upPolicyCurrencyVO = JSONUtil.toBean(logList.get(0).getNewValue(), UpPolicyCurrencyVO.class);
            //政策币启用状态 0 已启用 1已禁用 EnableStatus
            Integer enableStatus = upPolicyCurrencyVO.getEnableStatus();
            //政策币转账状态 1允许 2禁止 EPopupType
            Integer transfer = upPolicyCurrencyVO.getTransfer();
            if (null != enableStatus && null != transfer) {
                if (enableStatus.equals(EnableStatus.ENABLE.getValue()) && transfer.equals(EPopupType.ALLOW.getValue())) {
                    BdAccount bdAccount = iAccountServiceApi.getBdAccountByFieldValue(pkCountry, EAccount.POLICY.getValue()).getData();
                    accountList.add(bdAccount);
                }
            }
        }
        //根据配置的账户白名单增加可转账的账户
        this.getAccountByTransferWhite(pkMember, pkCountry, accountList);
        return AjaxResult.success(BeanUtil.copyToList(accountList, BdAccountVO.class));
    }

    /**
     * 根据配置的账户白名单增加可转账的账户
     *
     * @param pkMember    会员ID
     * @param pkCountry   国家
     * @param accountList 可转账账户
     */
    private void getAccountByTransferWhite(Long pkMember, Integer pkCountry, List<BdAccount> accountList) {
        //查询转账账户白名单配置
        List<Integer> transferWhiteList = iTradeConfigServiceApi.selectTransferWhiteByPkMember(pkMember, pkCountry).getData();
        if (CollUtil.isNotEmpty(transferWhiteList)) {
            List<BdAccount> allAccounts = iCuMemberBaseService.getAccountByCountryId(pkCountry);
            Map<Integer, BdAccount> map = allAccounts.stream().collect(Collectors.toMap(BdAccount::getPkId, o -> o));
            transferWhiteList.forEach(pkAccount -> {
                BdAccount bdAccount = map.get(pkAccount);
                if (null != bdAccount) {
                    accountList.add(bdAccount);
                }
            });
        }
    }

    /**
     * 查询用户、体系是否开通政策币
     *
     * @param pkCountry 国家ID
     * @param pkMember  会员ID
     * @return List<CuMemberServiceLog>
     */
    private List<CuMemberServiceLog> getServiceLogValue(Integer pkCountry, Long pkMember) {
        //查询体系
        CuMember cuMember = iCuMemberService.queryMember(pkMember);
        Long pkVertex = cuMember.getPkVertex();

        List<Integer> editTypeList = Collections.singletonList(EApprovalBusiness.POLICY_CURRENCY_YES_NO.getValue());
        CuMemberServiceLogExt log = new CuMemberServiceLogExt();
        log.setPkMember(pkMember);
        log.setPkVertex(pkVertex);
        log.setPkCountry(pkCountry);
        log.setEditTypeList(editTypeList);
        return iCuMemberServiceLogService.selectServiceValue(log);
    }

    /**
     * 用户转账
     *
     * @param cuMemberTransferParam 转账入参
     * @return AjaxResult
     */
    @PostMapping("/add")
    @RepeatSubmitSimple
    public AjaxResult addTransferInfo(@RequestBody CuMemberTransferParam cuMemberTransferParam) {
        //是否走血缘
        Integer pkCountry = SecurityUtils.getPkCountry();
        Long pkMember = SecurityUtils.getUserId();
        String memberCode = SecurityUtils.getMemberCode();

        CuMemberExt member = iCuMemberService.getMemberByCode(memberCode);
        Assert.notNull(member, TransactionUtils.getContent(FinanceMsgConstants.TRANSFER_OUT_USER_NOT_EXIST));

        //币种ID
        Integer pkAccount = cuMemberTransferParam.getPkAccount();
        if (null == pkAccount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.TRANSFER_OUT_ACCOUNT_NOT_EMPTY));
        }

        //校验支付密码
        String payPwd = member.getPayPwd();
        if (StringUtils.isEmpty(payPwd) || !SecurityUtils.matchesPassword(cuMemberTransferParam.getPayPwd(), payPwd)) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.PAYMENT_PASSWORD_ERROR));
        }

        //接收方
        String toMemberCode = cuMemberTransferParam.getToMemberCode();

        BdAccount bdAccount = iAccountServiceApi.getAccount(pkAccount).getData();
        Integer accountsType = bdAccount.getFieldValue();
        //中国区校验
        if (pkCountry.equals(CountryConstants.CHINA_COUNTRY)) {
            Integer expireStatus = member.getExpireStatus();
            //休止期的会员不允许转账
            Boolean restPeriodStatus = iCuMemberBaseService.restPeriodMemberUserWallet(pkMember, expireStatus, accountsType);
            if (restPeriodStatus) {
                return AjaxResult.error(FinanceMsgConstants.REST_PERIOD_NOT_TRANSFER);
            }
            //已终止会员不允许转账
            if (expireStatus.equals(EExpireStatus.TERMINATED.getValue())) {
                return AjaxResult.error(FinanceMsgConstants.TERMINATED_NOT_TRANSFER);
            }

            //校验是否实名
            Boolean existRealName = iCuMemberBaseService.isExistRealName(pkMember, pkCountry, EBusinessModule.TRANSFER_ACCOUNTS.getValue());
            if (!existRealName) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.REAL_NAME_NOT_EXIST));
            }
        }
        BigDecimal transferMoney = cuMemberTransferParam.getTransferMoney();
        if (transferMoney.compareTo(BigDecimal.ZERO) <= 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.INCORRECT_TRANSFER_AMOUNT));
        }

        //配置信息
        BdTransfer bdTransfer = iCuMemberTransferService.getBdTransfer(pkCountry);
        if (null == bdTransfer) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.CONFIGURE_TRANSFER_CONFIGURATION));
        }
        //取整
        transferMoney = computeRounding(bdTransfer, transferMoney);

        BigDecimal minAmount = bdTransfer.getMinAmount();
        BigDecimal maxAmount = bdTransfer.getMaxAmount();
        if (transferMoney.compareTo(minAmount) < 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.CANNOT_LOWER_THAN_MINIMUM_TRANSFER_AMOUNT));
        }
        if (transferMoney.compareTo(maxAmount) > 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.CANNOT_GREATER_MAXIMUM_TRANSFER_AMOUNT));
        }

        if (bdTransfer.getIsRounding().equals(EYesNo.YES.getIntValue())) {
            //倍数
            Integer multiple = bdTransfer.getMultiple();
            //取余
            BigDecimal[] multiples = transferMoney.divideAndRemainder(new BigDecimal(multiple));
            if (multiples[1].compareTo(BigDecimal.ZERO) != 0) {
                return AjaxResult.error("转账金额不是" + multiple + "倍数");
            }
        }

        //查询账户信息
        CuMemberAccount cuMemberAccount = iCuMemberAccountService.queryCuMemberAccountByPkMember(pkMember);
        //是否转账
        Integer isTransfer = cuMemberAccount.getIsTransfer();
        //是否允许转账
        if (isTransfer.equals(EYesNo.NO.getIntValue())) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.NOT_ALLOWED_TRANSFER));
        }

        CuMember toMember = iCuMemberService.getMemberByCode(toMemberCode);
        Assert.notNull(toMember, TransactionUtils.getContent(FinanceMsgConstants.TRANSFER_IN_USER_NOT_EXIST));
        Long toPkMember = toMember.getPkId();
        //禁止登录的用户无法接受转账
        if (toMember.getAccountStatus().equals(EAccountStatus.SHUT_DOWN.getValue())) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.TRANSFER_IN_USER_NOT_ALLOWED));
        }
        //中国区校验
        if (pkCountry.equals(CountryConstants.CHINA_COUNTRY)) {
            GradeDTO gradeDTO = iGradeServiceApi.getGradeByGradeValue(EGrade.START_UP.getValue(), pkCountry).getData();
            //结算等级为1 (目前是会员)不允许转账 转入方
            if (member.getPkSettleGrade().equals(gradeDTO.getPkId())) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.MEMBER_IN_NOT_ALLOWED_TRANSFER));
            }
            //结算等级为1 (目前是会员)不允许转账 转出方
            if (toMember.getPkSettleGrade().equals(gradeDTO.getPkId())) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.MEMBER_OUt_NOT_ALLOWED_TRANSFER));
            }
        }
        if (pkMember.equals(toPkMember)) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.NOT_TRANSFER_MONEY_TO_YOURSELF));
        }
        if (!member.getPkSettleCountry().equals(toMember.getPkSettleCountry())) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.NOT_ALLOWED_CROSS_BORDER_TRANSFER));
        }

        //个人转账状态（0正常、1:全网）
        Integer transferStatus = cuMemberAccount.getTransferStatus();
        // 没有配置全网转账时，校验血缘线
        if (transferStatus.equals(EYesNo.YES.getIntValue())) {
            //血缘线配置 是否血缘(0是 1 否)
            Integer reference = bdTransfer.getIsReference();
            if (isReference(transferStatus, reference, pkMember, toPkMember)) {
                // 走血缘
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.RECEIVER_NUMBER_NOT_IN_BLOOD_LINE));
            }
        }

        //币种value值
        Integer pkAccountValue = iCuMemberBaseService.getAccountValueById(pkAccount);
        //查询余额
        BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + pkAccountValue);
        BigDecimal lockAccount = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_TRANSFER_ACCOUNT + pkAccountValue);
        if (null != lockAccount && lockAccount.compareTo(BigDecimal.ZERO) > 0) {
            balance = balance.subtract(lockAccount);
        }

        //余额不足
        if (balance.compareTo(transferMoney) < 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.BALANCE_NOT_ENOUGH));
        }
        //手续费金额
        BigDecimal serviceRatio = this.computeServiceCharge(bdTransfer, transferMoney);
        //可用金额
        BigDecimal issuedAmount = transferMoney.subtract(serviceRatio);

        //单号
        String code = CommonUtil.createSerialNumber(EOrderPrefix.TRANSFER_CODE.getValue());
        //汇率
        CurrencyDTO currencyDTO = iCuMemberBaseService.getCurrency(pkCountry);
        //转入币种ID（从配置中获取）
        Integer toPkAccount = iAccountServiceApi.getPkAccount(pkAccount).getData();

        CuMemberTransfer cuMemberTransfer = CuMemberTransfer.builder().pkMember(pkMember)
                .pkAccount(pkAccount).transferCode(code).toPkMember(toPkMember)
                .pkToAccount(toPkAccount).pkRate(currencyDTO.getPkId())
                .transferMoney(transferMoney).remarks(cuMemberTransferParam.getRemarks())
                .serviceCharge(serviceRatio).issuedAmount(issuedAmount)
                .build();
        cuMemberTransfer.setPkCountry(pkCountry);
        cuMemberTransfer.setPkCreator(pkMember);
        CuMemberAccount toMemberAccount = iCuMemberAccountService.queryCuMemberAccountByPkMember(cuMemberTransfer.getToPkMember());
        return toAjax(iCuMemberTransferService.saveMemberTransferInfo(cuMemberTransfer, cuMemberAccount, toMemberAccount));
    }


    /**
     * 判断是否走血缘
     *
     * @param transferStatus 个人转账状态（0正常、1:全网）
     * @param reference      血缘线配置 是否血缘(0是 1 否)
     * @param pkMember       转出方
     * @param toPkMember     转入方
     * @return Boolean
     */
    private Boolean isReference(Integer transferStatus, Integer reference, Long pkMember, Long toPkMember) {
        return (reference.equals(EYesNo.YES.getIntValue()) || transferStatus.equals(EYesNo.YES.getIntValue())) && !iCuMemberTransferService.isBloodLine(pkMember, toPkMember);
    }

    /**
     * 计算手续费金额
     *
     * @param bdTransfer    转账配置
     * @param transferMoney 转账金额
     * @return BigDecimal
     */
    private BigDecimal computeServiceCharge(BdTransfer bdTransfer, BigDecimal transferMoney) {
        //手续费类型
        Integer serviceType = bdTransfer.getServiceType();
        BigDecimal serviceRatio = bdTransfer.getServiceRatio();
        //按金额
        if (serviceType.equals(ECalType.VALUE.getValue())) {
            return serviceRatio;
        } else {//按比例
            //转化为百分比比率
            BigDecimal serviceChargeeRatio = serviceRatio.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
            //手续费金额 = 本次提现金额 * 手续费比例
            return transferMoney.multiply(serviceChargeeRatio).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
    }

    /**
     * 取整
     *
     * @param bdTransfer    转账配置
     * @param transferMoney 转账金额
     * @return BigDecimal
     */
    private BigDecimal computeRounding(BdTransfer bdTransfer, BigDecimal transferMoney) {
        BigDecimal roundIngAmount;
        Integer isRounding = bdTransfer.getIsRounding();
        if (isRounding.equals(EYesNo.YES.getIntValue())) {
            //向下取整
            roundIngAmount = transferMoney.setScale(0, BigDecimal.ROUND_DOWN);
        } else {
            roundIngAmount = transferMoney;
        }
        return roundIngAmount;
    }

    /**
     * 查询用户余额
     *
     * @param pkAccount 币种ID
     * @return
     */
    @GetMapping("/member-balance")
    public AjaxResult findMemberBalance(Integer pkAccount) {
        Long pkMember = SecurityUtils.getUserId();
        CuMemberRechargeAccountParam cuMemberBalance = iCuMemberAccountService.findMemberBalanceById(iCuMemberBaseService.getAccountValueById(pkAccount), pkMember);
        return AjaxResult.success(cuMemberBalance.getAvailableBalance());
    }

}
