"""compile_scad — generate STL from an OpenSCAD script."""

from __future__ import annotations

import asyncio
import shutil
from pathlib import Path

from .config import Settings


async def compile_scad(
    settings: Settings,
    session_id: str,
    source_path: str,
    output_path: str,
) -> dict:
    """Compile a .scad file into a binary STL.

    Returns a dict with:
    - success (bool)
    - output (str) — human-readable summary
    - error (str | None)
    - metadata (dict) — output_path, size_kb
    """
    if not shutil.which(settings.openscad):
        return {
            "success": False,
            "output": "OpenSCAD is not installed on this system.",
            "error": "openscad_not_found",
            "metadata": {},
        }

    try:
        scad_path = settings.resolve_path(session_id, source_path)
        stl_path = settings.resolve_path(session_id, output_path)
    except ValueError as exc:
        return {
            "success": False,
            "output": str(exc),
            "error": "invalid_path",
            "metadata": {},
        }

    if not scad_path.exists():
        return {
            "success": False,
            "output": f"SCAD file not found: {scad_path}",
            "error": "scad_not_found",
            "metadata": {},
        }
    if not scad_path.is_file():
        return {
            "success": False,
            "output": f"Path is not a file: {scad_path}",
            "error": "not_a_file",
            "metadata": {},
        }

    stl_path.parent.mkdir(parents=True, exist_ok=True)

    proc = await asyncio.create_subprocess_exec(
        settings.openscad,
        "--export-format", "binstl",
        "-o", str(stl_path),
        str(scad_path),
        stdout=asyncio.subprocess.PIPE,
        stderr=asyncio.subprocess.PIPE,
    )
    stdout, stderr = await proc.communicate()

    if proc.returncode != 0:
        err = (stderr.decode(errors="replace") or "OpenSCAD exited with an error.").strip()
        return {
            "success": False,
            "output": f"OpenSCAD failed to compile STL:\n{err}",
            "error": "openscad_compile_error",
            "metadata": {},
        }

    if not stl_path.exists():
        return {
            "success": False,
            "output": "OpenSCAD completed but no STL file was produced.",
            "error": "no_output",
            "metadata": {},
        }

    size_kb = stl_path.stat().st_size / 1024
    return {
        "success": True,
        "output": (
            f"Generated: {stl_path.name}\n"
            f"Path: {stl_path}\n"
            f"Size: {size_kb:.1f} KB"
        ),
        "error": None,
        "metadata": {
            "output_path": str(stl_path),
            "size_kb": round(size_kb, 1),
        },
    }
