#!/usr/bin/env python3
import os
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path

# Use temp-backed cache directories so matplotlib/fontconfig/ezdxf can run in
# sandboxed environments where $HOME cache locations are not writable.
_CACHE_ROOT = Path(tempfile.gettempdir()) / "dwg_to_png_cache"
(_CACHE_ROOT / "matplotlib").mkdir(parents=True, exist_ok=True)
(_CACHE_ROOT / "xdg-cache").mkdir(parents=True, exist_ok=True)
os.environ.setdefault("MPLCONFIGDIR", str(_CACHE_ROOT / "matplotlib"))
os.environ.setdefault("XDG_CACHE_HOME", str(_CACHE_ROOT / "xdg-cache"))

from ezdxf.addons import odafc
from ezdxf.addons.odafc import ODAFCNotInstalledError


def pdf_to_png(pdf_path: Path, png_path: Path, dpi: int = 300) -> None:
    pdftoppm = shutil.which("pdftoppm")
    if pdftoppm is None:
        raise RuntimeError(
            "pdftoppm is required for PDF fallback but is not installed."
        )

    png_path.parent.mkdir(parents=True, exist_ok=True)
    output_base = png_path.with_suffix("")
    subprocess.run(
        [
            pdftoppm,
            "-png",
            "-singlefile",
            "-r",
            str(dpi),
            str(pdf_path),
            str(output_base),
        ],
        check=True,
    )


def dwg_to_png(dwg_path: str, png_path: str, dpi: int = 300) -> None:
    from ezdxf.addons.drawing import Frontend, RenderContext
    from ezdxf.addons.drawing.matplotlib import MatplotlibBackend
    import matplotlib.pyplot as plt

    # Read DWG through ODA File Converter
    doc = odafc.readfile(dwg_path, audit=True)

    # Render model space
    fig = plt.figure()
    ax = fig.add_axes([0, 0, 1, 1])
    ax.set_axis_off()

    ctx = RenderContext(doc)
    backend = MatplotlibBackend(ax)
    Frontend(ctx, backend).draw_layout(doc.modelspace(), finalize=True)

    Path(png_path).parent.mkdir(parents=True, exist_ok=True)
    fig.savefig(png_path, dpi=dpi, bbox_inches="tight", pad_inches=0)
    plt.close(fig)


def convert_to_png(input_path: str, png_path: str, dpi: int = 300) -> str:
    source = Path(input_path)
    target = Path(png_path)

    if source.suffix.lower() == ".pdf":
        pdf_to_png(source, target, dpi=dpi)
        return f"Saved from PDF: {target}"

    try:
        dwg_to_png(str(source), str(target), dpi=dpi)
        return f"Saved from DWG: {target}"
    except ODAFCNotInstalledError:
        fallback_pdf = source.with_suffix(".pdf")
        if fallback_pdf.exists():
            pdf_to_png(fallback_pdf, target, dpi=dpi)
            return (
                "ODAFileConverter not found; used sibling PDF fallback: "
                f"{fallback_pdf} -> {target}"
            )
        raise RuntimeError(
            "Could not open DWG because ODAFileConverter is not installed, "
            "and no sibling PDF fallback was found."
        )


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: python dwg_to_png.py input.dwg output.png")
        sys.exit(1)

    message = convert_to_png(sys.argv[1], sys.argv[2])
    print(message)
