#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
会话管理模块
处理用户登录状态、会话令牌和权限验证
"""

import secrets
import time
import hashlib
from typing import Dict, Optional, Any
from datetime import datetime, timedelta
from user_manager import User


class Session:
    """会话类"""
    
    def __init__(self, session_id: str, user_id: int, username: str, role: str,
                 created_at: datetime, expires_at: datetime):
        """
        初始化会话对象
        
        Args:
            session_id: 会话ID
            user_id: 用户ID
            username: 用户名
            role: 用户角色
            created_at: 创建时间
            expires_at: 过期时间
        """
        self.session_id = session_id
        self.user_id = user_id
        self.username = username
        self.role = role
        self.created_at = created_at
        self.expires_at = expires_at
        self.last_activity = datetime.now()
    
    def is_expired(self) -> bool:
        """检查会话是否过期"""
        return datetime.now() > self.expires_at
    
    def is_admin(self) -> bool:
        """检查是否为管理员"""
        return self.role == 'admin'
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'session_id': self.session_id,
            'user_id': self.user_id,
            'username': self.username,
            'role': self.role,
            'created_at': self.created_at.isoformat(),
            'expires_at': self.expires_at.isoformat(),
            'last_activity': self.last_activity.isoformat()
        }


class SessionManager:
    """会话管理器"""
    
    def __init__(self, session_timeout_hours: int = 24):
        """
        初始化会话管理器
        
        Args:
            session_timeout_hours: 会话超时时间（小时）
        """
        self.sessions: Dict[str, Session] = {}
        self.session_timeout_hours = session_timeout_hours
        
        # 启动清理线程（简化版，实际使用中可以用定时任务）
        self._last_cleanup = time.time()
    
    def generate_session_id(self, user_id: int) -> str:
        """
        生成会话ID
        
        Args:
            user_id: 用户ID
            
        Returns:
            会话ID
        """
        # 使用用户ID、时间戳和随机数生成唯一会话ID
        timestamp = str(int(time.time()))
        random_part = secrets.token_hex(16)
        data = f"{user_id}:{timestamp}:{random_part}"
        
        return hashlib.sha256(data.encode()).hexdigest()
    
    def create_session(self, user: User) -> Session:
        """
        创建新会话
        
        Args:
            user: 用户对象
            
        Returns:
            会话对象
        """
        session_id = self.generate_session_id(user.user_id)
        created_at = datetime.now()
        expires_at = created_at + timedelta(hours=self.session_timeout_hours)
        
        session = Session(
            session_id=session_id,
            user_id=user.user_id,
            username=user.username,
            role=user.role,
            created_at=created_at,
            expires_at=expires_at
        )
        
        # 存储会话
        self.sessions[session_id] = session
        
        # 清理过期会话
        self._cleanup_expired_sessions()
        
        print(f"创建会话: {user.username} ({session_id[:8]}...)")
        return session
    
    def get_session(self, session_id: str) -> Optional[Session]:
        """
        获取会话
        
        Args:
            session_id: 会话ID
            
        Returns:
            会话对象，如果不存在或已过期返回None
        """
        if not session_id or session_id not in self.sessions:
            return None
        
        session = self.sessions[session_id]
        
        # 检查是否过期
        if session.is_expired():
            self.destroy_session(session_id)
            return None
        
        # 更新最后活动时间
        session.last_activity = datetime.now()
        
        return session
    
    def destroy_session(self, session_id: str) -> bool:
        """
        销毁会话
        
        Args:
            session_id: 会话ID
            
        Returns:
            成功返回True
        """
        if session_id in self.sessions:
            session = self.sessions[session_id]
            print(f"销毁会话: {session.username} ({session_id[:8]}...)")
            del self.sessions[session_id]
            return True
        return False
    
    def destroy_user_sessions(self, user_id: int):
        """
        销毁指定用户的所有会话
        
        Args:
            user_id: 用户ID
        """
        session_ids_to_remove = []
        
        for session_id, session in self.sessions.items():
            if session.user_id == user_id:
                session_ids_to_remove.append(session_id)
        
        for session_id in session_ids_to_remove:
            self.destroy_session(session_id)
    
    def validate_session(self, session_id: str) -> bool:
        """
        验证会话有效性
        
        Args:
            session_id: 会话ID
            
        Returns:
            有效返回True
        """
        session = self.get_session(session_id)
        return session is not None
    
    def require_login(self, session_id: str) -> Optional[Session]:
        """
        要求用户登录
        
        Args:
            session_id: 会话ID
            
        Returns:
            有效会话对象，否则返回None
        """
        return self.get_session(session_id)
    
    def require_admin(self, session_id: str) -> Optional[Session]:
        """
        要求管理员权限
        
        Args:
            session_id: 会话ID
            
        Returns:
            有效的管理员会话对象，否则返回None
        """
        session = self.get_session(session_id)
        if session and session.is_admin():
            return session
        return None
    
    def _cleanup_expired_sessions(self):
        """清理过期会话"""
        current_time = time.time()
        
        # 每小时清理一次
        if current_time - self._last_cleanup < 3600:
            return
        
        self._last_cleanup = current_time
        
        expired_sessions = []
        for session_id, session in self.sessions.items():
            if session.is_expired():
                expired_sessions.append(session_id)
        
        for session_id in expired_sessions:
            self.destroy_session(session_id)
        
        if expired_sessions:
            print(f"清理了 {len(expired_sessions)} 个过期会话")
    
    def get_active_sessions(self) -> Dict[str, Session]:
        """获取所有活跃会话"""
        self._cleanup_expired_sessions()
        return self.sessions.copy()
    
    def get_session_count(self) -> int:
        """获取活跃会话数量"""
        self._cleanup_expired_sessions()
        return len(self.sessions)
    
    def extend_session(self, session_id: str, hours: int = None) -> bool:
        """
        延长会话时间
        
        Args:
            session_id: 会话ID
            hours: 延长小时数，默认使用配置的超时时间
            
        Returns:
            成功返回True
        """
        session = self.get_session(session_id)
        if not session:
            return False
        
        extend_hours = hours or self.session_timeout_hours
        session.expires_at = datetime.now() + timedelta(hours=extend_hours)
        
        return True


# 全局会话管理器实例
session_manager = SessionManager()


def get_session_manager() -> SessionManager:
    """获取会话管理器实例"""
    return session_manager


if __name__ == "__main__":
    # 测试会话管理器
    print("=== 会话管理器测试 ===")
    
    from user_manager import User
    
    # 创建测试用户
    test_user = User(
        user_id=1,
        username="test_user",
        role="user"
    )
    
    # 创建会话
    sm = get_session_manager()
    session = sm.create_session(test_user)
    
    print(f"创建会话: {session.session_id}")
    print(f"会话有效: {sm.validate_session(session.session_id)}")
    
    # 获取会话
    retrieved_session = sm.get_session(session.session_id)
    if retrieved_session:
        print(f"获取会话成功: {retrieved_session.username}")
    
    # 销毁会话
    sm.destroy_session(session.session_id)
    print(f"会话已销毁: {sm.validate_session(session.session_id)}") 