import json

import pytest

from sqlalchemy_relay_pagination.codec import Base64JsonCodec, CursorCodec
from sqlalchemy_relay_pagination.exceptions import InvalidCursorError


def test_roundtrip():
    codec = Base64JsonCodec()
    original = {"id": 42, "name": "Alice"}
    encoded = codec.encode(original)
    decoded = codec.decode(encoded)
    assert decoded == {"id": "42", "name": "Alice"}


def test_output_is_urlsafe():
    codec = Base64JsonCodec()
    encoded = codec.encode({"id": 1, "name": "Test+Value/Here"})
    assert "+" not in encoded
    assert "/" not in encoded


def test_output_is_not_plain_json():
    codec = Base64JsonCodec()
    encoded = codec.encode({"id": 1, "name": "Alice"})
    with pytest.raises((json.JSONDecodeError, ValueError)):
        json.loads(encoded)


def test_invalid_cursor_raises():
    codec = Base64JsonCodec()
    with pytest.raises(InvalidCursorError):
        codec.decode("not-valid-base64!!!")


def test_custom_codec_satisfies_protocol():
    class MyCodec:
        def encode(self, values: dict) -> str:
            return ":".join(f"{k}={v}" for k, v in values.items())

        def decode(self, cursor: str) -> dict:
            return dict(pair.split("=", 1) for pair in cursor.split(":"))

    obj = MyCodec()
    assert isinstance(obj, CursorCodec)
