"""Tests for media-mcp image tools."""

import tempfile
from pathlib import Path

from PIL import Image
import pytest

# We import the tool functions directly for unit testing
from media_mcp.server import (
    get_image_info,
    resize_image,
    convert_image,
    compress_image,
    crop_image,
    create_thumbnail,
    strip_metadata,
    rotate_image,
    flip_image,
    apply_filter,
)


@pytest.fixture
def sample_png(tmp_path):
    """Create a sample PNG image for testing."""
    img = Image.new("RGB", (800, 600), color=(255, 0, 0))
    path = tmp_path / "test_image.png"
    img.save(path, format="PNG")
    return str(path)


@pytest.fixture
def sample_rgba(tmp_path):
    """Create a sample RGBA image for testing."""
    img = Image.new("RGBA", (400, 300), color=(0, 255, 0, 128))
    path = tmp_path / "test_rgba.png"
    img.save(path, format="PNG")
    return str(path)


class TestGetImageInfo:
    def test_basic_info(self, sample_png):
        info = get_image_info(sample_png)
        assert info["width"] == 800
        assert info["height"] == 600
        assert info["format"] == "PNG"
        assert info["mode"] == "RGB"
        assert info["file_size_bytes"] > 0

    def test_file_not_found(self):
        with pytest.raises(FileNotFoundError):
            get_image_info("/nonexistent/image.png")


class TestResizeImage:
    def test_resize_by_width(self, sample_png):
        result = resize_image(sample_png, width=400)
        assert result["new_size"] == "400x300"
        assert Path(result["output_path"]).exists()

    def test_resize_by_height(self, sample_png):
        result = resize_image(sample_png, height=300)
        assert result["new_size"] == "400x300"

    def test_resize_by_scale(self, sample_png):
        result = resize_image(sample_png, scale=0.5)
        assert result["new_size"] == "400x300"

    def test_resize_both_dims_keep_aspect(self, sample_png):
        result = resize_image(sample_png, width=200, height=200, keep_aspect_ratio=True)
        # Should fit within 200x200 keeping 4:3 ratio
        assert "200x150" == result["new_size"]

    def test_resize_no_params_raises(self, sample_png):
        with pytest.raises(ValueError):
            resize_image(sample_png)


class TestConvertImage:
    def test_png_to_jpeg(self, sample_png):
        result = convert_image(sample_png, format="jpeg")
        assert result["format"] == "JPEG"
        assert result["output_path"].endswith(".jpeg")
        assert Path(result["output_path"]).exists()

    def test_png_to_webp(self, sample_png):
        result = convert_image(sample_png, format="webp")
        assert result["format"] == "WEBP"

    def test_rgba_to_jpeg(self, sample_rgba):
        """RGBA images should be auto-converted to RGB for JPEG."""
        result = convert_image(sample_rgba, format="jpeg")
        assert result["format"] == "JPEG"

    def test_unsupported_format(self, sample_png):
        with pytest.raises(ValueError, match="Unsupported format"):
            convert_image(sample_png, format="xyz")


class TestCompressImage:
    def test_compress_reduces_size(self, sample_png):
        result = compress_image(sample_png, quality=30)
        # Compressed file should exist
        assert Path(result["output_path"]).exists()
        assert result["compressed_size_bytes"] > 0

    def test_compress_with_max_dims(self, sample_png):
        result = compress_image(sample_png, quality=50, max_width=400)
        assert "400x" in result["dimensions"] or int(result["dimensions"].split("x")[0]) <= 400


class TestCropImage:
    def test_basic_crop(self, sample_png):
        result = crop_image(sample_png, left=100, top=100, right=500, bottom=400)
        assert result["cropped_size"] == "400x300"

    def test_invalid_crop_region(self, sample_png):
        with pytest.raises(ValueError):
            crop_image(sample_png, left=500, top=0, right=100, bottom=600)

    def test_out_of_bounds_crop(self, sample_png):
        with pytest.raises(ValueError):
            crop_image(sample_png, left=0, top=0, right=9999, bottom=600)


class TestCreateThumbnail:
    def test_default_thumbnail(self, sample_png):
        result = create_thumbnail(sample_png)
        # Should fit within 256x256
        w, h = map(int, result["thumbnail_size"].split("x"))
        assert w <= 256
        assert h <= 256

    def test_custom_size(self, sample_png):
        result = create_thumbnail(sample_png, size=128)
        w, h = map(int, result["thumbnail_size"].split("x"))
        assert w <= 128
        assert h <= 128


class TestStripMetadata:
    def test_strip(self, sample_png):
        result = strip_metadata(sample_png)
        assert result["metadata_removed"] is True
        assert Path(result["output_path"]).exists()


class TestRotateImage:
    def test_rotate_90(self, sample_png):
        result = rotate_image(sample_png, degrees=90)
        assert Path(result["output_path"]).exists()
        assert result["rotation_degrees"] == 90


class TestFlipImage:
    def test_horizontal_flip(self, sample_png):
        result = flip_image(sample_png, direction="horizontal")
        assert Path(result["output_path"]).exists()

    def test_vertical_flip(self, sample_png):
        result = flip_image(sample_png, direction="vertical")
        assert Path(result["output_path"]).exists()

    def test_invalid_direction(self, sample_png):
        with pytest.raises(ValueError):
            flip_image(sample_png, direction="diagonal")


class TestApplyFilter:
    def test_grayscale(self, sample_png):
        result = apply_filter(sample_png, filter_name="grayscale")
        assert result["filter_applied"] == "grayscale"

    def test_blur(self, sample_png):
        result = apply_filter(sample_png, filter_name="blur")
        assert result["filter_applied"] == "blur"

    def test_unknown_filter(self, sample_png):
        with pytest.raises(ValueError, match="Unknown filter"):
            apply_filter(sample_png, filter_name="nonexistent")
