import pytest
from src.transforms.constants import CV2ConstantHandler
import cv2



@pytest.fixture
def cv2_handler():
    return CV2ConstantHandler()


@pytest.mark.parametrize("constant_type,prefix,expected_constants", [
    ("interpolation", "cv2.INTER_", {
        "cv2.INTER_NEAREST",
        "cv2.INTER_LINEAR",
        "cv2.INTER_CUBIC",
        "cv2.INTER_AREA",
        "cv2.INTER_LANCZOS4",
        "cv2.INTER_LINEAR_EXACT",
        "cv2.INTER_NEAREST_EXACT",
    }),
    ("border", "cv2.BORDER_", {
        "cv2.BORDER_CONSTANT",
        "cv2.BORDER_REPLICATE",
        "cv2.BORDER_REFLECT",
        "cv2.BORDER_WRAP",
        "cv2.BORDER_REFLECT_101",
    })
])
def test_cv2_constant_handler(constant_type: str, prefix: str, expected_constants: set[str]):
    """Test CV2ConstantHandler's constant name handling."""
    handler = CV2ConstantHandler()

    if constant_type == "interpolation":
        constants = handler.interpolation_names
    else:
        constants = handler.border_names

    # Test prefix
    assert all(name.startswith(prefix) for name in constants)

    # Test specific constants are present
    for constant in expected_constants:
        assert constant in constants


@pytest.mark.parametrize("value,prefix,expected", [
    (1, "INTER_", "cv2.INTER_LINEAR"),
    (0, "BORDER_", "cv2.BORDER_CONSTANT"),
])
def test_cv2_constant_formatting(value: int, prefix: str, expected: str):
    """Test CV2ConstantHandler's constant formatting."""
    handler = CV2ConstantHandler()
    assert f"cv2.{handler.get_constant_name(value, prefix)}" == expected


@pytest.mark.parametrize("input_value,prefix,expected", [
    (cv2.INTER_LINEAR, "INTER_", "INTER_LINEAR"),
    (cv2.INTER_NEAREST, "INTER_", "INTER_NEAREST"),
    (cv2.BORDER_CONSTANT, "BORDER_", "BORDER_CONSTANT"),  # Use actual cv2.BORDER_CONSTANT value
])
def test_get_constant_name_with_int(cv2_handler, input_value, prefix, expected):
    """Test that integer values are correctly converted to constant names."""
    result = cv2_handler.get_constant_name(input_value, prefix)
    assert result == expected

@pytest.mark.parametrize("input_value,prefix", [
    ("cv2.INTER_LINEAR", "INTER_"),  # Should raise ValueError - string input not allowed
    ("cv2.BORDER_CONSTANT", "BORDER_"),  # Should raise ValueError - string input not allowed
    (999, "INTER_"),  # Should raise ValueError - invalid constant value
    (1, "INVALID_"),  # Should raise ValueError - invalid prefix
])
def test_get_constant_name_invalid_inputs(cv2_handler, input_value, prefix):
    """Test that invalid inputs raise appropriate errors."""
    with pytest.raises(ValueError):
        cv2_handler.get_constant_name(input_value, prefix)

@pytest.mark.parametrize("input_value,expected", [
    (1, True),  # INTER_LINEAR
    (0, True),  # INTER_NEAREST
    (999, False),  # Invalid value
])
def test_is_interpolation(cv2_handler, input_value, expected):
    """Test that interpolation values are correctly validated."""
    assert cv2_handler.is_interpolation(input_value) == expected

@pytest.mark.parametrize("input_value,expected", [
    (4, True),  # BORDER_CONSTANT
    (0, True),  # BORDER_REPLICATE
    (999, False),  # Invalid value
])
def test_is_border_mode(cv2_handler, input_value, expected):
    """Test that border mode values are correctly validated."""
    assert cv2_handler.is_border_mode(input_value) == expected


@pytest.mark.parametrize("input_name,expected", [
    ("cv2.BORDER_CONSTANT", cv2.BORDER_CONSTANT),
    ("BORDER_CONSTANT", cv2.BORDER_CONSTANT),
    ("cv2.BORDER_REPLICATE", cv2.BORDER_REPLICATE),
    ("BORDER_REPLICATE", cv2.BORDER_REPLICATE),
    ("cv2.BORDER_REFLECT", cv2.BORDER_REFLECT),
    ("BORDER_REFLECT", cv2.BORDER_REFLECT),
    ("cv2.BORDER_WRAP", cv2.BORDER_WRAP),
    ("BORDER_WRAP", cv2.BORDER_WRAP),
    ("cv2.BORDER_REFLECT_101", cv2.BORDER_REFLECT_101),
    ("BORDER_REFLECT_101", cv2.BORDER_REFLECT_101),
])
def test_get_border_constant_valid(cv2_handler, input_name, expected):
    """Test conversion of valid border constant names to values."""
    assert cv2_handler.get_border_constant(input_name) == expected


@pytest.mark.parametrize("input_name,expected", [
    ("cv2.INTER_NEAREST", cv2.INTER_NEAREST),
    ("INTER_NEAREST", cv2.INTER_NEAREST),
    ("cv2.INTER_LINEAR", cv2.INTER_LINEAR),
    ("INTER_LINEAR", cv2.INTER_LINEAR),
    ("cv2.INTER_CUBIC", cv2.INTER_CUBIC),
    ("INTER_CUBIC", cv2.INTER_CUBIC),
    ("cv2.INTER_AREA", cv2.INTER_AREA),
    ("INTER_AREA", cv2.INTER_AREA),
    ("cv2.INTER_LANCZOS4", cv2.INTER_LANCZOS4),
    ("INTER_LANCZOS4", cv2.INTER_LANCZOS4),
    ("cv2.INTER_LINEAR_EXACT", cv2.INTER_LINEAR_EXACT),
    ("INTER_LINEAR_EXACT", cv2.INTER_LINEAR_EXACT),
    ("cv2.INTER_NEAREST_EXACT", cv2.INTER_NEAREST_EXACT),
    ("INTER_NEAREST_EXACT", cv2.INTER_NEAREST_EXACT),
])
def test_get_interpolation_constant_valid(cv2_handler, input_name, expected):
    """Test conversion of valid interpolation constant names to values."""
    assert cv2_handler.get_interpolation_constant(input_name) == expected
