import random
from sqlalchemy.orm import selectinload
from fastapi import APIRouter, Depends
from sqlalchemy.future import select
from sqlalchemy.ext.asyncio import AsyncSession
from user_auth_zxw.db.models import User
from user_auth_zxw.db.get_db import get_db
from user_auth_zxw.apis.api_登录注册.login import login_user_async
from user_auth_zxw.apis.api_用户权限_增加 import 分配或创建角色
from user_auth_zxw.apis.schemas import (返回_login,
                                        请求_分配或创建角色,
                                        请求_手机邮箱_注册,
                                        请求_手机邮箱_登录)
from datetime import datetime, timedelta

from user_auth_zxw.config import AliyunSMS
from user_auth_zxw.SDK_jwt import (get_current_user)

from app_tools_zxw.SDK_阿里云.SMS_发送短信v2 import SMS阿里云
from app_tools_zxw.Errors.api_errors import HTTPException_AppToolsSZXW, ErrorCode


# 用于存储验证码的字典
verification_codes = {}


def store_verification_code(phone: str, code: str):
    verification_codes[phone] = {
        "code": code,
        "expiry": datetime.now() + timedelta(minutes=5)
    }


def verify_code(phone: str, code: str) -> bool:
    if phone not in verification_codes:
        return False
    stored_code = verification_codes[phone]
    if datetime.now() > stored_code["expiry"]:
        del verification_codes[phone]
        return False
    if stored_code["code"] != code:
        return False
    del verification_codes[phone]
    return True


sms = SMS阿里云(AliyunSMS.ali_access_key_id, AliyunSMS.ali_access_key_secret)
router = APIRouter(prefix="/account/phone")


@router.post("/send-verification-code/")
async def 发送验证码(phone: str):
    verification_code = ''.join([str(random.randint(0, 9)) for _ in range(4)])  # 生成6位随机数字验证码
    result = await sms.发送_验证码_async(phone, verification_code)
    if result is None:
        store_verification_code(phone, verification_code)
        return {"message": "验证码已发送"}
    else:
        raise HTTPException_AppToolsSZXW(error_code=ErrorCode.验证码发送失败,
                                         detail="Failed to send verification code",
                                         http_status_code=500)


@router.post("/register-phone/", response_model=返回_login)
async def 注册_手机(user_create: 请求_手机邮箱_注册, db: AsyncSession = Depends(get_db)):
    # 检查手机号是否已存在
    result = await db.execute(select(User).filter(User.phone == user_create.phone))
    user = result.scalar_one_or_none()
    if user:
        raise HTTPException_AppToolsSZXW(error_code=ErrorCode.手机号已注册,
                                         detail="Phone number already registered",
                                         http_status_code=400)
    # 验证验证码
    if not verify_code(user_create.phone, user_create.sms_code):
        raise HTTPException_AppToolsSZXW(error_code=ErrorCode.验证码验证失败,
                                         detail="Invalid verification code",
                                         http_status_code=400)
    # 创建新用户并保存到数据库
    new_user = User(
        username=user_create.phone,
        email=user_create.email if user_create.email else None,
        phone=user_create.phone,
        hashed_password=User.hash_password(user_create.sms_code),
        notes="phone register"
    )
    db.add(new_user)
    await db.commit()
    await db.refresh(new_user)

    # 增加初始权限
    user_info = 请求_分配或创建角色(
        user_id=new_user.id,
        role_name=user_create.role_name,
        app_name=user_create.app_name)
    await 分配或创建角色(user_info, db)
    return await login_user_async(new_user, db)


@router.post("/login-phone/", response_model=返回_login)
async def 登录_手机(info: 请求_手机邮箱_登录, db: AsyncSession = Depends(get_db)):
    result = await db.execute(select(User).options(selectinload(User.roles)).filter(User.phone == info.phone))
    user = result.scalar_one_or_none()
    if user is None or not verify_code(info.phone, info.sms_code):
        raise HTTPException_AppToolsSZXW(error_code=ErrorCode.无效的手机号或验证码,
                                         detail="Invalid phone number or SMS code",
                                         http_status_code=400)
    return await login_user_async(user, db)


@router.post("/change-phone/", response_model=返回_login)
async def 更换绑定手机号(new_phone: str,
                         sms_code: str,
                         db: AsyncSession = Depends(get_db),
                         user: User = Depends(get_current_user)):
    user: User | None = await db.get(User, user.id)
    if user is None or not verify_code(new_phone, sms_code):
        raise HTTPException_AppToolsSZXW(error_code=ErrorCode.无效的手机号或验证码,
                                         detail="Invalid user or SMS code",
                                         http_status_code=400)
    user.phone = new_phone
    await db.commit()
    await db.refresh(user)
    return await login_user_async(user, db)
