"""
Session management core logic.

Provides business logic for user session management including creation,
retrieval, and deletion of sessions.
"""

import uuid
from typing import Any, List

from fastauth.adapters.base.sessions import SessionAdapter
from fastauth.adapters.base.users import UserAdapter


class SessionNotFoundError(Exception):
    """Raised when a session is not found."""


def create_session(
    *,
    sessions: SessionAdapter,
    users: UserAdapter,
    user_id: uuid.UUID,
    device: str | None = None,
    ip_address: str | None = None,
    user_agent: str | None = None,
) -> Any:
    """
    Create a new session for a user.

    Args:
        sessions: Session adapter for database operations
        users: User adapter for database operations
        user_id: User's unique identifier
        device: Device information
        ip_address: IP address of the client
        user_agent: User agent string

    Returns:
        Created session object
    """
    session = sessions.create_session(
        user_id=user_id,
        device=device,
        ip_address=ip_address,
        user_agent=user_agent,
    )

    users.update_last_login(user_id=user_id)

    return session


def get_user_sessions(
    *,
    sessions: SessionAdapter,
    user_id: uuid.UUID,
) -> List[Any]:
    """
    Get all active sessions for a user.

    Args:
        sessions: Session adapter for database operations
        user_id: User's unique identifier

    Returns:
        List of session objects
    """
    return sessions.get_user_sessions(user_id)


def delete_session(
    *,
    sessions: SessionAdapter,
    session_id: uuid.UUID,
    user_id: uuid.UUID,
) -> None:
    """
    Delete a specific session.

    Args:
        sessions: Session adapter for database operations
        session_id: Session's unique identifier
        user_id: User's unique identifier (for authorization)

    Raises:
        SessionNotFoundError: If session doesn't exist or doesn't belong to user
    """
    session = sessions.get_session_by_id(session_id)

    if not session or session.user_id != user_id:
        raise SessionNotFoundError("Session not found")

    sessions.delete_session(session_id)


def delete_all_user_sessions(
    *,
    sessions: SessionAdapter,
    user_id: uuid.UUID,
    except_session_id: uuid.UUID | None = None,
) -> None:
    """
    Delete all sessions for a user, optionally excluding the current session.

    Args:
        sessions: Session adapter for database operations
        user_id: User's unique identifier
        except_session_id: Optional session ID to keep (current session)
    """
    sessions.delete_user_sessions(
        user_id=user_id,
        except_session_id=except_session_id,
    )


def update_session_activity(
    *,
    sessions: SessionAdapter,
    session_id: uuid.UUID,
) -> None:
    """
    Update the last active timestamp for a session.

    Args:
        sessions: Session adapter for database operations
        session_id: Session's unique identifier
    """
    sessions.update_last_active(session_id)


def cleanup_inactive_sessions(
    *,
    sessions: SessionAdapter,
    inactive_days: int = 30,
) -> None:
    """
    Remove sessions that haven't been active for a specified number of days.

    Args:
        sessions: Session adapter for database operations
        inactive_days: Number of days of inactivity before cleanup (default: 30)
    """
    sessions.cleanup_inactive_sessions(inactive_days)
