"""
SVG to half-block terminal art rasterization.

Pipeline: SVG -> cairosvg -> PIL -> greyscale threshold -> half-block encode.
Follows the same pixel-pair approach as engine/render.py for OTF fonts.
"""

from __future__ import annotations

import os
import sys
from io import BytesIO

# cairocffi (used by cairosvg) calls dlopen() to find the Cairo C library.
# On macOS with Homebrew, Cairo lives in /opt/homebrew/lib (Apple Silicon) or
# /usr/local/lib (Intel), which are not in dyld's default search path.
# Setting DYLD_LIBRARY_PATH before the import directs dlopen() to those paths.
if sys.platform == "darwin" and not os.environ.get("DYLD_LIBRARY_PATH"):
    for _brew_lib in ("/opt/homebrew/lib", "/usr/local/lib"):
        if os.path.exists(os.path.join(_brew_lib, "libcairo.2.dylib")):
            os.environ["DYLD_LIBRARY_PATH"] = _brew_lib
            break

import cairosvg
from PIL import Image

_cache: dict[tuple[str, int, int], list[str]] = {}


def rasterize_svg(svg_path: str, width: int, height: int) -> list[str]:
    """Convert SVG file to list of half-block terminal rows (uncolored).

    Args:
        svg_path: Path to SVG file.
        width: Target terminal width in columns.
        height: Target terminal height in rows.

    Returns:
        List of strings, one per terminal row, containing block characters.
    """
    cache_key = (svg_path, width, height)
    if cache_key in _cache:
        return _cache[cache_key]

    # SVG -> PNG in memory
    png_bytes = cairosvg.svg2png(
        url=svg_path,
        output_width=width,
        output_height=height * 2,  # 2 pixel rows per terminal row
    )

    # PNG -> greyscale PIL image
    # Composite RGBA onto white background so transparent areas become white (255)
    # and drawn pixels retain their luminance values.
    img_rgba = Image.open(BytesIO(png_bytes)).convert("RGBA")
    img_rgba = img_rgba.resize((width, height * 2), Image.Resampling.LANCZOS)
    background = Image.new("RGBA", img_rgba.size, (255, 255, 255, 255))
    background.paste(img_rgba, mask=img_rgba.split()[3])
    img = background.convert("L")

    data = img.tobytes()
    pix_w = width
    pix_h = height * 2
    # White (255) = empty space, dark (< threshold) = filled pixel
    threshold = 128

    # Half-block encode: walk pixel pairs
    rows: list[str] = []
    for y in range(0, pix_h, 2):
        row: list[str] = []
        for x in range(pix_w):
            top = data[y * pix_w + x] < threshold
            bot = data[(y + 1) * pix_w + x] < threshold if y + 1 < pix_h else False
            if top and bot:
                row.append("█")
            elif top:
                row.append("▀")
            elif bot:
                row.append("▄")
            else:
                row.append(" ")
        rows.append("".join(row))

    _cache[cache_key] = rows
    return rows


def clear_cache() -> None:
    """Clear the rasterization cache (e.g., on terminal resize)."""
    _cache.clear()
