package com.erp.user.service.auth.impl;

import com.erp.user.service.auth.CaptchaService;
import com.erp.user.entity.auth.SmsCode;
import lombok.extern.slf4j.Slf4j;
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.util.Random;

/**
 * 短信服务实现
 * 
 * 支持配置阿里云短信(AliYun)或腾讯云短信(TencentCloud)
 * 默认使用模拟模式，仅输出日志而不真实发送
 */
@Slf4j
@Service
public class SmsServiceImpl implements com.erp.user.service.auth.SmsService {
    
    private static final String SMS_CODE_PREFIX = "sms:code:";
    private static final int CODE_LENGTH = 6;
    private static final int CODE_EXPIRY_MINUTES = 5;
    private static final int MAX_VERIFY_COUNT = 5;
    
    private final RedisTemplate<String, Object> redisTemplate;
    private final CaptchaService captchaService;
    
    @Value("${sms.provider:aliyun}")
    private String smsProvider;
    
    @Value("${sms.aliyun.enabled:false}")
    private boolean aliyunEnabled;
    
    @Value("${sms.aliyun.access-key-id:}")
    private String aliyunAccessKeyId;
    
    @Value("${sms.aliyun.access-key-secret:}")
    private String aliyunAccessKeySecret;
    
    @Value("${sms.aliyun.sign-name:}")
    private String aliyunSignName;
    
    @Value("${sms.aliyun.template-code:}")
    private String aliyunTemplateCode;
    
    @Value("${sms.tencent.enabled:false}")
    private boolean tencentEnabled;
    
    @Value("${sms.tencent.app-id:}")
    private String tencentAppId;
    
    @Value("${sms.tencent.app-key:}")
    private String tencentAppKey;
    
    @Value("${sms.tencent.sign-name:}")
    private String tencentSignName;
    
    @Value("${sms.tencent.template-id:}")
    private String tencentTemplateId;
    
    public SmsServiceImpl(RedisTemplate<String, Object> redisTemplate, CaptchaService captchaService) {
        this.redisTemplate = redisTemplate;
        this.captchaService = captchaService;
    }
    
    @Override
    public void sendCode(String phone, String scene) {
        // 生成验证码
        String code = generateCode();
        
        SmsCode smsCode = SmsCode.builder()
                .phone(phone)
                .code(code)
                .scene(scene)
                .sentAt(LocalDateTime.now())
                .expiresAt(LocalDateTime.now().plusMinutes(CODE_EXPIRY_MINUTES))
                .verifyCount(0)
                .used(false)
                .build();
        
        String key = SMS_CODE_PREFIX + phone + ":" + scene;
        redisTemplate.opsForValue().set(key, smsCode, Duration.ofMinutes(CODE_EXPIRY_MINUTES));
        
        // 发送短信
        if ("aliyun".equalsIgnoreCase(smsProvider) && aliyunEnabled) {
            sendAliyunSms(phone, code);
        } else if ("tencent".equalsIgnoreCase(smsProvider) && tencentEnabled) {
            sendTencentSms(phone, code);
        } else {
            // 模拟模式
            log.info("【短信验证码】手机号: {}, 场景: {}, 验证码: {} (模拟模式)", phone, scene, code);
        }
    }
    
    @Override
    public boolean verifyCode(String phone, String code, String scene) {
        String key = SMS_CODE_PREFIX + phone + ":" + scene;
        Object value = redisTemplate.opsForValue().get(key);
        
        if (!(value instanceof SmsCode smsCode)) {
            log.warn("短信验证码不存在或已过期: phone={}, scene={}", phone, scene);
            return false;
        }
        
        if (smsCode.getUsed()) {
            log.warn("短信验证码已被使用: phone={}, scene={}", phone, scene);
            return false;
        }
        
        if (smsCode.getExpiresAt().isBefore(LocalDateTime.now())) {
            log.warn("短信验证码已过期: phone={}, scene={}", phone, scene);
            return false;
        }
        
        if (smsCode.getVerifyCount() >= MAX_VERIFY_COUNT) {
            log.warn("短信验证码验证次数超限: phone={}, scene={}", phone, scene);
            return false;
        }
        
        if (!smsCode.getCode().equals(code)) {
            // 增加验证次数
            smsCode.setVerifyCount(smsCode.getVerifyCount() + 1);
            redisTemplate.opsForValue().set(key, smsCode, Duration.ofMinutes(CODE_EXPIRY_MINUTES));
            log.warn("短信验证码错误: phone={}, scene={}, 验证次数={}", phone, scene, smsCode.getVerifyCount());
            return false;
        }
        
        // 标记为已使用
        smsCode.setUsed(true);
        redisTemplate.opsForValue().set(key, smsCode, Duration.ofMinutes(CODE_EXPIRY_MINUTES));
        
        log.info("短信验证码验证成功: phone={}, scene={}", phone, scene);
        return true;
    }
    
    private String generateCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < CODE_LENGTH; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
    
    /**
     * 阿里云短信发送
     */
    private void sendAliyunSms(String phone, String code) {
        log.info("【阿里云短信】发送中: phone={}, code={}, signName={}, template={}", 
                phone, code, aliyunSignName, aliyunTemplateCode);
        // 实际实现需要添加阿里云SDK依赖: com.aliyun:dysmsapi20170525
        // DefaultAcsClient client = new DefaultAcsClient(profile);
        // SendSmsRequest request = new SendSmsRequest();
        // request.setPhoneNumbers(phone);
        // request.setSignName(aliyunSignName);
        // request.setTemplateCode(aliyunTemplateCode);
        // request.setTemplateParam("{\"code\":\"" + code + "\"}");
        // client.getAcsResponse(request);
    }
    
    /**
     * 腾讯云短信发送
     */
    private void sendTencentSms(String phone, String code) {
        log.info("【腾讯云短信】发送中: phone={}, code={}, appId={}, templateId={}", 
                phone, code, tencentAppId, tencentTemplateId);
        // 实际实现需要添加腾讯云SDK依赖: com.tencentcloudapi:tencentcloud-sdk-java
        // SmsMultiSender sender = new SmsMultiSender(Integer.parseInt(tencentAppId), tencentAppKey);
        // SmsMultiSenderResult result = sender.send(0, "86", Lists.newArrayList(phone), ...);
    }
}
