import pcbnew
from shapely.geometry import MultiPolygon, Polygon

# ---------------------------------------------------------------------------
# KiKit postprocess hook – cleanup.py
#
# 1. Copy all Edge.Cuts content (substrate rings) to Eco1_User as segments,
#    EXCEPT the outermost panel rectangle.
# ---------------------------------------------------------------------------

TOLERANCE_NM = 1_000   # 1 µm


def _mm(nm_val):
    return f"{pcbnew.ToMM(int(nm_val)):.4f} mm"


def _collect_rings(geom):
    """Return all rings as list of (shapely_ring, coord_list)."""
    rings = []
    if isinstance(geom, Polygon):
        rings.append((geom.exterior, list(geom.exterior.coords)))
        for interior in geom.interiors:
            rings.append((interior, list(interior.coords)))
    elif isinstance(geom, MultiPolygon):
        for poly in geom.geoms:
            rings.extend(_collect_rings(poly))
    return rings


def _is_outer_frame(ring_geom, x0, y0, x1, y1, tol=TOLERANCE_NM):
    """True if the ring's bounding box equals the panel bounding box."""
    b = ring_geom.bounds
    return (abs(b[0] - x0) <= tol and abs(b[1] - y0) <= tol and
            abs(b[2] - x1) <= tol and abs(b[3] - y1) <= tol)


def _shapely_to_segments(board, coords, layer, width_mm=0.05):
    pts = list(coords)
    if not pts:
        return 0
    if pts[0] != pts[-1]:
        pts.append(pts[0])
    count = 0
    for i in range(len(pts) - 1):
        seg = pcbnew.PCB_SHAPE(board)
        seg.SetShape(pcbnew.SHAPE_T_SEGMENT)
        seg.SetLayer(layer)
        seg.SetWidth(pcbnew.FromMM(width_mm))
        seg.SetStart(pcbnew.VECTOR2I(int(pts[i][0]),   int(pts[i][1])))
        seg.SetEnd  (pcbnew.VECTOR2I(int(pts[i+1][0]), int(pts[i+1][1])))
        board.Add(seg)
        count += 1
    return count


def kikitPostprocess(panel, arg):
    print("=" * 60)
    print("[cleanup] START")

    board     = panel.board
    substrate = panel.boardSubstrate

    # outer panel bbox
    b = substrate.bounds()
    x0, y0, x1, y1 = int(b[0]), int(b[1]), int(b[2]), int(b[3])
    print(f"[cleanup] Panel bbox: ({_mm(x0)},{_mm(y0)})–({_mm(x1)},{_mm(y1)})")

    # get substrate geometry
    geom = None
    for attr in ("substrates", "substrate", "_substrate", "geometry"):
        if hasattr(substrate, attr):
            geom = getattr(substrate, attr)
            break
    if geom is None:
        print("[cleanup] ERROR: cannot access substrate geometry")
        return

    rings = _collect_rings(geom)
    print(f"[cleanup] Total rings in substrate: {len(rings)}")

    total = 0
    for i, (ring_geom, coords) in enumerate(rings):
        rb = ring_geom.bounds
        if _is_outer_frame(ring_geom, x0, y0, x1, y1):
            print(f"[cleanup]   ring[{i}] pts={len(coords)-1} → OUTER FRAME, skipped")
            continue
        n = _shapely_to_segments(board, coords, pcbnew.Eco1_User)
        total += n
        print(f"[cleanup]   ring[{i}] pts={len(coords)-1}"
              f"  bbox=({_mm(rb[0])},{_mm(rb[1])})–({_mm(rb[2])},{_mm(rb[3])})"
              f" → {n} segments on Eco1_User")

    print(f"[cleanup] Total Eco1_User segments added: {total}")
    print("[cleanup] END")
    print("=" * 60)