"""Global pagination configuration backed by pydantic-settings.

``PaginationConfig`` is a ``BaseSettings`` model, so every field can be
overridden with an environment variable prefixed ``SQLALCHEMY_RELAY_PAGINATION_``:

    SQLALCHEMY_RELAY_PAGINATION_DEFAULT_PAGE_SIZE=50
    SQLALCHEMY_RELAY_PAGINATION_MAX_PAGE_SIZE=500

The module keeps a single global instance that is used by ``paginate`` /
``paginate_sync`` when no explicit ``config`` argument is supplied.  Call
``configure()`` to replace it at application start-up (e.g. in your ASGI
lifespan handler), and ``get_config()`` to read the current value.
"""

from pydantic import Field, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

from sqlalchemy_relay_pagination.codec import Base64JsonCodec, CursorCodec

MIN_PAGE_SIZE = 1
DEFAULT_PAGE_SIZE = 100
DEFAULT_MAX_PAGE_SIZE = 2**15  # 32768


class PaginationConfig(BaseSettings):
    """Pagination limits, configurable via environment variables or code."""

    model_config = SettingsConfigDict(
        env_prefix="SQLALCHEMY_RELAY_PAGINATION_",
        arbitrary_types_allowed=True,
    )

    default_page_size: int = DEFAULT_PAGE_SIZE
    max_page_size: int = DEFAULT_MAX_PAGE_SIZE
    cursor_codec: CursorCodec = Field(default_factory=Base64JsonCodec)

    @model_validator(mode="after")
    def validate_sizes(self) -> "PaginationConfig":
        if not (MIN_PAGE_SIZE <= self.default_page_size <= self.max_page_size):
            raise ValueError(
                f"Must satisfy: {MIN_PAGE_SIZE} <= default_page_size ({self.default_page_size}) "
                f"<= max_page_size ({self.max_page_size})"
            )
        return self


_global_config: PaginationConfig = PaginationConfig()


def configure(config: PaginationConfig) -> None:
    """Replace the process-wide default ``PaginationConfig``."""
    global _global_config  # noqa: PLW0603
    _global_config = config


def get_config() -> PaginationConfig:
    """Return the current process-wide ``PaginationConfig``."""
    return _global_config
