"""
Base Repository

Provides common functionality for all repositories.
"""

import logging
from abc import ABC
from contextlib import contextmanager
from datetime import datetime, timezone
from typing import Generator, TypeVar, Generic
from uuid import UUID

from sqlmodel import Session

from backend.data.database import get_session_context

logger = logging.getLogger(__name__)

T = TypeVar("T")


class BaseRepository(ABC, Generic[T]):
    """Base class for all repositories.

    Provides:
    - Session management via context manager
    - Logging infrastructure
    - Common query patterns
    - Utility methods for datetime and UUID handling
    """

    @contextmanager
    def _session(self) -> Generator[Session, None, None]:
        """Get a database session with auto-commit/rollback."""
        with get_session_context() as session:
            yield session

    def _expunge(self, session: Session, entity: T) -> T:
        """Detach entity from session for safe return."""
        session.expunge(entity)
        return entity

    def _expunge_all(self, session: Session, entities: list[T]) -> list[T]:
        """Detach multiple entities from session."""
        for entity in entities:
            session.expunge(entity)
        return entities

    @staticmethod
    def _now() -> datetime:
        """Get current UTC time as timezone-aware datetime.

        Use this instead of datetime.utcnow() which is deprecated in Python 3.12+.
        """
        return datetime.now(timezone.utc)

    @staticmethod
    def _validate_uuid(value: str, field_name: str = "id") -> UUID:
        """Validate and convert string to UUID.

        Args:
            value: String to convert to UUID
            field_name: Name of field for error message

        Returns:
            Validated UUID

        Raises:
            ValueError: If value is not a valid UUID
        """
        try:
            return UUID(value)
        except (ValueError, TypeError) as e:
            raise ValueError(f"Invalid {field_name}: {value}") from e
