from io import BytesIO
from unittest.mock import patch
import pytest

import numpy as np
import nibabel as nib
from PIL import Image, ImageFont

from coord2region.utils.image_utils import add_watermark, generate_mni152_image


@patch("coord2region.utils.image_utils.plot_stat_map")
@patch("coord2region.utils.image_utils.load_mni152_template")
def test_generate_mni152_image_returns_png_bytes(mock_load, mock_plot):
    """Generated bytes from Nilearn helper open as a PNG."""
    template = nib.Nifti1Image(np.zeros((5, 5, 5)), np.eye(4))
    mock_load.return_value = template

    class DummyDisplay:
        def savefig(self, buffer, format="png", bbox_inches="tight"):
            Image.new("RGB", (10, 10), color="white").save(buffer, format="PNG")

        def close(self):
            pass

    mock_plot.return_value = DummyDisplay()

    img_bytes = generate_mni152_image([0, 0, 0])
    img = Image.open(BytesIO(img_bytes))
    assert img.format == "PNG"


def test_add_watermark_overlays_text():
    """Watermark text alters pixels near the bottom of the image."""
    base = Image.new("RGB", (100, 50), color="black")
    buf = BytesIO()
    base.save(buf, format="PNG")
    watermarked_bytes = add_watermark(buf.getvalue(), text="WM")

    watermarked = Image.open(BytesIO(watermarked_bytes))
    arr = np.array(watermarked)
    bottom = arr[int(arr.shape[0] * 0.8) :, :, :]
    assert np.any(bottom > 0)

@pytest.mark.unit
def test_add_watermark_font_fallback():
    base = Image.new("RGB", (100, 50), color="black")
    buf = BytesIO(); base.save(buf, format="PNG")
    orig_font = ImageFont.load_default()
    with patch("coord2region.utils.image_utils.ImageFont.truetype", side_effect=[OSError(), orig_font]) as mock_tt:
        watermarked_bytes = add_watermark(buf.getvalue(), text="WM")
    arr = np.array(Image.open(BytesIO(watermarked_bytes)))
    assert np.any(arr[int(arr.shape[0]*0.8):] > 0)
    assert mock_tt.call_count >= 1
