"""app.image_upload.decode_upload -- pure decoding logic, no HTTP, no DB.
See routers/api_widgets.py's api_widget_static_upload for the endpoint
that calls this, and tests/test_widget_config_and_queue_endpoints.py for
HTTP-level coverage of that endpoint."""

from __future__ import annotations

import io

import pytest
from fastapi import HTTPException
from PIL import Image

from app import image_upload


def _png_bytes(size=(20, 10), color=(255, 0, 0)) -> bytes:
    buf = io.BytesIO()
    Image.new("RGB", size, color).save(buf, format="PNG")
    return buf.getvalue()


def _pdf_bytes(size=(40, 30), color=(0, 255, 0)) -> bytes:
    buf = io.BytesIO()
    Image.new("RGB", size, color).save(buf, format="PDF")
    return buf.getvalue()


def _gif_bytes(size=(15, 15)) -> bytes:
    buf = io.BytesIO()
    Image.new("RGB", size, (0, 0, 255)).save(buf, format="GIF")
    return buf.getvalue()


def test_decodes_a_png():
    img = image_upload.decode_upload(_png_bytes(size=(20, 10)))
    assert img.size == (20, 10)
    assert img.mode == "RGB"


def test_decodes_a_jpeg():
    buf = io.BytesIO()
    Image.new("RGB", (12, 8), (1, 2, 3)).save(buf, format="JPEG")
    img = image_upload.decode_upload(buf.getvalue())
    assert img.size == (12, 8)
    assert img.mode == "RGB"


def test_decodes_a_gif():
    img = image_upload.decode_upload(_gif_bytes(size=(15, 15)))
    assert img.size == (15, 15)
    assert img.mode == "RGB"


def test_decodes_a_pdfs_first_page():
    img = image_upload.decode_upload(_pdf_bytes(size=(40, 30)))
    # Rendered at PDF_RENDER_SCALE (2.0), not the page's native point size.
    assert img.size == (80, 60)
    assert img.mode == "RGB"


def test_rejects_garbage_bytes():
    with pytest.raises(HTTPException) as exc_info:
        image_upload.decode_upload(b"this is not an image or a pdf")
    assert exc_info.value.status_code == 400


def test_rejects_a_pdf_with_no_pages():
    # A syntactically-valid empty PDF (no /Page objects) -- pypdfium2
    # opens it fine but reports zero pages.
    empty_pdf = (
        b"%PDF-1.4\n"
        b"1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n"
        b"2 0 obj<</Type/Pages/Kids[]/Count 0>>endobj\n"
        b"xref\n0 1\n0000000000 65535 f \n"
        b"trailer<</Size 3/Root 1 0 R>>\n"
        b"startxref\n0\n%%EOF"
    )
    with pytest.raises(HTTPException) as exc_info:
        image_upload.decode_upload(empty_pdf)
    assert exc_info.value.status_code == 400


def test_rejects_a_file_over_the_size_limit(monkeypatch):
    monkeypatch.setattr(image_upload, "MAX_UPLOAD_BYTES", 10)
    with pytest.raises(HTTPException) as exc_info:
        image_upload.decode_upload(_png_bytes())
    assert exc_info.value.status_code == 400
