import random
import json
from extensions import redis_client
from config import Config

# 阿里云号码认证服务 SDK
try:
    from alibabacloud_dypnsapi20170525.client import Client as Dypnsapi20170525Client
    from alibabacloud_tea_openapi import models as open_api_models
    from alibabacloud_dypnsapi20170525 import models as dypnsapi_20170525_models
    from alibabacloud_tea_util import models as util_models
    ALIYUN_SDK_AVAILABLE = True
except ImportError:
    ALIYUN_SDK_AVAILABLE = False
    print("⚠️  阿里云号码认证服务 SDK 未安装，请运行: pip install alibabacloud_dypnsapi20170525")

class SMSService:
    @staticmethod
    def _create_client():
        """创建号码认证服务客户端"""
        config = open_api_models.Config(
            access_key_id=Config.ALIBABA_CLOUD_ACCESS_KEY_ID,
            access_key_secret=Config.ALIBABA_CLOUD_ACCESS_KEY_SECRET
        )
        config.endpoint = 'dypnsapi.aliyuncs.com'
        return Dypnsapi20170525Client(config)

    @staticmethod
    def send_code(phone):
        # 检查是否在冷却期内
        cooldown_key = f"sms_cooldown:{phone}"
        if redis_client.exists(cooldown_key):
            ttl = redis_client.ttl(cooldown_key)
            return False, f"请{ttl}秒后再试"
        
        # 开发模式：使用固定验证码
        if Config.DEV_MODE:
            code = Config.DEV_SMS_CODE
            redis_client.set(f"sms_code:{phone}", code, ex=1800)
            redis_client.set(cooldown_key, "1", ex=60)
            print(f"🟡 [开发模式] 验证码: {code} (手机: {phone})")
            return True, "验证码已发送（开发模式）"
        
        # 生产模式：真实发送
        # 调用阿里云号码认证服务（自动生成验证码）
        success, biz_id = SMSService._call_aliyun(phone, None)
        
        if success:
            # 发送成功后存储 BizId 用于校验
            redis_client.set(f"sms_biz_id:{phone}", biz_id, ex=1800)
            redis_client.set(cooldown_key, "1", ex=60)
            print(f"✅ 短信已发送至 {phone}, BizId: {biz_id}")
            return True, "发送成功"
        else:
            print(f"❌ 短信发送失败: {biz_id}")  # biz_id 此时是错误信息
            return False, biz_id

    @staticmethod
    def verify_code(phone, code):
        """校验验证码 - 统一使用本地 Redis 校验"""
        # 从 Redis 获取验证码
        cached_code = redis_client.get(f"sms_code:{phone}")
        
        if not cached_code:
            print(f"⚠️  未找到验证码，手机号: {phone}")
            return False
        
        # 比对验证码
        stored_code = cached_code.decode('utf-8') if isinstance(cached_code, bytes) else str(cached_code)
        input_code = str(code)
        
        print(f"🔍 校验验证码: 输入={input_code}, 存储={stored_code}")
        
        if stored_code == input_code:
            # 校验成功，删除验证码（一次性使用）
            redis_client.delete(f"sms_code:{phone}")
            redis_client.delete(f"sms_biz_id:{phone}")  # 也删除 BizId
            print(f"✅ 验证码校验成功")
            return True
        else:
            print(f"❌ 验证码不匹配")
            return False

    @staticmethod
    def _call_aliyun(phone, code):
        """调用阿里云号码认证服务发送验证码"""
        if not ALIYUN_SDK_AVAILABLE:
            return False, "SDK未安装"
            
        try:
            client = SMSService._create_client()
            
            # 使用 SendSmsVerifyCode 接口
            request = dypnsapi_20170525_models.SendSmsVerifyCodeRequest(
                phone_number=phone,
                sign_name=Config.SMS_SIGN_NAME,
                template_code=Config.SMS_TEMPLATE_CODE,
                # 模板需要 code 和 min 两个参数
                template_param='{"code":"##code##","min":"30"}',
                code_type=1,     # 1=纯数字
                code_length=6,   # 6位验证码
                interval=60,     # 60秒重发间隔
                valid_time=1800, # 30分钟有效期（秒）
                return_verify_code=True  # 返回验证码用于本地校验
            )
            
            runtime = util_models.RuntimeOptions()
            resp = client.send_sms_verify_code_with_options(request, runtime)
            
            if resp.body.code == "OK":
                # 获取阿里云生成的验证码
                verify_code = resp.body.model.verify_code if hasattr(resp.body.model, 'verify_code') else None
                biz_id = resp.body.model.biz_id
                
                if verify_code:
                    # 将验证码存储到 Redis 用于本地校验
                    redis_client.set(f"sms_code:{phone}", verify_code, ex=1800)
                    print(f"✅ 短信已发送至 {phone}, 验证码: {verify_code}, BizId: {biz_id}")
                else:
                    # 如果没有返回验证码，只存储 BizId
                    redis_client.set(f"sms_biz_id:{phone}", biz_id, ex=1800)
                    print(f"✅ 短信已发送至 {phone}, BizId: {biz_id}")
                
                return True, biz_id
            else:
                return False, resp.body.message
        except Exception as e:
            import traceback
            error_detail = traceback.format_exc()
            print(f"❌ 详细错误信息:\n{error_detail}")
            return False, str(e)
