package com.xy.xyaicpzs.service.impl;

import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.xy.xyaicpzs.service.SmsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务实现类（腾讯云SMS）
 */
@Service
public class SmsServiceImpl implements SmsService {
    
    private static final Logger logger = LoggerFactory.getLogger(SmsServiceImpl.class);
    
    @Value("${tencent.sms.secret-id}")
    private String secretId;
    
    @Value("${tencent.sms.secret-key}")
    private String secretKey;
    
    @Value("${tencent.sms.sdk-app-id}")
    private String sdkAppId;
    
    @Value("${tencent.sms.template-id}")
    private String templateId;
    
    @Value("${tencent.sms.sign-name}")
    private String signName;
    
    @Value("${tencent.sms.region:ap-guangzhou}")
    private String region;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 短信验证码Redis前缀
    private static final String SMS_CODE_PREFIX = "sms:code:";
    // 短信发送次数Redis前缀
    private static final String SMS_COUNT_PREFIX = "sms:count:";
    // 短信验证码有效期（分钟）
    private static final long SMS_CODE_EXPIRE = 5;
    // 每天最大发送次数
    private static final int MAX_SMS_COUNT_PER_DAY = 10;
    
    /**
     * 创建腾讯云短信客户端
     */
    private SmsClient createSmsClient() {
        Credential cred = new Credential(secretId, secretKey);
        return new SmsClient(cred, region);
    }
    
    /**
     * 生成6位随机数字验证码
     */
    private String generateVerificationCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
    
    /**
     * 获取当天结束时间的剩余秒数
     */
    private long getSecondsUntilEndOfDay() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);
        Duration duration = Duration.between(now, endOfDay);
        return duration.getSeconds();
    }
    
    @Override
    public boolean sendVerificationCode(String phoneNumber) throws Exception {
        // 检查当天发送次数是否达到上限
        String countKey = SMS_COUNT_PREFIX + phoneNumber + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
        
        if (count != null && count >= MAX_SMS_COUNT_PER_DAY) {
            logger.warn("手机号{}今日短信发送次数已达上限: {}", phoneNumber, MAX_SMS_COUNT_PER_DAY);
            return false;
        }
        
        // 生成6位随机验证码
        String verificationCode = generateVerificationCode();
        
        try {
            // 创建腾讯云短信客户端
            SmsClient client = createSmsClient();
            
            // 构建短信请求
            SendSmsRequest req = new SendSmsRequest();
            
            // 短信应用ID
            req.setSmsSdkAppId(sdkAppId);
            
            // 短信签名内容
            req.setSignName(signName);
            
            // 模板ID
            req.setTemplateId(templateId);
            
            // 模板参数：验证码
            String[] templateParamSet = {verificationCode};
            req.setTemplateParamSet(templateParamSet);
            
            // 下发手机号码，采用E.164标准，+[国家或地区码][手机号]
            // 例如：+8613711112222，其中前面有一个+号，86为国家码，13711112222为手机号
            String[] phoneNumberSet = {"+86" + phoneNumber};
            req.setPhoneNumberSet(phoneNumberSet);
            
            // 发送短信
            SendSmsResponse resp = client.SendSms(req);
            
            // 检查发送结果
            if (resp.getSendStatusSet() != null && resp.getSendStatusSet().length > 0) {
                String code = resp.getSendStatusSet()[0].getCode();
                if ("Ok".equals(code)) {
                    logger.info("短信验证码发送成功，手机号: {}, SerialNo: {}", phoneNumber, resp.getSendStatusSet()[0].getSerialNo());
                    
                    // 将验证码保存到Redis，设置过期时间
                    String codeKey = SMS_CODE_PREFIX + phoneNumber;
                    redisTemplate.opsForValue().set(codeKey, verificationCode, SMS_CODE_EXPIRE, TimeUnit.MINUTES);
                    
                    // 增加当天发送次数，并设置过期时间为当天结束
                    if (count == null) {
                        count = 0;
                    }
                    redisTemplate.opsForValue().set(countKey, count + 1, getSecondsUntilEndOfDay(), TimeUnit.SECONDS);
                    
                    return true;
                } else {
                    logger.error("短信发送失败, 手机号: {}, Code: {}, Message: {}", 
                            phoneNumber, code, resp.getSendStatusSet()[0].getMessage());
                    return false;
                }
            } else {
                logger.error("短信发送失败, 手机号: {}, 响应为空", phoneNumber);
                return false;
            }
            
        } catch (TencentCloudSDKException e) {
            logger.error("腾讯云短信发送异常, 手机号: {}, 错误信息: {}", phoneNumber, e.getMessage(), e);
            return false;
        } catch (Exception e) {
            logger.error("短信发送异常, 手机号: {}", phoneNumber, e);
            return false;
        }
    }
    
    @Override
    public boolean verifyCode(String phoneNumber, String code) {
        if (phoneNumber == null || code == null) {
            return false;
        }
        
        String codeKey = SMS_CODE_PREFIX + phoneNumber;
        String savedCode = (String) redisTemplate.opsForValue().get(codeKey);
        
        if (savedCode != null && savedCode.equals(code)) {
            // 验证成功后删除验证码
            redisTemplate.delete(codeKey);
            return true;
        }
        
        return false;
    }
} 