#!/usr/bin/env python3
"""Compare a KiCad schematic XML netlist and PCB IPC-D-356 records by (reference,pin)."""
from pathlib import Path
import argparse, json, xml.etree.ElementTree as ET
p=argparse.ArgumentParser(); p.add_argument("schematic_netlist_xml"); p.add_argument("board_ipc356"); p.add_argument("--output",default="pad_net_comparison.json"); a=p.parse_args()
r=ET.parse(a.schematic_netlist_xml).getroot(); s={}
for n in r.findall(".//nets/net"):
 net=n.get("name","").lstrip("/")
 for node in n.findall("node"): s[(node.get("ref"),node.get("pin"))]=net
b={}; vias=0
for line in Path(a.board_ipc356).read_text().splitlines():
 parts=line.split()
 if len(parts)>=3 and (parts[0].startswith("317") or parts[0].startswith("327")):
  net=parts[0][3:]; ref=parts[1]; pin=parts[2].lstrip("-")
  if ref=="VIA": vias+=1; continue
  b[(ref,pin)]="unconnected" if net=="N/C" else net
ms=sorted(set(s)-set(b)); mb=sorted(set(b)-set(s)); common=set(s)&set(b); mm=[]; connected=nc=0
for k in sorted(common):
 x,y=s[k],b[k]
 if x.startswith("unconnected-") and y=="unconnected": nc+=1
 elif x.lstrip("/")==y: connected+=1
 else: mm.append({"ref":k[0],"pin":k[1],"schematic_net":x,"board_net":y})
out={"schematic_net_pin_rows":len(s),"board_component_pin_rows":len(b),"board_via_records_excluded":vias,"matched_ref_pin_pairs":len(common),"connected_pin_pairs_matching_after_root_slash_normalization":connected,"schematic_unconnected_and_board_NC_pairs":nc,"missing_from_schematic":[{"ref":x,"pin":y} for x,y in ms],"missing_from_board":[{"ref":x,"pin":y} for x,y in mb],"net_mismatches":mm,"result":"PASS_CUSTOM_PIN_NET_MAP" if not ms and not mb and not mm and connected+nc==len(common) else "FAIL"}
Path(a.output).write_text(json.dumps(out,ensure_ascii=False,indent=2)+chr(10)); print(json.dumps(out,ensure_ascii=False,indent=2))
