import io
from pathlib import Path

import pytest
from PIL import Image

from src.image_sanitizer import MAX_IMAGE_PIXELS, sanitize_image


def test_runtime_dependencies_install_the_image_decoder():
    requirements = (Path(__file__).parents[1] / "requirements.txt").read_text().splitlines()
    assert any(line.startswith("Pillow==") for line in requirements)


def encoded_image(format_name, size=(3, 2), *, exif=None):
    image = Image.new("RGB", size)
    image.putdata(
        [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (0, 255, 255), (255, 0, 255)]
    )
    output = io.BytesIO()
    image.save(output, format=format_name, exif=exif or b"")
    return output.getvalue()


def test_sanitize_image_applies_orientation_and_removes_jpeg_metadata():
    exif = Image.Exif()
    exif[274] = 6
    exif[ GPS_TAG := 34853 ] = {1: "N", 2: (1, 1, 1)}
    source = encoded_image("JPEG", exif=exif)

    sanitized = sanitize_image("image/jpeg", source)

    with Image.open(io.BytesIO(sanitized)) as result:
        assert result.size == (2, 3)
        assert not result.getexif()
        assert GPS_TAG not in result.info
        assert result.format == "JPEG"


def test_sanitize_image_rejects_bytes_that_do_not_match_claimed_type():
    source = encoded_image("PNG")

    with pytest.raises(ValueError, match="does not match"):
        sanitize_image("image/jpeg", source)


def test_sanitize_image_rejects_over_twelve_megapixels_before_decoding():
    image = Image.new("RGB", (4096, 3073))
    output = io.BytesIO()
    image.save(output, format="PNG")

    with pytest.raises(ValueError, match="12 megapixels"):
        sanitize_image("image/png", output.getvalue())


def test_sanitize_image_rejects_animated_webp():
    first = Image.new("RGB", (2, 2), "red")
    second = Image.new("RGB", (2, 2), "blue")
    output = io.BytesIO()
    first.save(output, format="WEBP", save_all=True, append_images=[second], duration=100)

    with pytest.raises(ValueError, match="animated"):
        sanitize_image("image/webp", output.getvalue())
