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

import cn.hutool.core.collection.CollUtil;
import com.hzs.common.core.annotation.RepeatSubmitSimple;
import com.hzs.common.core.constant.CountryConstants;
import com.hzs.common.core.constant.MagicNumberConstants;
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.core.web.page.TableDataInfo;
import com.hzs.common.domain.member.account.CuMemberAccount;
import com.hzs.common.domain.member.account.CuMemberWithdraw;
import com.hzs.common.domain.member.account.CuMemberWithdrawExt;
import com.hzs.common.domain.member.ext.CuMemberExt;
import com.hzs.common.domain.system.config.BdWithdrawal;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.common.util.TransactionUtils;
import com.hzs.member.account.dto.CuMemberWithdrawParam;
import com.hzs.member.account.service.ICuMemberAccountService;
import com.hzs.member.account.service.ICuMemberBankService;
import com.hzs.member.account.service.ICuMemberBaseService;
import com.hzs.member.account.service.ICuMemberWithdrawService;
import com.hzs.member.account.vo.CuMemberWithdrawVO;
import com.hzs.member.account.vo.CuMemberWithdrawalAddVO;
import com.hzs.member.base.service.ICuMemberService;
import com.hzs.system.base.dto.CurrencyDTO;
import com.hzs.system.config.IGradeServiceApi;
import com.hzs.system.config.IWithdrawalServiceApi;
import com.hzs.system.config.dto.GradeDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.List;

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

    @Autowired
    ICuMemberBankService iCuMemberBankService;
    @Autowired
    ICuMemberService iCuMemberService;
    @Autowired
    ICuMemberBaseService iCuMemberBaseService;
    @Autowired
    ICuMemberAccountService iCuMemberAccountService;
    @Autowired
    ICuMemberWithdrawService iCuMemberWithdrawService;

    @DubboReference
    IWithdrawalServiceApi iWithdrawalServiceApi;
    @DubboReference
    IGradeServiceApi iGradeServiceApi;

    /**
     * 提现时展示信息
     *
     * @return AjaxResult
     */
    @GetMapping("/show/add")
    public AjaxResult showAddWithdrawInfo(Integer pkAccount, BigDecimal cashAmount) {
        Integer pkCountry = SecurityUtils.getPkCountry();
        Long pkMember = SecurityUtils.getUserId();
        if (null == pkAccount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.SELECT_WITHDRAWAL_ACCOUNT));
        }
        if (null == cashAmount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.ENTER_WITHDRAWAL_AMOUNT));
        }
        //提现配置信息
        BdWithdrawal bdWithdrawal = iWithdrawalServiceApi.queryWithdrawal(pkCountry, pkAccount).getData();
        if (null == bdWithdrawal) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.CONFIGURE_WITHDRAWAL_INFO));
        }
        CuMemberAccount cuMemberAccount = iCuMemberAccountService.queryCuMemberAccountByPkMember(pkMember);
        Integer accountValue = iCuMemberBaseService.getAccountValueById(pkAccount);
        //余额
        BigDecimal balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.ACCOUNT + accountValue);
        //可用金额
        BigDecimal availableBalance = getAvailableBalance(accountValue, cuMemberAccount);
        //手续费金额
        BigDecimal serviceChargeAmount = accountValue.equals(EAccount.BONUS.getValue()) ? iCuMemberWithdrawService.computeServiceCharge(pkCountry, cashAmount) : BigDecimal.ZERO;

        CuMemberWithdrawalAddVO cuMemberWithdrawalAddVO = CuMemberWithdrawalAddVO.builder()
                .minAmount(bdWithdrawal.getMinAmount()).maxAmount(bdWithdrawal.getMaxAmount())
                .amount(availableBalance).balance(balance).srviceCharge(serviceChargeAmount).build();
        return AjaxResult.success(cuMemberWithdrawalAddVO);
    }

    /**
     * 用户提现
     * 提现时先扣账户的钱，撤销时返回账户的钱
     *
     * @param cuMemberWithdrawParam 提现入参
     * @return AjaxResult
     */
    @PostMapping("/add")
    @RepeatSubmitSimple
    public AjaxResult addWithdrawInfo(@RequestBody CuMemberWithdrawParam cuMemberWithdrawParam) {
        Integer pkCountry = SecurityUtils.getPkCountry();
        Long pkMember = SecurityUtils.getUserId();
        String memberCode = SecurityUtils.getMemberCode();

        CuMemberExt cuMemberLoginExt = iCuMemberService.getMemberByCode(memberCode);
        if (null == cuMemberLoginExt) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.RECHAGER_USER_NOT_EXIST));
        }
        //获取银行卡信息
//        Long pkBank = cuMemberWithdrawParam.getPkBank();
//        CuMemberBankVO memberBank = iCuMemberBankService.selectCuMemberBankById(pkBank);
//        if (null == memberBank) {
//            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.BIND_BANK_CARD));
//        }
        //校验支付密码
        String payPwd = cuMemberLoginExt.getPayPwd();
        if (StringUtils.isEmpty(payPwd) || !SecurityUtils.matchesPassword(cuMemberWithdrawParam.getPayPwd(), payPwd)) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.PAYMENT_PASSWORD_ERROR));
        }

        //查询提现账户
        Integer pkAccount = cuMemberWithdrawParam.getPkAccount();
        if (null == pkAccount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.SELECT_WITHDRAWAL_ACCOUNT));
        }
        Integer accountsType = iCuMemberBaseService.getAccountValueById(pkAccount);

        if (pkCountry.equals(CountryConstants.CHINA_COUNTRY)) {
            Integer expireStatus = cuMemberLoginExt.getExpireStatus();
            //休止期的会员奖金账户不允许提现
            Boolean restPeriodStatus = iCuMemberBaseService.restPeriodMemberUserWallet(pkMember, expireStatus, accountsType);
            if (restPeriodStatus) {
                return AjaxResult.error(FinanceMsgConstants.REST_PERIOD_NOT_WITHDRAWAL);
            }
            //已终止会员不允许提现
            if (expireStatus.equals(EExpireStatus.TERMINATED.getValue())) {
                return AjaxResult.error(FinanceMsgConstants.TERMINATED_NOT_WITHDRAWAL);
            }

            //结算等级为1 (目前是会员)不允许提现
            GradeDTO gradeDTO = iGradeServiceApi.getGradeByGradeValue(EGrade.START_UP.getValue(), pkCountry).getData();
            if (cuMemberLoginExt.getPkSettleGrade().equals(gradeDTO.getPkId())) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.NOT_WITHDRAWAL_UPGRADE));
            }
            //校验是否实名
            Boolean existRealName = iCuMemberBaseService.isExistRealName(pkMember, pkCountry, EBusinessModule.WITHDRAWAL.getValue());
            if (!existRealName) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.REAL_NAME_NOT_EXIST));
            }
            //校验实名认证的真实姓名与营业执照的法人姓名是否一致
/*            Boolean result = iCuMemberBaseService.verificationRealNameAndLicense(pkMember, pkCountry);
            if (!result) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.REAL_NAME_LICENSE_NOT_SAME));
            }*/
        }
        //查询账户信息
        CuMemberAccount cuMemberAccount = iCuMemberAccountService.queryCuMemberAccountByPkMember(pkMember);
        //是否可提现
        Integer isWithdraw = cuMemberAccount.getIsWithdraw();
        //不允许提现
        if (isWithdraw.equals(EYesNo.NO.getIntValue())) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.NOT_ALLOWED_WITHDRAWAL));
        }
        //提现配置信息
        BdWithdrawal bdWithdrawal = iWithdrawalServiceApi.queryWithdrawal(pkCountry, pkAccount).getData();
        //提现次数
        Integer withdrawalNumber = bdWithdrawal.getWithdrawalNumber();
        // 只能发起配置项次数待审核提现 必须通过或者驳回之后才能发起下一笔
        List<CuMemberWithdraw> memberWithdraws = iCuMemberWithdrawService.getWithdrawTimes(pkMember);
        if (CollUtil.isNotEmpty(memberWithdraws) && memberWithdraws.size() >= withdrawalNumber) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.EXCEEDING_WITHDRAWALS_NUMBER));
        }
        //提现金额校验
        BigDecimal minAmount = bdWithdrawal.getMinAmount();
        BigDecimal maxAmount = bdWithdrawal.getMaxAmount();
        if (null == minAmount || null == maxAmount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.CONFIGURE_WITHDRAWAL_AMOUNT_LIMIT));
        }
        // 提现金额
        BigDecimal cashAmount = cuMemberWithdrawParam.getCashAmount();
        if (null == cashAmount) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.ENTER_WITHDRAWAL_AMOUNT));
        }
        //提现金额是否输入整数值
        Integer isRounding = bdWithdrawal.getIsRounding();
        if (isRounding.equals(EYesNo.YES.getIntValue()) && Boolean.TRUE.equals(!isIntegerValue(cashAmount))) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.ENTER_INTEGER_VALUE));
        }

        if (cashAmount.compareTo(minAmount) < 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.WITHDRAWAL_AMOUNT_GREATER_MINIMUM_AMOUNT));
        }
        if (cashAmount.compareTo(maxAmount) > 0) {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.WITHDRAWAL_AMOUNT_LESS_MAXIMUM_AMOUNT));
        }
        //校验倍数
        if (pkCountry.equals(CountryConstants.CHINA_COUNTRY) && !remainder(cashAmount)) {
            return AjaxResult.error(FinanceMsgConstants.WITHDRAW_AMOUNT_MULTIPLE);
        }
        //本次应缴个税
        BigDecimal payIncomeTax = BigDecimal.ZERO;
        //手续费金额
        BigDecimal serviceChargeAmount = BigDecimal.ZERO;
        //实发金额
        BigDecimal issuedAmount = cashAmount;

        //奖金账户余额（兼容奖金账户奖金余额小于可提现金额时）
        if (accountsType.equals(EAccount.BONUS.getValue())) {
            //账户余额
            BigDecimal accountBalance = iCuMemberWithdrawService.getAccountBalance(accountsType, cuMemberAccount);
            //可提现余额
            BigDecimal balance = getAvailableBalance(accountsType, cuMemberAccount);
            //余额不足
            if (balance.compareTo(cashAmount) < 0 || accountBalance.compareTo(cashAmount) < 0) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.BALANCE_NOT_ENOUGH));
            }
            //奖金账户个税、手续费根据配置、其它用户暂不收取
            //本次应缴个税
            payIncomeTax = iCuMemberWithdrawService.computeIncomeTaxValue(pkMember, cashAmount, pkCountry, minAmount);
            //手续费金额
            serviceChargeAmount = iCuMemberWithdrawService.computeServiceCharge(pkCountry, cashAmount);
            issuedAmount = cashAmount.subtract(payIncomeTax).subtract(serviceChargeAmount);
        } else { //其它用户的余额
            BigDecimal balance = getAvailableBalance(accountsType, cuMemberAccount);
            //余额不足
            if (balance.compareTo(cashAmount) < 0) {
                return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.BALANCE_NOT_ENOUGH));
            }

        }
        String code = CommonUtil.createSerialNumber(EOrderPrefix.WITHDRAWAL_CODE.getValue());
        //汇率
        CurrencyDTO currencyDTO = iCuMemberBaseService.getCurrency(pkCountry);

        CuMemberWithdraw cuMemberWithdraw = CuMemberWithdraw.builder().pkMember(pkMember)
//                .pkAccount(pkAccount).pkBank(pkBank).remarks(cuMemberWithdrawParam.getRemarks())
                .pkAccount(pkAccount).pkBank(0L).remarks(cuMemberWithdrawParam.getRemarks())
                .pkRate(currencyDTO.getPkId()).cashAmount(cashAmount)
                .serviceCharge(serviceChargeAmount).incomeTax(payIncomeTax)
                .issuedAmount(issuedAmount).withdrawCode(code).build();
        cuMemberWithdraw.setApproveState(EApproveStatus.WAIT_SUBMIT.getValue());
        cuMemberWithdraw.setDelFlag(EDelFlag.UN_DELETE.getValue());
        cuMemberWithdraw.setPkCountry(pkCountry);
        cuMemberWithdraw.setPkCreator(pkMember);
        return toAjax(iCuMemberWithdrawService.saveMemberWithdrawInfo(cuMemberWithdraw));

    }

    /**
     * 取余
     *
     * @param amount
     * @return Boolean
     */
    private static Boolean remainder(BigDecimal amount) {
        BigDecimal[] results = amount.divideAndRemainder(BigDecimal.valueOf(MagicNumberConstants.WITHDRAW_MULTIPLE));
        if (results[1].compareTo(BigDecimal.ZERO) == 0) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 获取余额
     *
     * @param accountsType    账户值
     * @param cuMemberAccount 账户信息
     * @return BigDecimal
     */
    private BigDecimal getAvailableBalance(Integer accountsType, CuMemberAccount cuMemberAccount) {
        BigDecimal balance;
        //如果是奖金账户，取可提现金额
        if (accountsType.equals(EAccount.BONUS.getValue())) {
            balance = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.WITHDRAW_ACCOUNT + accountsType);
            BigDecimal lockAccount = ReflectUtils.invokeGetter(cuMemberAccount, MemberFieldConstants.LOCK_WITHDRAW_ACCOUNT + accountsType);
            if (null != lockAccount && lockAccount.compareTo(BigDecimal.ZERO) > 0) {
                balance = balance.subtract(lockAccount);
            }
        } else {
            //其它配置账户余额
            balance = iCuMemberWithdrawService.getAccountBalance(accountsType, cuMemberAccount);
        }
        return balance;
    }

    @PostMapping("/auto")
    public AjaxResult autoWithdrawInfo() {
        iCuMemberWithdrawService.autoWithdraw();
        return AjaxResult.success();
    }

    /**
     * 是否为整数值
     *
     * @param bd 入参
     * @return boolean
     */
    private static Boolean isIntegerValue(BigDecimal bd) {
        boolean ret;
        try {
            bd.toBigIntegerExact();
            ret = true;
        } catch (ArithmeticException ex) {
            ret = false;
        }
        return ret;
    }

    /**
     * 查询列表(会员端)
     *
     * @return TableDataInfo
     */
    @GetMapping("/list-detail")
    public TableDataInfo memberWithdrawDetail() {
        startPage();
        Object[] objects = iCuMemberWithdrawService.selectMemberWithdrawListByPkMember(SecurityUtils.getUserId(), SecurityUtils.getPkCountry());
        //处理分页
        TableDataInfo tableDataInfo = getDataTable((List<CuMemberWithdrawExt>) objects[0]);
        tableDataInfo.setRows((List<CuMemberWithdrawVO>) objects[1]);
        return tableDataInfo;
    }

    @GetMapping("/cancel")
    public AjaxResult cancelMemberWithdrawD(Long pkId) {
        CuMemberWithdraw cuMemberWithdraw = iCuMemberWithdrawService.getById(pkId);
        if (cuMemberWithdraw.getApproveState().equals(EApproveStatus.WAIT_SUBMIT.getValue()) && cuMemberWithdraw.getStatus().equals(EWithdrawStatus.NORMAL.getValue())) {
            return toAjax(iCuMemberWithdrawService.updateWithdrawStatusByPkId(pkId, SecurityUtils.getUserId()));
        } else {
            return AjaxResult.error(TransactionUtils.getContent(FinanceMsgConstants.WITHDRAWAL_NOT_CANCEL));
        }
    }

}
