from datetime import datetime
from typing import Any, TypeVar

from sqlalchemy.schema import Column as Column

from . import constants as constants
from .errors import (
    ERROR_ENTITY_COMPOSITE_KEY_NOT_SUPPORTED as ERROR_ENTITY_COMPOSITE_KEY_NOT_SUPPORTED,
    ERROR_NOT_CREATABLE as ERROR_NOT_CREATABLE,
    ERROR_NOT_SOFT_DELETABLE as ERROR_NOT_SOFT_DELETABLE,
    ERROR_NOT_UPDATABLE as ERROR_NOT_UPDATABLE,
)

T = TypeVar('T')

def current_timestamp() -> datetime:
    """Get the current timestamp in SYSTEM_TIMEZONE as a naive datetime (no tzinfo)."""

def get_class(value: T | type[T]) -> type[T]:
    """Get the class of a value.

    Args:
        value: Class or class instance.

    Returns:
       The class
    """

def get_pk(instance: Any) -> dict[str, Any]:
    """Return a dict of primary keys and values."""

def get_pk_columns(cls) -> list[Column[Any]]:
    """Return primary key columns.

    Args:
        cls: Model class or instance to get primary key columns from.

    Returns:
        List of primary key Column objects.
    """

def is_creatable(model: Any) -> bool:
    """Check if model supports creation fields.

    A model is creatable if it has either `created_at` or `created_by`.
    """

def is_soft_deletable(model: Any) -> bool:
    """Check if model supports soft deletion.

    A model is soft-deletable if it has either `deleted_at` or `deleted_by`.
    """

def is_updatable(model: Any) -> bool:
    """Check if model supports update tracking.

    A model is updatable if it has either `last_modified` or `last_modified_by`.
    """

def remove_from_registry(cls) -> None:
    """Clear a mapping from the SQLAlchemy registry.

    Args:
        cls: SQLAlchemy model class to remove from the registry
    """

def try_creatable(model: Any) -> None:
    """Raise error if model is not creatable."""

def try_pk_column(instance: Any) -> Column[Any]:
    """Return single primary key value or raise error."""

def try_soft_deletable(model: Any) -> None:
    """Raise error if model is not soft-deletable."""

def try_updatable(model: Any) -> None:
    """Raise error if model is not updatable."""
