package cn.wisenergy.service.app.impl;

import cn.wisenergy.common.utils.*;
import cn.wisenergy.mapper.AccountMapper;
import cn.wisenergy.mapper.BankInfoMapper;
import cn.wisenergy.mapper.TradeRecordMapper;
import cn.wisenergy.mapper.UsersMapper;
import cn.wisenergy.model.app.AccountInfo;
import cn.wisenergy.model.app.BankInfo;
import cn.wisenergy.model.app.TradeRecord;
import cn.wisenergy.model.app.User;
import cn.wisenergy.model.dto.WithdrawBankDto;
import cn.wisenergy.model.enums.TradeRecordEnum;
import cn.wisenergy.model.enums.TradeStatusEnum;
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.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;


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

        //编辑
        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) {
            if (dto.getMoney() > accountInfo.getExtractMoney().doubleValue()) {
                return R.error("提现金额不得超过余额");
            }
        }
        //2、验证短信验证码
        //判断缓存是否过期
        assert accountInfo != null;
        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、添加提现交易流水记录
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setUserId(accountInfo.getUserId());
        tradeRecord.setTradeType(TradeRecordEnum.WITHDRAW_DEPOSIT.getCode());
        tradeRecord.setTradeNo(null);
        tradeRecord.setStatus(TradeStatusEnum.BANK_TRANSFER_ACCOUNTS.getCode());
        int count = recordMapper.add(tradeRecord);
        if (count == 0) {
            return R.error("保存交易流水失败!");
        }
        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);
    }
}
