#!/usr/bin/env python3
"""Convert SVG to PNG for Canvas-safe image embedding.

Canvas strips raw SVGs from page HTML (XSS prevention), so this script
converts SVG source files to high-resolution PNGs for upload as images.

Optional dependency:
    pip install -r scripts/requirements-optional.txt
    macOS: brew install cairo pkg-config

Usage:
    python convert_svg.py input.svg --output output.png --scale 2
    python convert_svg.py input.svg  # writes input.png next to input.svg
"""

import os
import sys
import argparse
import platform

# On macOS, help cairocffi find the Homebrew-installed cairo library.
# System Python strips DYLD_LIBRARY_PATH, so we set the fallback path
# before importing cairosvg (which imports cairocffi).
if platform.system() == "Darwin":
    homebrew_lib = "/opt/homebrew/lib"
    if os.path.isdir(homebrew_lib):
        os.environ.setdefault("DYLD_FALLBACK_LIBRARY_PATH", homebrew_lib)

CAIROSVG_AVAILABLE = False
_cairosvg_import_error = None

try:
    import cairosvg
    CAIROSVG_AVAILABLE = True
except (ImportError, OSError) as e:
    cairosvg = None
    _cairosvg_import_error = e


def _require_cairosvg():
    """Raise a friendly error when optional SVG conversion deps are missing."""
    if CAIROSVG_AVAILABLE:
        return

    message_lines = [
        "cairosvg is required for SVG to PNG conversion.",
        "Install the optional visual-builder dependency with:",
        "  pip install -r scripts/requirements-optional.txt",
    ]
    if platform.system() == "Darwin":
        message_lines.extend(
            [
                "On macOS, install the cairo system library first:",
                "  brew install cairo pkg-config",
                "Or run the helper:",
                "  python3 scripts/ensure_cairosvg.py",
            ]
        )
    if _cairosvg_import_error is not None:
        message_lines.append(f"Original import error: {_cairosvg_import_error}")
    raise RuntimeError("\n".join(message_lines))


def svg_to_png(svg_input, output_path=None, scale=2):
    """Convert SVG to PNG.

    Args:
        svg_input: SVG string (str) or file path (str ending in .svg)
        output_path: Where to write the PNG. If None, returns PNG bytes.
        scale: Render scale factor (2 = retina/2x resolution)

    Returns:
        If output_path is provided: the output path (str)
        If output_path is None: PNG bytes
    """
    _require_cairosvg()

    # Determine if input is a file path or SVG string
    if isinstance(svg_input, str) and svg_input.strip().endswith('.svg') and os.path.isfile(svg_input):
        # File path
        if output_path:
            cairosvg.svg2png(url=svg_input, write_to=output_path, scale=scale)
            return output_path
        else:
            return cairosvg.svg2png(url=svg_input, scale=scale)
    else:
        # SVG string
        svg_bytes = svg_input.encode('utf-8') if isinstance(svg_input, str) else svg_input
        if output_path:
            cairosvg.svg2png(bytestring=svg_bytes, write_to=output_path, scale=scale)
            return output_path
        else:
            return cairosvg.svg2png(bytestring=svg_bytes, scale=scale)


def svg_file_to_png(svg_path, output_path=None, scale=2):
    """Convert an SVG file to PNG file.

    Args:
        svg_path: Path to the SVG file
        output_path: Path for the PNG output. If None, uses same name with .png extension.
        scale: Render scale factor (2 = retina/2x resolution)

    Returns:
        Path to the output PNG file
    """
    _require_cairosvg()

    if not os.path.isfile(svg_path):
        raise FileNotFoundError(f"SVG file not found: {svg_path}")

    if output_path is None:
        output_path = os.path.splitext(svg_path)[0] + '.png'

    cairosvg.svg2png(url=svg_path, write_to=output_path, scale=scale)
    size_kb = os.path.getsize(output_path) / 1024
    print(f"  Converted: {os.path.basename(svg_path)} → {os.path.basename(output_path)} ({size_kb:.0f} KB)")
    return output_path


def main():
    parser = argparse.ArgumentParser(
        description="Convert SVG to PNG for Canvas image embedding."
    )
    parser.add_argument("input", help="Path to SVG file")
    parser.add_argument("--output", "-o", default=None, help="Output PNG path (default: same name with .png)")
    parser.add_argument("--scale", "-s", type=float, default=2, help="Scale factor (default: 2 for retina)")
    args = parser.parse_args()

    try:
        _require_cairosvg()
    except RuntimeError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        sys.exit(1)

    output = svg_file_to_png(args.input, args.output, args.scale)
    print(f"  Output: {output}")


if __name__ == "__main__":
    main()
