"""Tests for rbsp.core.varint — Variable-byte integer encoding."""

import os
import sys
import unittest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))

from rbsp.core.varint import (
    encode_varint,
    decode_varint,
    encode_varints,
    decode_varints,
    encode_delta,
    decode_delta,
)


class TestSingleVarint(unittest.TestCase):
    """Test single varint encode/decode."""

    def test_zero(self):
        data = encode_varint(0)
        val, consumed = decode_varint(data)
        self.assertEqual(val, 0)
        self.assertEqual(consumed, 1)

    def test_small_values(self):
        for v in [1, 42, 127]:
            data = encode_varint(v)
            val, consumed = decode_varint(data)
            self.assertEqual(val, v)
            self.assertEqual(consumed, 1)

    def test_medium_values(self):
        for v in [128, 255, 16383]:
            data = encode_varint(v)
            val, consumed = decode_varint(data)
            self.assertEqual(val, v)
            self.assertEqual(consumed, 2)

    def test_large_values(self):
        for v in [16384, 1_000_000, 2**32]:
            data = encode_varint(v)
            val, consumed = decode_varint(data)
            self.assertEqual(val, v)

    def test_decode_with_offset(self):
        prefix = b'\xff\xff'
        encoded = encode_varint(42)
        data = prefix + encoded
        val, consumed = decode_varint(data, offset=len(prefix))
        self.assertEqual(val, 42)


class TestBatchVarint(unittest.TestCase):
    """Test batch varint encode/decode."""

    def test_round_trip(self):
        values = [0, 1, 127, 128, 10000, 1_000_000]
        data = encode_varints(values)
        result = decode_varints(data)
        self.assertEqual(result, values)

    def test_empty(self):
        data = encode_varints([])
        result = decode_varints(data)
        self.assertEqual(result, [])

    def test_single(self):
        data = encode_varints([42])
        result = decode_varints(data)
        self.assertEqual(result, [42])


class TestDeltaEncoding(unittest.TestCase):
    """Test delta + varint encoding for sorted integers."""

    def test_round_trip(self):
        values = [10, 20, 35, 100, 500]
        data = encode_delta(values)
        result = decode_delta(data)
        self.assertEqual(result, values)

    def test_empty(self):
        data = encode_delta([])
        result = decode_delta(data)
        self.assertEqual(result, [])

    def test_single(self):
        data = encode_delta([42])
        result = decode_delta(data)
        self.assertEqual(result, [42])

    def test_consecutive(self):
        values = list(range(100))
        data = encode_delta(values)
        result = decode_delta(data)
        self.assertEqual(result, values)

    def test_compression_ratio(self):
        """Delta encoding of sequential IDs should be smaller than naive encoding."""
        values = list(range(0, 10000, 10))
        delta_data = encode_delta(values)
        naive_data = encode_varints(values)
        self.assertLess(len(delta_data), len(naive_data))


if __name__ == "__main__":
    unittest.main()
