"""
Session management for encrypted database connections.
Handles session creation, validation, and cleanup.
"""

import datetime
import gc
import secrets
from datetime import UTC
from typing import Dict, Optional

from loguru import logger

from ...security import get_security_default


class SessionManager:
    """Manages user sessions and database connection lifecycle."""

    def __init__(self):
        self.sessions: Dict[str, dict] = {}
        # Load session timeouts from security settings
        session_hours = get_security_default(
            "security.session_timeout_hours", 2
        )
        remember_days = get_security_default(
            "security.session_remember_me_days", 30
        )
        self.session_timeout = datetime.timedelta(hours=session_hours)
        self.remember_me_timeout = datetime.timedelta(days=remember_days)

    def create_session(self, username: str, remember_me: bool = False) -> str:
        """Create a new session for a user."""
        session_id = secrets.token_urlsafe(32)

        self.sessions[session_id] = {
            "username": username,
            "created_at": datetime.datetime.now(UTC),
            "last_access": datetime.datetime.now(UTC),
            "remember_me": remember_me,
        }

        logger.debug(f"Created session {session_id[:8]}... for user {username}")
        return session_id

    def validate_session(self, session_id: str) -> Optional[str]:
        """
        Validate a session and return username if valid.
        Updates last access time.
        """
        if session_id not in self.sessions:
            return None

        session_data = self.sessions[session_id]
        now = datetime.datetime.now(UTC)

        # Check timeout
        timeout = (
            self.remember_me_timeout
            if session_data["remember_me"]
            else self.session_timeout
        )
        if now - session_data["last_access"] > timeout:
            # Session expired
            self.destroy_session(session_id)
            logger.debug(f"Session {session_id[:8]}... expired")
            return None

        # Update last access
        session_data["last_access"] = now
        return session_data["username"]

    def destroy_session(self, session_id: str):
        """Destroy a session and clean up."""
        if session_id in self.sessions:
            username = self.sessions[session_id]["username"]
            del self.sessions[session_id]

            # Force garbage collection to clear any sensitive data
            gc.collect()

            logger.debug(
                f"Destroyed session {session_id[:8]}... for user {username}"
            )

    def cleanup_expired_sessions(self):
        """Remove all expired sessions."""
        now = datetime.datetime.now(UTC)
        expired = []

        for session_id, data in self.sessions.items():
            timeout = (
                self.remember_me_timeout
                if data["remember_me"]
                else self.session_timeout
            )
            if now - data["last_access"] > timeout:
                expired.append(session_id)

        for session_id in expired:
            self.destroy_session(session_id)

        if expired:
            logger.info(f"Cleaned up {len(expired)} expired sessions")

    def get_active_sessions_count(self) -> int:
        """Get count of active sessions."""
        self.cleanup_expired_sessions()
        return len(self.sessions)

    def get_user_sessions(self, username: str) -> list:
        """Get all active sessions for a user."""
        user_sessions = []
        for session_id, data in self.sessions.items():
            if data["username"] == username:
                user_sessions.append(
                    {
                        "session_id": session_id[:8] + "...",
                        "created_at": data["created_at"],
                        "last_access": data["last_access"],
                        "remember_me": data["remember_me"],
                    }
                )
        return user_sessions
