import pytest
from fastapi.testclient import TestClient

from src.main import app

client = TestClient(app)

def test_image_paths_exist():
    """Test that all required image files exist."""
    from src.config import settings
    required_files = [
        settings.IMAGE_PATH / "billy.jpg",
        settings.IMAGE_PATH / "parrot.jpg",
    ]
    for file_path in required_files:
        assert file_path.exists(), f"Required file {file_path} not found"
        assert file_path.is_file(), f"{file_path} is not a file"

@pytest.mark.parametrize("transform_name,expected_data", [
    (
        "Resize",
        {
            "required_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            },
            "non_null_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            }
        }
    ),
    (
        "Blur",
        {
            "required_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            },
            "non_null_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            }
        }
    ),
    (
        "HorizontalFlip",
        {
            "required_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            },
            "non_null_keys": {
                "image",
                "mask", "bboxes", "keypoints",
            }
        }
    ),
])
def test_get_original_data(transform_name: str, expected_data: dict):
    """Test getting original data with appropriate visualizations based on transform."""
    # Ensure required files exist
    test_image_paths_exist()

    # Construct URL
    url = f"/original-data/{transform_name}"

    # Get response
    response = client.get(url)
    assert response.status_code == 200
    data = response.json()

    # Check required keys exist (now without transform_type/targets)
    required_keys = {"image", "mask", "bboxes", "keypoints"}
    present_keys = set(data.keys())
    assert present_keys == required_keys

    # Check which keys have non-null values
    non_null_keys = {k for k, v in data.items() if v is not None}
    assert non_null_keys == expected_data["non_null_keys"]

    # Validate image data
    assert data["image"].startswith("data:image/")

    # Validate visualization data if present
    if "mask" in non_null_keys:
        assert data["mask"].startswith("data:image/")

    if "bboxes" in non_null_keys:
        assert isinstance(data["bboxes"], list)
        if data["bboxes"]:
            assert len(data["bboxes"][0]) == 5  # x_min, y_min, x_max, y_max, label

    if "keypoints" in non_null_keys:
        assert isinstance(data["keypoints"], list)
        if data["keypoints"]:
            assert len(data["keypoints"][0]) == 3  # x, y, label


def test_get_original_data_invalid_transform():
    """Test error handling for invalid transform."""
    response = client.get("/original-data/NonExistentTransform")
    assert response.status_code == 404
    assert "not found" in response.json()["detail"].lower()

def test_get_original_data_image_quality():
    """Test that returned images have reasonable quality."""
    response = client.get("/original-data/Resize")
    assert response.status_code == 200
    data = response.json()

    # Check image has reasonable size
    assert len(data["image"]) > 1000, "Image seems too compressed"

    # Check mask has reasonable size
    assert len(data["mask"]) > 1000, "Mask image seems too compressed"


@pytest.mark.parametrize("transform_name", [
    "FDA",
    "PixelDistributionAdaptation",
    "HistogramMatching",
])
def test_get_reference_data(transform_name: str):
    """Test getting reference image data."""
    response = client.get(f"/reference-data/{transform_name}")
    assert response.status_code == 200
    data = response.json()

    # Expect a list
    assert isinstance(data, list)
    assert len(data) > 0 # Should return at least the default parrot image

    # Check structure of the first item in the list
    first_item = data[0]
    assert isinstance(first_item, dict)
    assert "image" in first_item
    assert "mask" in first_item
    assert "bboxes" in first_item
    assert "keypoints" in first_item

    # Basic check for image content (should be base64)
    assert first_item["image"].startswith("data:image/webp;base64,")
