import os
import pytest
from io import BytesIO
from unittest.mock import patch, MagicMock
from PIL import Image as PILImage
from src.images import process_image, _resize_to_fit


def _make_test_image(width, height, fmt="JPEG"):
    img = PILImage.new("RGB", (width, height), color="red")
    buf = BytesIO()
    img.save(buf, format=fmt)
    buf.seek(0)
    return buf.read()


def test_resize_landscape_downscale():
    img = PILImage.new("RGB", (1600, 900))
    result = _resize_to_fit(img)
    assert result.width <= 800
    assert result.height <= 480
    assert result.width / result.height == pytest.approx(1600 / 900, rel=0.02)


def test_resize_portrait_downscale():
    img = PILImage.new("RGB", (600, 1200))
    result = _resize_to_fit(img)
    assert result.width <= 480
    assert result.height <= 800
    assert result.width / result.height == pytest.approx(600 / 1200, rel=0.02)


def test_resize_small_image_upscales():
    img = PILImage.new("RGB", (200, 100))
    result = _resize_to_fit(img)
    assert result.width > 200
    assert result.width <= 800
    assert result.height <= 480


def test_resize_already_fits():
    img = PILImage.new("RGB", (800, 480))
    result = _resize_to_fit(img)
    assert result.size == (800, 480)


def test_process_image_downloads_and_saves(tmp_path):
    image_bytes = _make_test_image(1024, 768)

    mock_response = MagicMock()
    mock_response.content = image_bytes
    mock_response.raise_for_status = MagicMock()

    with patch("src.images.requests.get", return_value=mock_response):
        path, w, h = process_image(
            "https://example.com/photo.jpg", str(tmp_path)
        )

    assert os.path.exists(path)
    assert path.endswith(".jpg")
    assert w <= 800
    assert h <= 480

    saved = PILImage.open(path)
    assert saved.format == "JPEG"


def test_process_image_dedup(tmp_path):
    image_bytes = _make_test_image(500, 300)

    mock_response = MagicMock()
    mock_response.content = image_bytes
    mock_response.raise_for_status = MagicMock()

    with patch("src.images.requests.get", return_value=mock_response) as mock_get:
        path1, _, _ = process_image("https://example.com/same.jpg", str(tmp_path))
        path2, _, _ = process_image("https://example.com/same.jpg", str(tmp_path))

    assert path1 == path2
    assert mock_get.call_count == 1
