from datetime import datetime, timedelta
import uuid
import secrets
from flask import session, request, g
from app.models.database.models import db, User, UserSession

class AuthService:
    """认证服务"""
    
    @staticmethod
    def register_user(username, email, password):
        """
        注册新用户
        
        Args:
            username: 用户名
            email: 电子邮件
            password: 密码
            
        Returns:
            (bool, str|int): 包含是否成功及结果(错误信息或用户ID)的元组
        """
        # 检查用户名是否已存在
        if User.query.filter_by(username=username).first():
            return False, "用户名已存在"
        
        # 检查邮箱是否已存在
        if User.query.filter_by(email=email).first():
            return False, "邮箱已存在"
        
        # 创建新用户
        user = User(username=username, email=email)
        user.set_password(password)
        
        try:
            db.session.add(user)
            db.session.commit()
            return True, user.id
        except Exception as e:
            db.session.rollback()
            return False, str(e)
    
    @staticmethod
    def authenticate_user(username_or_email, password):
        """
        验证用户凭据
        
        Args:
            username_or_email: 用户名或邮箱
            password: 密码
            
        Returns:
            User|None: 验证成功返回用户对象，失败返回None
        """
        # 查找用户
        user = User.query.filter(
            (User.username == username_or_email) | 
            (User.email == username_or_email)
        ).first()
        
        if not user:
            return None
        
        # 验证密码
        if not user.check_password(password):
            return None
        
        # 更新最后登录时间
        user.last_login = datetime.utcnow()
        db.session.commit()
        
        return user
    
    @staticmethod
    def create_session(user, remember=False, days=30):
        """
        创建用户会话
        
        Args:
            user: 用户对象
            remember: 是否记住登录状态
            days: 记住登录的天数
            
        Returns:
            str: 会话令牌
        """
        # 生成安全的令牌
        token = secrets.token_hex(32)
        
        # 设置过期时间
        expires_at = datetime.utcnow()
        if remember:
            expires_at += timedelta(days=days)
        else:
            expires_at += timedelta(hours=24)
        
        # 创建会话记录
        user_session = UserSession(
            user_id=user.id,
            session_token=token,
            ip_address=request.remote_addr,
            user_agent=request.user_agent.string if request.user_agent else None,
            expires_at=expires_at
        )
        
        try:
            db.session.add(user_session)
            db.session.commit()
            
            # 设置Flask会话
            session['user_id'] = user.id
            session['session_token'] = token
            
            return token
        except Exception as e:
            db.session.rollback()
            raise e
    
    @staticmethod
    def verify_session(session_token=None):
        """
        验证会话有效性
        
        Args:
            session_token: 会话令牌，如果为None则从Flask会话中获取
            
        Returns:
            User|None: 会话有效返回用户对象，无效返回None
        """
        if not session_token:
            session_token = session.get('session_token')
            
        if not session_token:
            return None
        
        # 查找会话记录
        user_session = UserSession.query.filter_by(session_token=session_token).first()
        
        if not user_session or not user_session.is_valid:
            return None
        
        return user_session.user
    
    @staticmethod
    def logout():
        """
        用户登出
        
        Returns:
            bool: 是否成功登出
        """
        session_token = session.get('session_token')
        
        if session_token:
            # 删除会话记录
            UserSession.query.filter_by(session_token=session_token).delete()
            db.session.commit()
        
        # 清除Flask会话
        session.clear()
        
        return True
    
    @staticmethod
    def get_current_user():
        """
        获取当前用户
        
        Returns:
            User|None: 当前用户或None
        """
        # 检查是否已经在g对象中
        if hasattr(g, 'user'):
            return g.user
        
        user_id = session.get('user_id')
        session_token = session.get('session_token')
        
        if not user_id or not session_token:
            return None
        
        # 验证会话
        user = AuthService.verify_session(session_token)
        if user:
            g.user = user
            return user
            
        return None 