package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONObject;
//import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.sms.AliSmsService;
import com.ruoyi.common.sms.SendSmsDto;
import com.ruoyi.common.sms.SmsType;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.system.domain.enums.verificationCode.CodeBusinessType;
import com.ruoyi.system.service.IVerificationCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 验证码服务
 * @author wjh
 * 2024/3/27
 */
@Service
public class VerificationCodeServiceImpl implements IVerificationCodeService {

    @Value("${verificationCode.redis.key}")
    private String redisKey;

    @Value("${verificationCode.redis.lock}")
    private String redisLockKey;

    @Autowired
    private RedisCache redisCache;

    @Value("${debug}")
    private Boolean debug;

    @Autowired
    private AliSmsService aliSmsService;
    @Autowired
    private RedisLock redisLock;

    /**
     * 发送手机验证码
     * @param mobile 手机号
     * @param type 验证码类型
     * @return 是否发送成功
     */
    @Override
    public boolean sendMobileCode(String mobile, CodeBusinessType type) {
        ServiceUtil.assertion(mobile == null || type == null, "参数错误:null");
        ServiceUtil.assertion(getLock(mobile, type) != null, "请勿频繁获取验证码");

        // 生成验证码并缓存
        String code = generateCode(type.getLength());
        saveToRedis(mobile, type, code);

        // 发送短信验证码
        JSONObject param = new JSONObject();
        // TODO 模板参数
        SendSmsDto dto = new SendSmsDto();
        dto.setMobile(mobile);
        dto.setType(SmsType.VERIFICATION_CODE);
        dto.setParam(param);

        try {
            // SendSmsResponse send = aliSmsService.send(dto);


        } catch (Exception e) {

            return false;
        }

        return true;
    }

    /**
     * 校验验证码
     * @param key 键，可以是手机号、邮箱等
     * @param code 验证码
     * @param type 业务类型
     * @return 是否校验成功
     */
    @Override
    public boolean checkCode(String key, String code, CodeBusinessType type, boolean remove) {
        if (key == null || code == null || type == null) {
            return false;
        }
        String redisCode = getRedisCode(key, type);
        boolean result = redisCode != null && redisCode.equals(code);
        if (remove && result) {
            removeCode(key, type);
        }
        return result;
    }

    @Override
    public boolean checkCode(String key, String code, CodeBusinessType type) {
        return checkCode(key, code, type, true);
    }

    /**
     * 清除验证码缓存
     * @param key 键
     * @param type 业务类型
     */
    private void removeCode(String key, CodeBusinessType type) {
        redisCache.deleteObject(String.format("%s:%s:%s", redisKey, type.getType(), key));
    }

    /**
     * 获取验证码缓存
     * @param key 键
     * @param type 业务类型
     */
    private String getRedisCode(String key, CodeBusinessType type) {
        return redisCache.getCacheObject(String.format("%s:%s:%s", redisKey, type.getType(), key));
    }

    /**
     * 获取验证码冷却锁定值
     * @param key 键，可以手机号、邮箱等
     * @param type 业务类型
     */
    private String getLock(String key, CodeBusinessType type) {
        return redisCache.getCacheObject(String.format("%s:%s:%s:%s", redisKey, redisLockKey, type.getType(), key));
    }

    /**
     * 保存数据到Redis中
     * @param key 键，可以是手机号、邮箱等
     * @param type 业务类型
     * @param code 验证码
     */
    private void saveToRedis(String key, CodeBusinessType type, String code) {
        redisCache.setCacheObject(String.format("%s:%s:%s", redisKey, type.getType(), key),
                code, type.getExpireTime(), TimeUnit.SECONDS);

        redisCache.setCacheObject(String.format("%s:%s:%s:%s", redisKey, redisLockKey, type.getType(), key),
                code, type.getLockTime(), TimeUnit.SECONDS);
    }

    /**
     * 生成一个验证码
     */
    private String generateCode(Integer length) {
        if (this.debug) {
            return "888888";
        }
        return String.valueOf((int)( (Math.random() * 9 + 1) * Math.pow(10, length-1)) );
    }

}
