"""Handlers for netlist export and connection tracing."""

import json
import os
import subprocess
import tempfile
from pathlib import Path


def handle_generate_netlist(kicad_info: dict, args: dict) -> dict:
    """Export a netlist from a schematic using kicad-cli."""
    if not kicad_info.get("installed"):
        return {
            "success": False,
            "error": "KiCad not installed",
            "_hint": "Report to the user and ask them to install KiCad from https://www.kicad.org/download/, then retry.",
        }

    file_path = args.get("filePath", "")
    if not file_path:
        return {"success": False, "error": "No filePath specified"}

    sch_path = Path(file_path)
    if not sch_path.exists():
        return {"success": False, "error": f"Schematic file not found: {file_path}"}

    cli_exe = kicad_info.get("kicad_cli_exe")
    if not cli_exe or not Path(cli_exe).exists():
        return {"success": False, "error": "kicad-cli not found"}

    fmt = args.get("format", "kicadxml")
    if fmt not in ("kicadxml", "cadstar"):
        return {"success": False, "error": f"Unsupported netlist format: {fmt}"}

    tmp_fd, output_path = tempfile.mkstemp(suffix=".xml" if fmt == "kicadxml" else ".net")
    os.close(tmp_fd)

    try:
        cmd = [
            cli_exe,
            "sch", "export", "netlist",
            "--format", fmt,
            "--output", output_path,
            str(sch_path),
        ]

        result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)

        output_file = Path(output_path)
        if not output_file.exists() or output_file.stat().st_size == 0:
            return {"success": False, "error": f"Netlist export produced no output. stderr: {result.stderr}"}

        netlist_text = output_file.read_text(encoding="utf-8")

        return {
            "success": True,
            "output": f"Netlist exported ({len(netlist_text)} bytes)",
            "data": {"netlist": netlist_text, "format": fmt},
        }

    except subprocess.TimeoutExpired:
        return {"success": False, "error": "Netlist export timed out after 60 seconds"}
    except Exception as e:
        return {"success": False, "error": f"Netlist export failed: {e}"}
    finally:
        try:
            Path(output_path).unlink(missing_ok=True)
        except OSError:
            pass


def handle_trace_connection(kicad_info: dict, args: dict) -> dict:
    """Trace connections for a component pin through the schematic.

    Uses the schematic parser to find which net a component's pin
    belongs to, then lists all other components connected to that net.
    """
    import sys
    sys.path.insert(0, str(Path(__file__).parent.parent))
    from parsers.schematic import parse_schematic

    file_path = args.get("filePath", "")
    reference = args.get("reference", "")

    if not file_path:
        return {"success": False, "error": "No filePath specified"}
    if not reference:
        return {"success": False, "error": "No reference specified"}

    sch_path = Path(file_path)
    if not sch_path.exists():
        return {"success": False, "error": f"Schematic not found: {file_path}"}

    try:
        data = parse_schematic(sch_path)
    except Exception as e:
        return {"success": False, "error": f"Failed to parse schematic: {e}"}

    # Find the target component
    target = None
    for comp in data["components"]:
        if comp["reference"] == reference:
            target = comp
            break

    if not target:
        return {
            "success": False,
            "error": f"Component '{reference}' not found in schematic",
        }

    return {
        "success": True,
        "output": f"Component {reference} ({target['value']}) found",
        "data": {
            "reference": reference,
            "value": target["value"],
            "lib_id": target["lib_id"],
            "footprint": target["footprint"],
            "position": target["position"],
            "properties": target["properties"],
        },
    }


def handle_get_net_connections(kicad_info: dict, args: dict) -> dict:
    """Get all components connected to a named net via PCB data.

    Uses the PCB parser to find all pads on a given net, identifying
    which footprints (components) are connected.
    """
    import sys
    sys.path.insert(0, str(Path(__file__).parent.parent))
    from parsers.pcb import parse_pcb

    file_path = args.get("filePath", "")
    net_name = args.get("netName", "")

    if not file_path:
        return {"success": False, "error": "No filePath specified"}
    if not net_name:
        return {"success": False, "error": "No netName specified"}

    pcb_path = Path(file_path)
    if not pcb_path.exists():
        return {"success": False, "error": f"PCB file not found: {file_path}"}

    try:
        data = parse_pcb(pcb_path)
    except Exception as e:
        return {"success": False, "error": f"Failed to parse PCB: {e}"}

    # Find net number
    net_number = None
    for net in data["nets"]:
        if net["name"] == net_name:
            net_number = net["number"]
            break

    if net_number is None:
        return {"success": False, "error": f"Net '{net_name}' not found"}

    # Find all footprints with pads on this net
    connections = []
    for fp in data["footprints"]:
        for pad in fp.get("pads", []):
            if pad.get("net_number") == net_number:
                connections.append({
                    "reference": fp["reference"],
                    "value": fp["value"],
                    "footprint": fp["footprint"],
                    "pad_number": pad.get("number", ""),
                    "pad_type": pad.get("type", ""),
                })

    return {
        "success": True,
        "output": f"Net '{net_name}': {len(connections)} connection(s)",
        "data": {
            "net_name": net_name,
            "net_number": net_number,
            "connections": connections,
        },
    }
