package cn.novalon.gym.manage.auth.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.novalon.gym.manage.auth.config.SmsProperties;
import cn.novalon.gym.manage.auth.service.SmsService;
import cn.novalon.gym.manage.common.constant.RedisKeyConstants;
import cn.novalon.gym.manage.common.util.RedisUtil;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.time.Duration;

/**
 * 短信服务实现类
 *
 * @author auto-generated
 * @date 2026-06-20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SmsServiceImpl implements SmsService {

    private final SmsProperties smsProperties;
    private final RedisUtil redisUtil;

    @Override
    public boolean sendVerificationCode(String phone) {
        log.info("发送短信验证码, phone: {}", phone);

        try {
            // 生成验证码
            String code = generateCode();

            // 发送短信
            boolean sent = sendSms(phone, code);

            if (sent) {
                // 将验证码存入Redis，5分钟过期
                String cacheKey = RedisKeyConstants.SMS_CODE + phone;
                redisUtil.setWithExpire(cacheKey, code, smsProperties.getCodeExpireSeconds())
                        .doOnSuccess(result -> log.info("验证码已缓存, phone: {}, code: {}, expire: {}s",
                                phone, code, smsProperties.getCodeExpireSeconds()))
                        .block();

                log.info("短信验证码发送成功, phone: {}", phone);
                return true;
            }

            log.warn("短信验证码发送失败, phone: {}", phone);
            return false;

        } catch (Exception e) {
            log.error("发送短信验证码异常, phone: {}", phone, e);
            return false;
        }
    }

    @Override
    public boolean verifyCode(String phone, String code) {
        log.info("验证短信验证码, phone: {}", phone);

        try {
            String cacheKey = RedisKeyConstants.SMS_CODE + phone;
            String cachedCode = redisUtil.get(cacheKey, String.class).block();

            if (cachedCode == null) {
                log.warn("验证码已过期或不存在, phone: {}", phone);
                return false;
            }

            if (cachedCode.equals(code)) {
                // 验证成功后删除验证码
                redisUtil.delete(cacheKey).block();
                log.info("验证码验证成功, phone: {}", phone);
                return true;
            }

            log.warn("验证码不匹配, phone: {}, input: {}, cached: {}", phone, code, cachedCode);
            return false;

        } catch (Exception e) {
            log.error("验证短信验证码异常, phone: {}", phone, e);
            return false;
        }
    }

    @Override
    public String getVerificationCode(String phone) {
        try {
            String cacheKey = RedisKeyConstants.SMS_CODE + phone;
            return redisUtil.get(cacheKey, String.class).block();
        } catch (Exception e) {
            log.error("获取验证码异常, phone: {}", phone, e);
            return null;
        }
    }

    /**
     * 生成验证码
     */
    private String generateCode() {
        return RandomUtil.randomNumbers(smsProperties.getCodeLength());
    }

    /**
     * 发送短信
     */
    private boolean sendSms(String phone, String code) throws Exception {
        log.info("调用阿里云短信API发送短信, phone: {}, code: {}", phone, code);

        // 创建阿里云短信客户端
        Config config = new Config()
                .setAccessKeyId(smsProperties.getAccessKeyId())
                .setAccessKeySecret(smsProperties.getAccessKeySecret())
                .setEndpoint("dysmsapi.aliyuncs.com");

        Client client = new Client(config);

        // 构建发送短信请求
        SendSmsRequest request = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName(smsProperties.getSignName())
                .setTemplateCode(smsProperties.getTemplateCode())
                .setTemplateParam("{\"code\":\"" + code + "\"}");

        // 发送短信
        SendSmsResponse response = client.sendSms(request);

        log.info("阿里云短信API响应, phone: {}, code: {}, message: {}",
                phone, response.getBody().getCode(), response.getBody().getMessage());

        // 判断发送结果
        if ("OK".equals(response.getBody().getCode())) {
            return true;
        }

        log.error("阿里云短信发送失败, phone: {}, code: {}, message: {}",
                phone, response.getBody().getCode(), response.getBody().getMessage());
        return false;
    }
}
