"""Link-preview image validation (task 1.6, design D6, spec link-preview).

Pure tests: what they assert is a decision about bytes, so there is no database and no HTTP
here. The fixtures below are hand-built headers rather than real photographs, which is
exactly what is under test — `read_dimensions` reads the header and nothing else, on purpose,
so that the API image needs no imaging library.

The JPEG fixture deliberately carries a comment segment before its frame header. A JPEG in
the wild leads with EXIF or a colour profile, and one that embeds a thumbnail in EXIF
contains a *second* frame header that a naive byte search would find first. Stepping over
segments by their length is the only way to reach the right one.
"""

import struct

import pytest

from app.services import media

from .conftest import jpeg_bytes as _jpeg
from .conftest import png_bytes as _png

# ------------------------------------------------------------------ dimensions


def test_png_dimensions_are_read_from_the_header() -> None:
    assert media.read_dimensions(_png(1200, 630), "image/png") == (1200, 630)


def test_jpeg_dimensions_are_read_past_an_earlier_segment() -> None:
    assert media.read_dimensions(_jpeg(1200, 630), "image/jpeg") == (1200, 630)


def test_jpeg_thumbnail_before_the_real_frame_does_not_win() -> None:
    """An EXIF thumbnail is a whole JPEG inside a segment. Walking by length skips it; a byte
    search for the SOF marker would return the thumbnail's dimensions instead."""
    thumbnail = _jpeg(160, 120)
    exif = b"\xff\xe1" + struct.pack(">H", 2 + len(thumbnail)) + thumbnail
    data = b"\xff\xd8" + exif + _jpeg(1200, 630)[2:]
    assert media.read_dimensions(data, "image/jpeg") == (1200, 630)


def test_bytes_that_are_not_an_image_measure_as_none() -> None:
    assert media.read_dimensions(b"not an image at all", "image/png") is None
    assert media.read_dimensions(b"\xff\xd8truncated", "image/jpeg") is None


# ------------------------------------------------------------------ validation


def test_a_well_formed_preview_is_accepted_without_warning() -> None:
    kind, width, height, warning = media.validate_preview_image(_png(1200, 630), "image/png")
    assert (kind, width, height) == ("image/png", 1200, 630)
    assert warning is None


def test_jpeg_is_accepted() -> None:
    kind, _, _, _ = media.validate_preview_image(_jpeg(1200, 630), "image/jpeg")
    assert kind == "image/jpeg"


@pytest.mark.parametrize("content_type", ["image/svg+xml", "image/webp", "image/avif"])
def test_non_raster_and_patchy_formats_are_refused_by_name(content_type: str) -> None:
    """SVG no unfurler renders; WebP and AVIF are refused for inconsistent support, so the
    message has to say what *is* accepted or the designer has nothing to act on."""
    with pytest.raises(media.MediaRejectedError) as exc:
        media.validate_preview_image(_png(1200, 630), content_type)
    assert "PNG" in str(exc.value) and "JPEG" in str(exc.value)


def test_oversized_is_refused_with_both_numbers() -> None:
    data = _png(1200, 630, pad=media.PREVIEW_MAX_BYTES)
    with pytest.raises(media.MediaRejectedError) as exc:
        media.validate_preview_image(data, "image/png")
    message = str(exc.value)
    assert "KB" in message and "300 KB" in message


def test_undersized_is_refused_with_its_own_dimensions() -> None:
    with pytest.raises(media.MediaRejectedError) as exc:
        media.validate_preview_image(_png(400, 210), "image/png")
    assert "400x210" in str(exc.value)
    assert f"{media.PREVIEW_MIN_WIDTH}x{media.PREVIEW_MIN_HEIGHT}" in str(exc.value)


def test_empty_is_refused() -> None:
    with pytest.raises(media.MediaRejectedError):
        media.validate_preview_image(b"", "image/png")


def test_unreadable_bytes_of_an_accepted_type_are_refused() -> None:
    """Content type is a claim the uploader makes. The header is the fact."""
    with pytest.raises(media.MediaRejectedError) as exc:
        media.validate_preview_image(b"x" * 5000, "image/png")
    assert "could not be read" in str(exc.value)


def test_a_square_image_is_accepted_with_a_warning() -> None:
    """Warned, not refused: it crops rather than breaks, and a re-export for a cosmetic
    reason is a worse outcome than a cropped picture the admin was told about."""
    _, _, _, warning = media.validate_preview_image(_png(800, 800), "image/png")
    assert warning is not None
    assert "800x800" in warning and "cut off" in warning


def test_a_slightly_off_ratio_image_is_not_warned_about() -> None:
    _, _, _, warning = media.validate_preview_image(_png(1200, 675), "image/png")
    assert warning is None
