"""kicad_export_molecule — one-shot "molecule export pack" for a KiCad board.

The Adom molecule pipeline (container side) is:
    STEP  →  step2glb (color-preserving GLB)  →  adom-molecule create
             --glb ... --pcb ... --sch ... --pro ...   →  Hydrogen molecule
             (+ optionally a wiki.adom.inc component page)

adom-molecule REQUIRES four files for a KiCad source: .glb, .kicad_pcb,
.kicad_sch and .kicad_pro. The GLB comes from the STEP via step2glb *in the
container*; everything else lives here on the Windows host next to the board.

This verb does the entire desktop-side half in one call:
  1. export the board's STEP (geometry + component models),
  2. render silkscreen top/bottom PNGs when `kicad-cli pcb render` exists
     (KiCad 9+; optional extras for the molecule page),
  3. locate the sibling .kicad_sch / .kicad_pro by the board's stem,
  4. return a single manifest of host paths + the exact container commands
     to finish the pipeline.

The caller then pull_file's the manifest paths and runs the printed commands.
No container tools are shelled from here — the bridge stays desktop-only.
"""

import os
import subprocess
from pathlib import Path

from .export import _run_pcb_export


def handle_export_molecule(kicad_info: dict, args: dict) -> dict:
    if not kicad_info.get("installed"):
        return {
            "success": False,
            "error": "KiCad not installed",
            "_hint": "Install KiCad first (kicad_upgrade), then retry.",
        }

    file_path = args.get("filePath", "")
    if not file_path:
        return {"success": False, "error": "No filePath specified (the .kicad_pcb)"}
    pcb_path = Path(file_path)
    if not pcb_path.exists():
        return {
            "success": False,
            "error": f"PCB file not found: {file_path}",
            "_hint": "Path must exist on the Windows host. send_files it first if it lives in Docker.",
        }

    out_dir = args.get("outputDir") or str(pcb_path.parent / "molecule_output")
    os.makedirs(out_dir, exist_ok=True)

    result: dict = {"success": True, "data": {}}
    missing: list = []

    # 1) STEP (reuse the standard export; honors its own error paths)
    step_res = _run_pcb_export(
        kicad_info,
        {"filePath": str(pcb_path), "outputDir": out_dir},
        "step",
        "STEP",
    )
    if not step_res.get("success"):
        return {
            "success": False,
            "error": f"STEP export failed: {step_res.get('error')}",
            "_hint": "The STEP is mandatory for the molecule GLB — fix this first.",
        }
    step_path = step_res["data"]["output_path"]
    result["data"]["step"] = step_path

    # 2) Silkscreen renders (optional; needs `kicad-cli pcb render`, KiCad 9+)
    cli_exe = kicad_info.get("kicad_cli_exe")
    silk = {}
    for side in ("top", "bottom"):
        png = os.path.join(out_dir, f"{pcb_path.stem}-silk-{side}.png")
        try:
            r = subprocess.run(
                [cli_exe, "pcb", "render", "--side", side,
                 "--background", "transparent", "--output", png, str(pcb_path)],
                capture_output=True, text=True, timeout=180,
            )
            if r.returncode == 0 and Path(png).exists():
                silk[side] = png
            else:
                missing.append(f"silk-{side} (kicad-cli pcb render rc={r.returncode})")
        except Exception as e:  # old KiCad without `pcb render`, timeout, …
            missing.append(f"silk-{side} ({e})")
    result["data"]["silkscreen"] = silk

    # 3) Sibling project files by stem — adom-molecule needs sch + pro
    sch = pcb_path.with_suffix(".kicad_sch")
    pro = pcb_path.with_suffix(".kicad_pro")
    result["data"]["pcb"] = str(pcb_path)
    result["data"]["sch"] = str(sch) if sch.exists() else None
    result["data"]["pro"] = str(pro) if pro.exists() else None
    for label, p in (("sch", sch), ("pro", pro)):
        if not p.exists():
            missing.append(f"{label} ({p.name} not next to the board — adom-molecule requires it)")

    # 4) The exact container-side finish
    name = args.get("name") or pcb_path.stem
    result["data"]["nextSteps"] = [
        f"pull_file the paths in data (step/pcb/sch/pro/silkscreen) to the container",
        f"step2glb convert <step> --out /tmp/{pcb_path.stem}.glb",
        (
            f"adom-molecule create --source kicad --name \"{name}\" --owner <owner> "
            f"--description \"<desc>\" --glb /tmp/{pcb_path.stem}.glb "
            f"--pcb <pcb> --sch <sch> --pro <pro>"
            + (" --silk-top <silk-top> --silk-bottom <silk-bottom>" if silk else "")
        ),
    ]
    if missing:
        result["data"]["missing"] = missing
    result["output"] = (
        f"Molecule export pack in {out_dir}: STEP"
        + (f" + silk({','.join(silk)})" if silk else "")
        + (f"; MISSING: {'; '.join(missing)}" if missing else " — complete")
    )
    result["_hint"] = (
        "Desktop half of the molecule pipeline is done. pull_file everything in "
        "data, then run data.nextSteps in the container (step2glb → adom-molecule "
        "create). adom-molecule REQUIRES glb+pcb+sch+pro; silk PNGs are optional "
        "polish for the molecule page."
    )
    return result