package cn.wisenergy.service.app.impl;

import cn.wisenergy.common.utils.*;
import cn.wisenergy.mapper.*;
import cn.wisenergy.model.app.*;
import cn.wisenergy.model.dto.WithdrawBankDto;
import cn.wisenergy.model.enums.FrozenStatus;
import cn.wisenergy.model.enums.TradeRecordEnum;
import cn.wisenergy.model.enums.TradeStatusEnum;
import cn.wisenergy.model.vo.TaxRateVo;
import cn.wisenergy.model.vo.WithdrawAuditVo;
import cn.wisenergy.service.Manager.BankManger;
import cn.wisenergy.service.app.BankService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author 86187
 * @ Description: 银行卡相关接口实现
 * @ Author     : 86187
 * @ Date       : 2021/3/3 16:28
 */
@Service
@Slf4j
public class BankServiceImpl extends ServiceImpl<BankInfoMapper, BankInfo> implements BankService {

    @Autowired
    private BankInfoMapper bankInfoMapper;

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private TradeRecordMapper recordMapper;

    @Autowired
    private VariableMapper variableMapper;

    @Autowired
    private BankManger bankManger;

    @Autowired
    private TradeRecordMapper tradeRecordMapper;

    private static final String TAX_RATE_KEY = "TAX_RATE_CODE";


    @Override
    public R<BankInfo> add(BankInfo bankInfo) {
        log.info("shop-mall[]BankServiceImpl[]add[]input.param.bankInfo:" + bankInfo);
        if (null == bankInfo || StringUtils.isBlank(bankInfo.getUserId())) {
            return R.error("入参不能为空!");
        }

        //获取该用户下是否有银行卡信息  无：新增 有：编辑
        BankInfo bank = bankInfoMapper.getByUserId(bankInfo.getUserId());
        if (null == bank) {
            int count = bankInfoMapper.add(bankInfo);
            if (count == 0) {
                return R.error("保存用户银行卡信息失败!");
            }

            return R.ok(bankInfo);
        }
        bank.setName(bankInfo.getName());
        bank.setCardNumber(bankInfo.getCardNumber());
        bank.setBankName(bankInfo.getBankName());
        bank.setIdCardNo(bankInfo.getIdCardNo());
        bank.setUserId(bankInfo.getUserId());
        int number = bankInfoMapper.edit(bank);
        if (number == 0) {
            return R.error("保存用户银行卡信息失败!");
        }
        return R.ok(bankInfo);
    }

    @Override
    public R<BankInfo> edit(BankInfo bankInfo) {
        log.info("shop-mall[]BankServiceImpl[]edit[]input.param.bankInfo:" + bankInfo);
        if (null == bankInfo) {
            return R.error("入参不能为空!");
        }
        //获取用户银行卡信息
        BankInfo old = bankInfoMapper.selectById(bankInfo.getId());
        if (null == old) {
            return R.error("用户银行卡信息不存在!");
        }

        old.setBankName(bankInfo.getBankName());
        old.setCardNumber(bankInfo.getCardNumber());
        old.setName(bankInfo.getName());
        old.setIdCardNo(bankInfo.getIdCardNo());

        //编辑
        int count = bankInfoMapper.edit(old);
        if (count == 0) {
            return R.error("编辑用户银行卡信息失败!");
        }
        return R.ok(old);
    }

    @Override
    public R<BankInfo> getByUserId(String userId) {
        log.info("shop-mall[]BankServiceImpl[]getByUserId[]input.param.userId:" + userId);
        if (StringUtils.isBlank(userId)) {
            return R.error("入参不能为空!");
        }

        BankInfo bankInfo = bankInfoMapper.getByUserId(userId);
        return R.ok(bankInfo);
    }

    @Override
    public R<Boolean> bankWithdrawSendSms(String userId) {
        log.info("shop-mall[]BankServiceImpl[]edit[]input.param.userId:" + userId);
        if (StringUtils.isBlank(userId)) {
            return R.error("入参不能为空!");
        }

        //1、获取用户信息
        User user = usersMapper.getByUserId(userId);
        if (null == user) {
            return R.error("用户信息不存在!");
        }

        //2、调用发送短信验证码接口
        String templateCode = Constants.Sms.TemplateCode.LOGIN_SF_REGISTER;
        String code = MathUtils.random();
        boolean bool = smsUtils.sendMessage(user.getUserId(), templateCode, code);
        if (!bool) {
            return R.error("验证码发送失败，请重发!");
        }

        //缓存code到redis
        String phone = user.getUserId();
        String key = StringUtil.formatKeyWithPrefix(Constants.RedisKey.BANK_PRIFIX, Constants.RedisKey.SMS_PRIFIX, phone, code + "");
        boolean cache = redisUtils.set(key, code, Constants.Duration.MINUTE_INT);
        if (!cache) {
            return R.error("缓存验证码失败!");
        }
        return R.ok(0, true);
    }

    @Override
    public R<Boolean> userWithdrawBank(WithdrawBankDto dto) {
        log.info("shop-mall[]BankServiceImpl[]edit[]input.param.dto:" + dto);
        if (null == dto || StringUtils.isBlank(dto.getUserId()) || StringUtils.isBlank(dto.getCode()) ||
                null == dto.getMoney()) {
            return R.error("入参不能为空!");
        }

        //1、判断提现金额不得超过余额
        //获取账户信息
        AccountInfo accountInfo = accountMapper.getByUserId(dto.getUserId());
        if (null == accountInfo) {
            return R.error("账户信息不存在!");
        }

        if (accountInfo.getFrozenStatus().equals(FrozenStatus.ALREADY_FROZEN.getCode())) {
            return R.error("您的账户已被冻结，不能提现!");
        }

        if (dto.getMoney() > accountInfo.getExtractMoney().doubleValue()) {
            return R.error("提现金额不得超过余额");
        }

        //2、验证短信验证码
        //判断缓存是否过期
        String phone = accountInfo.getUserId();
        String code = dto.getCode();
        String key = StringUtil.formatKeyWithPrefix(Constants.RedisKey.BANK_PRIFIX, Constants.RedisKey.SMS_PRIFIX, phone, code + "");
        long time = redisUtils.getExpire(key);
        if (time < 0) {
            return R.error(1, "验证码已过期!", false);
        }

        //3、更新可提现金额和
        BigDecimal money = BigDecimal.valueOf(dto.getMoney());
        BigDecimal extractMoney = accountInfo.getExtractMoney().subtract(money);
        accountInfo.setExtractMoney(extractMoney);

        BigDecimal frozenMoney = accountInfo.getFrozenMoney().add(money);
        accountInfo.setFrozenMoney(frozenMoney);

        //4、添加提现交易流水记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setUserId(accountInfo.getUserId());
        tradeRecord.setTradeType(TradeRecordEnum.WITHDRAW_DEPOSIT.getCode());
        tradeRecord.setTradeNo(null);
        tradeRecord.setStatus(TradeStatusEnum.BANK_TRANSFER_ACCOUNTS.getCode());
        tradeRecord.setMoney(money);

        //获取用户银行卡信息
        BankInfo bankInfo = bankInfoMapper.getByUserId(dto.getUserId());
        if (null != bankInfo && StringUtils.isNotEmpty(bankInfo.getCardNumber())) {
            tradeRecord.setCardNumber(bankInfo.getCardNumber());
        }

        //更新提现状态，更新账户冻结金额
        Boolean bool = bankManger.updateAccountAddRecord(accountInfo, tradeRecord);
        if (!bool) {
            return R.ok(1, false);
        }
        return R.ok(0, true);
    }

    @Override
    public R<List<String>> getBankNameList() {
        log.info("shop-mall[]BankServiceImpl[]edit[]input.method");

        List<String> list = new ArrayList<>();
        list.add("中国工商银行");
        list.add("中国农业银行");
        list.add("中国建设银行");
        list.add("中国交通银行");
        list.add("中国民生银行");
        list.add("中国招商银行");
        list.add("中国农商银行");
        list.add("中国银行");
        list.add("平安银行");
        list.add("中国邮政储蓄银行");
        list.add("浦发银行");
        list.add("兴业银行");
        list.add("中信银行");
        return R.ok(list);
    }

    @Override
    public R<TaxRateVo> getTaxRate(Double money) {
        log.info("shop-mall[]BankServiceImpl[]getTaxRate[]input.param.money:" + money);
        if (null == money) {
            return R.error("入参为空!");
        }

        //获取提现税率信息
        Variable validate = variableMapper.getByKey(TAX_RATE_KEY);
        if (null == validate) {
            return R.error("未设置提现税率，请联系后台管理员设置!");
        }

        TaxRateVo taxRateVo = new TaxRateVo();
        Double value = Double.valueOf(validate.getVariableValue());
        Double taxMoney = money * value / 100;
        Double actualMoney = money - taxMoney;
        taxRateVo.setActualMoney(actualMoney);
        taxRateVo.setTaxMoney(taxMoney);
        taxRateVo.setTaxDesc("提现时系统自动扣除2%个人所得税，剩余税费由平台替缴。");
        return R.ok(taxRateVo);
    }

    @Override
    public R<Boolean> withdrawAudit(WithdrawAuditVo auditVo) {
        log.info("shop-mall[]BankServiceImpl[]withdrawAudit[]input.param.auditVo:" + auditVo);
        if (null == auditVo || null == auditVo.getId()) {
            return R.error("入参为空!");
        }

        //1、根据提现记录id,获取提现信息
        TradeRecord tradeRecord = tradeRecordMapper.selectById(auditVo.getId());
        if (null == tradeRecord) {
            return R.error("提现记录不正确，请联系管理员!");
        }

        //2、获取账户信息
        AccountInfo accountInfo = accountMapper.getByUserId(tradeRecord.getUserId());
        if (null == accountInfo) {
            return R.error("提现账户信息不存在!");
        }

        tradeRecord.setStatus(TradeStatusEnum.WITHDRAWAL_SUCCESS.getCode());
        BigDecimal frozenMoney = accountInfo.getFrozenMoney().subtract(tradeRecord.getMoney());
        accountInfo.setFrozenMoney(frozenMoney);

        //更新提现状态为 提现成功，更新账户冻结金额
        boolean bool = bankManger.updateAccountAndRecord(accountInfo, tradeRecord);
        if (!bool) {
            return R.ok(1, false);
        }
        return R.ok(0, true);
    }
}
