#  Copyright © 2025 Dr.-Ing. Paul Wilhelm <paul@wilhelm.dev>
#  This file is part of Archive Agent. See LICENSE for details.

from logging import Logger
from typing import Optional

import io
import base64
from PIL import Image


def image_resize_safe(
    image: Image.Image,
    logger: Logger,
    verbose: bool,
    # OpenAI highest resolution specs
    max_w: int = 768,
    max_h: int = 2000,
    max_bytes: int = 20 * 1024 * 1024,
) -> Optional[Image.Image]:
    """
    Resize image to safe dimensions or data size, if required.
    :param image: Image data.
    :param logger: Logger.
    :param verbose: Enable verbose output.
    :param max_w: Maximum width.
    :param max_h: Maximum height.
    :param max_bytes: Maximum data size (in bytes).
    :return: Possibly resized image (JPEG) if successful, None otherwise.
    """
    image_copy = image.copy()
    image_copy.thumbnail((max_w, max_h), Image.Resampling.LANCZOS)

    if image_copy.width != image.width or image_copy.height != image.height:
        if verbose:
            logger.info(
                f"Resized image "
                f"from ({image.width} × {image.height} px) "
                f"to ({image_copy.width} × {image_copy.height} px)"
            )
    else:
        if verbose:
            logger.info(f"Image size: ({image_copy.width} × {image_copy.height} px)")

    for quality in range(100, 0, -5):
        image_bytes = io.BytesIO()
        image_copy.save(image_bytes, format="JPEG", quality=quality)
        if image_bytes.tell() <= max_bytes:
            image_bytes.seek(0)
            return Image.open(image_bytes)
        logger.warning(f"Reducing image quality to ({quality} %)")

    logger.critical(f"⚠️ Failed to resize image: Too huge")
    return None


def image_to_base64(image: Image.Image) -> str:
    """
    Convert image data to Base64 as a UTF-8 encoded string.
    :param image: Image data.
    :return: Image as UTF-8 encoded Base64 string.
    """
    img_bytes = io.BytesIO()
    image.save(img_bytes, format="JPEG")
    # noinspection PyTypeChecker
    return base64.b64encode(img_bytes.getvalue()).decode("utf-8")
