import pytest

from sqlalchemy_relay_pagination.config import PaginationConfig
from sqlalchemy_relay_pagination.exceptions import InvalidArgumentsError
from sqlalchemy_relay_pagination.types import PaginationArgs


@pytest.fixture
def config():
    return PaginationConfig(default_page_size=10, max_page_size=100)


def test_first_and_last_raises(config):
    with pytest.raises(InvalidArgumentsError, match="both"):
        PaginationArgs(first=5, last=5, config=config)


def test_negative_first_raises(config):
    with pytest.raises(InvalidArgumentsError, match="non-negative"):
        PaginationArgs(first=-1, config=config)


def test_negative_last_raises(config):
    with pytest.raises(InvalidArgumentsError, match="non-negative"):
        PaginationArgs(last=-1, config=config)


def test_default_page_size(config):
    args = PaginationArgs(config=config)
    assert args.effective_limit == 10
    assert args.is_forward is True


def test_first_sets_forward(config):
    args = PaginationArgs(first=5, config=config)
    assert args.effective_limit == 5
    assert args.is_forward is True


def test_last_sets_backward(config):
    args = PaginationArgs(last=5, config=config)
    assert args.effective_limit == 5
    assert args.is_forward is False


def test_exceeds_max_page_size_raises(config):
    with pytest.raises(InvalidArgumentsError, match="exceeds maximum"):
        PaginationArgs(first=101, config=config)


def test_exact_max_page_size_allowed(config):
    args = PaginationArgs(first=100, config=config)
    assert args.effective_limit == 100


def test_zero_first_allowed(config):
    args = PaginationArgs(first=0, config=config)
    assert args.effective_limit == 0
    assert args.is_forward is True


def test_cursor_forward(config):
    args = PaginationArgs(first=5, after="abc", config=config)
    assert args.cursor == "abc"


def test_cursor_backward(config):
    args = PaginationArgs(last=5, before="xyz", config=config)
    assert args.cursor == "xyz"


def test_none_config_resolves_to_global():
    # Passing config=None should fall back to the global config, not error.
    args = PaginationArgs(first=5, config=None)  # type: ignore[arg-type]
    assert args.effective_limit == 5
