"""Tests for Telegram media handling."""

import io

import pytest
from PIL import Image


def test_detect_mime_from_jpeg():
    """Test MIME detection for JPEG images."""
    from nanobot.channels.telegram_media import detect_mime

    # Create minimal JPEG bytes (FF D8 FF = JPEG magic bytes)
    jpeg_bytes = b'\xff\xd8\xff\xe0\x00\x10JFIF'

    mime = detect_mime("test.jpg", jpeg_bytes)
    assert mime == "image/jpeg"


def test_detect_mime_from_png():
    """Test MIME detection for PNG images."""
    from nanobot.channels.telegram_media import detect_mime

    # PNG magic bytes
    png_bytes = b'\x89PNG\r\n\x1a\n'

    mime = detect_mime("test.png", png_bytes)
    assert mime == "image/png"


def test_detect_mime_from_extension_fallback():
    """Test MIME detection falls back to extension when no content provided."""
    from nanobot.channels.telegram_media import detect_mime

    mime = detect_mime("video.mp4", None)
    assert mime == "video/mp4"


def test_detect_mime_unknown():
    """Test MIME detection returns generic type for unknown files."""
    from nanobot.channels.telegram_media import detect_mime

    mime = detect_mime("unknown.xyz", None)
    assert mime == "application/octet-stream"


def test_detect_mime_magic_fallback_on_octet_stream():
    """Test that extension is preferred when magic returns generic type."""
    from nanobot.channels.telegram_media import detect_mime

    # Generic binary content that magic might identify as octet-stream
    generic_bytes = b'\x00\x01\x02\x03'

    # But extension clearly indicates it's an image
    mime = detect_mime("image.png", generic_bytes)

    # Should use extension (png) not magic's generic result
    # Note: This tests the logic at line 36 - avoiding generic types
    assert mime in ("image/png", "application/octet-stream")


def test_detect_mime_malformed_content():
    """Test fallback when magic detection fails with malformed content."""
    from nanobot.channels.telegram_media import detect_mime

    # Malformed content that might cause magic to raise an exception
    malformed = b'\xff' * 10

    # Should fallback to extension detection, not crash
    mime = detect_mime("test.mp4", malformed)
    assert mime == "video/mp4"


def test_classify_media_image():
    """Test classification of image MIME types."""
    from nanobot.channels.telegram_media import MediaKind, classify_media

    assert classify_media("image/jpeg") == MediaKind.IMAGE
    assert classify_media("image/png") == MediaKind.IMAGE
    assert classify_media("image/webp") == MediaKind.IMAGE


def test_classify_media_video():
    """Test classification of video MIME types."""
    from nanobot.channels.telegram_media import MediaKind, classify_media

    assert classify_media("video/mp4") == MediaKind.VIDEO
    assert classify_media("video/quicktime") == MediaKind.VIDEO


def test_classify_media_audio():
    """Test classification of audio MIME types."""
    from nanobot.channels.telegram_media import MediaKind, classify_media

    assert classify_media("audio/mpeg") == MediaKind.AUDIO
    assert classify_media("audio/ogg") == MediaKind.AUDIO


def test_classify_media_document():
    """Test classification of document MIME types."""
    from nanobot.channels.telegram_media import MediaKind, classify_media

    assert classify_media("application/pdf") == MediaKind.DOCUMENT
    assert classify_media("text/plain") == MediaKind.DOCUMENT
    assert classify_media("application/octet-stream") == MediaKind.DOCUMENT


def test_is_heic_format():
    """Test HEIC format detection."""
    from nanobot.channels.telegram_media import is_heic_format

    assert is_heic_format("photo.heic") is True
    assert is_heic_format("photo.HEIC") is True
    assert is_heic_format("photo.heif") is True
    assert is_heic_format("photo.jpg") is False


def test_optimize_image_jpeg_quality(tmp_path):
    """Test JPEG optimization reduces size with quality ladder."""
    from nanobot.channels.telegram_media import optimize_image

    # Create a large test image (3000x3000 RGB)
    img = Image.new("RGB", (3000, 3000), color="red")
    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=95)
    original_bytes = buf.getvalue()
    original_size = len(original_bytes)

    # Write to temp file
    temp_file = tmp_path / "test.jpg"
    temp_file.write_bytes(original_bytes)

    # Optimize to 1MB max
    optimized = optimize_image(str(temp_file), max_bytes=1_000_000)

    # Should be smaller than original
    assert len(optimized) < original_size
    # Should be under limit
    assert len(optimized) <= 1_000_000
    # Should still be valid JPEG
    assert optimized.startswith(b'\xff\xd8\xff')


def test_optimize_image_png_preserve_alpha(tmp_path):
    """Test PNG with alpha channel is preserved."""
    from nanobot.channels.telegram_media import optimize_image

    # Create PNG with alpha channel
    img = Image.new("RGBA", (1000, 1000), color=(255, 0, 0, 128))
    buf = io.BytesIO()
    img.save(buf, format="PNG")
    original_bytes = buf.getvalue()

    # Write to temp file
    temp_file = tmp_path / "test.png"
    temp_file.write_bytes(original_bytes)

    optimized = optimize_image(str(temp_file), max_bytes=5_000_000)

    # Should still be PNG (PNG magic bytes)
    assert optimized.startswith(b'\x89PNG')

    # Load and verify alpha channel preserved
    img_opt = Image.open(io.BytesIO(optimized))
    assert img_opt.mode == "RGBA"


@pytest.mark.asyncio
async def test_fetch_media_success():
    """Test fetching media from remote URL."""
    from unittest.mock import AsyncMock, MagicMock, patch

    from nanobot.channels.telegram_media import fetch_media

    # Mock httpx response
    mock_content = b"fake image data"
    mock_response = MagicMock()
    mock_response.content = mock_content
    mock_response.headers = {"content-type": "image/jpeg"}
    mock_response.raise_for_status = MagicMock()

    with patch("httpx.AsyncClient") as mock_client:
        mock_client.return_value.__aenter__.return_value.get = AsyncMock(return_value=mock_response)

        content, mime = await fetch_media("https://example.com/image.jpg", max_bytes=10_000_000)

        assert content == mock_content
        assert mime == "image/jpeg"


@pytest.mark.asyncio
async def test_fetch_media_timeout():
    """Test fetch media handles timeout."""
    from unittest.mock import AsyncMock, patch

    import httpx

    from nanobot.channels.telegram_media import fetch_media

    with patch("httpx.AsyncClient") as mock_client:
        mock_client.return_value.__aenter__.return_value.get = AsyncMock(side_effect=httpx.TimeoutException("timeout"))

        with pytest.raises(ValueError, match="timeout"):
            await fetch_media("https://example.com/image.jpg", max_bytes=10_000_000)


def test_group_media_all_images():
    """Test grouping all images into album."""
    from nanobot.channels.telegram_media import MediaKind, group_media_for_album

    media_items = [
        ("image1.jpg", MediaKind.IMAGE),
        ("image2.png", MediaKind.IMAGE),
        ("image3.jpeg", MediaKind.IMAGE),
    ]

    result = group_media_for_album(media_items)

    assert result["album"] == ["image1.jpg", "image2.png", "image3.jpeg"]
    assert result["separate"] == []


def test_group_media_all_videos():
    """Test grouping all videos into album."""
    from nanobot.channels.telegram_media import MediaKind, group_media_for_album

    media_items = [
        ("video1.mp4", MediaKind.VIDEO),
        ("video2.mov", MediaKind.VIDEO),
    ]

    result = group_media_for_album(media_items)

    assert result["album"] == ["video1.mp4", "video2.mov"]
    assert result["separate"] == []


def test_group_media_mixed_types():
    """Test mixed media types sent separately."""
    from nanobot.channels.telegram_media import MediaKind, group_media_for_album

    media_items = [
        ("image.jpg", MediaKind.IMAGE),
        ("video.mp4", MediaKind.VIDEO),
        ("audio.mp3", MediaKind.AUDIO),
    ]

    result = group_media_for_album(media_items)

    assert result["album"] == []
    assert result["separate"] == ["image.jpg", "video.mp4", "audio.mp3"]


def test_group_media_single_item():
    """Test single media item sent separately (not as album)."""
    from nanobot.channels.telegram_media import MediaKind, group_media_for_album

    media_items = [("image.jpg", MediaKind.IMAGE)]

    result = group_media_for_album(media_items)

    assert result["album"] == []
    assert result["separate"] == ["image.jpg"]
