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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.constant.CacheConstants;
import com.hzs.common.core.constant.SmsConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.EAliSmsTemplate;
import com.hzs.common.core.enums.EEnv;
import com.hzs.common.core.service.RedisService;
import com.hzs.common.core.utils.VerificationCodeUtil;
import com.hzs.member.sms.service.IApiAliSmsService;
import com.hzs.third.sms.ISmsServiceApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 阿里短信发送服务
 */
@Slf4j
@Service
public class ApiAliSmsServiceImpl implements IApiAliSmsService {

    @Autowired
    private RedisService redisService;

    @DubboReference
    ISmsServiceApi iSmsServiceApi;

    @Override
    public String sendCode(String phone, String checkKey, String sendTimKey, Long pkMember) {
        // 每个手机号每天只能获取20次短信验证码
        String smsCountKey = String.format(CacheConstants.SMS_COUNT, DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN));
        Object smsCountObj = redisService.getCacheMapValue(smsCountKey, phone);
        if (smsCountObj != null) {
            if (Integer.parseInt(smsCountObj.toString()) > 20) {
                return "当前手机号码获取短信已达当日上限";
            }
        }

        if (null == checkKey) {
            // 如果为空，使用默认发送短信key
            checkKey = CacheConstants.DEFAULT_CHECK;
        }
        if (null == sendTimKey) {
            // 如果为空，使用默认发送短信key间隔时间
            sendTimKey = CacheConstants.DEFAULT_SEND_TIME;
        }

        if (redisService.hasKey(sendTimKey + phone)) {
            return "获取验证码过于频繁，请稍后再试";
        }

        // 生成4位验证码
        String code = VerificationCodeUtil.createCode();
        log.info("发送短信验证码，phone: {}, code: {}", phone, code);

        R<String> sendResult = iSmsServiceApi.sendAliSms(phone, code, EAliSmsTemplate.MEMBER_SMS);
        if (sendResult.isSuccess()) {
            // 返回成功，验证码放入缓存
            // 验证码缓存有效期10分钟
            redisService.setCacheObject(checkKey + (null != pkMember ? pkMember : phone), code, SmsConstants.FAILURE_TIME, TimeUnit.MINUTES);

            // 验证码发送间隔不能低于1分钟
            redisService.setCacheObject(sendTimKey + phone, "", 1L, TimeUnit.MINUTES);

            if (smsCountObj == null) {
                redisService.setCacheMapValue(smsCountKey, phone, 1);
                redisService.expire(smsCountKey, 1, TimeUnit.DAYS);
            } else {
                redisService.setCacheMapValue(smsCountKey, phone, Integer.parseInt(smsCountObj.toString()) + 1);
            }

            return null;
        }
        log.error("发送短信失败：{}", sendResult.getMsg());
        return "获取验证码失败，请稍候重试";
    }

    @Override
    public String checkCode(String phone, String smsCode, String checkKey, Long pkMember) {
        if (EEnv.TEST.getValue().equals(BdConfig.getEnv()) && "ASDF".equals(smsCode)) {
            // 测试环境暂时不发放短信
            return null;
        }

        if (null == checkKey) {
            // 如果为空，使用默认发送短信key
            checkKey = CacheConstants.DEFAULT_CHECK;
        }

        String cacheSmsCode = redisService.getCacheObject(checkKey + (null != pkMember ? pkMember : phone));
        if (null == cacheSmsCode) {
            return "验证码已失效";
        }
        if (!cacheSmsCode.equals(smsCode)) {
            // TODO 验证码错误，需不需要清除缓存验证码？？会不会存在暴力破解情况？？
            return "验证码错误";
        }
        // 校验通过，删除验证码缓存
        redisService.deleteObject(checkKey + (null != pkMember ? pkMember : phone));
        return null;
    }

//    @Override
//    public String sendLoginCode(String phone) {
//        return this.sendCode(phone, CacheConstants.LOGIN_CHECK, CacheConstants.LOGIN_SEND_TIME);
//    }
//
//    @Override
//    public String checkLoginCode(String phone, String smsCode) {
//        String str = this.checkCode(phone, smsCode, CacheConstants.LOGIN_CHECK);
//        if (null == str) {
//            // 删除验证码间隔时间缓存
//            redisService.deleteObject(CacheConstants.LOGIN_SEND_TIME + phone);
//        }
//        return str;
//    }

//    @Override
//    public String sendRegisterCode(String phone) {
//        return this.sendCode(phone, CacheConstants.REGISTER_CHECK, CacheConstants.REGISTER_SEND_TIME);
//    }
//
//    @Override
//    public String checkRegisterCode(String phone, String smsCode) {
//        String str = this.checkCode(phone, smsCode, CacheConstants.REGISTER_CHECK);
//        if (null == str) {
//            // 删除验证码间隔时间缓存
//            redisService.deleteObject(CacheConstants.REGISTER_SEND_TIME + phone);
//        }
//        return str;
//    }

    @Override
    public String sendRecoverCode(String phone, Long pkMember) {
        return this.sendCode(phone, CacheConstants.RECOVER_CHECK, CacheConstants.RECOVER_SEND_TIME, pkMember);
    }

    @Override
    public String checkRecoverCode(String phone, String smsCode, Long pkMember) {
        String str = this.checkCode(phone, smsCode, CacheConstants.RECOVER_CHECK, pkMember);
        if (null == str) {
            // 删除验证码间隔时间缓存
            redisService.deleteObject(CacheConstants.RECOVER_SEND_TIME + phone);
        }
        return str;
    }

    @Override
    public String resetPayPasswordCode(String phone, Long pkMember) {
        return this.sendCode(phone, CacheConstants.RESET_CHECK, CacheConstants.RESET_SEND_TIME, pkMember);
    }

    @Override
    public String checkPayPasswordCode(String phone, String smsCode, Long pkMember) {
        String str = this.checkCode(phone, smsCode, CacheConstants.RESET_CHECK, pkMember);
        if (null == str) {
            // 删除验证码间隔时间缓存
            redisService.deleteObject(CacheConstants.RESET_SEND_TIME + phone);
        }
        return str;
    }

}
