"""Trace one budget-failure case to see if Phase 1 (new) cycles."""
import sys, os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import networkx as nx
from collections import defaultdict
from triangulation_gen import enumerate_all_triangulations
from level_cycles import compute_levels
from depth_monovariant_check import (
    faces_of_subgraph, canonical_face, edges_of_face,
    apex_levels_for_edge, identify_outer_face, face_depths,
)
from full_resolution_check import (
    isolated_odd_faces, any_lowest_depth_neighbor_flip,
)


tris = enumerate_all_triangulations(9)
G = tris[0]
source_set = {0, 7, 8}
levels = compute_levels(G, source_set)
by_level = defaultdict(list)
for v, lv in levels.items():
    by_level[lv].append(v)
nodes_k = by_level[1]
k = 1

print(f"L_1 = {sorted(nodes_k)}")
print(f"L_1 initial edges: {sorted(G.subgraph(nodes_k).edges())}")

Gc = G.copy()
ip, emb_c = nx.check_planarity(Gc)
history = []
for step in range(15):
    faces = faces_of_subgraph(Gc, emb_c, nodes_k)
    outer = identify_outer_face(faces, Gc, emb_c, levels, k)
    depths = face_depths(faces, outer)
    isolated = isolated_odd_faces(faces, depths, outer)
    iso_summary = [(f, d) for cf, f, d in isolated]
    edges = tuple(sorted(Gc.subgraph(nodes_k).edges()))
    print(f"\nstep {step}: |L_1 edges|={len(edges)} isolated_odd={iso_summary}")
    if not isolated:
        print("  done")
        break
    cf_t, face_t, d_t = max(isolated, key=lambda x: x[2])
    flip = any_lowest_depth_neighbor_flip(
        face_t, Gc, emb_c, levels, k, depths, faces, outer)
    if flip is None:
        print("  no flip")
        break
    u, v, w, x, od = flip
    apex = apex_levels_for_edge(Gc, emb_c, u, v, levels)
    (la, lb), _ = apex
    pair = tuple(sorted([la - k, lb - k]))
    print(f"  flip face {face_t} d={d_t}: ({u},{v})[apex {pair}] -> ({w},{x}), neighbor_depth={od}")
    if edges in [h[0] for h in history]:
        prior = next(h for h in history if h[0] == edges)
        print(f"  *** REPEATING state from step {prior[1]} ***")
        break
    history.append((edges, step))
    Gc.remove_edge(u, v)
    Gc.add_edge(w, x)
    ip, emb_c = nx.check_planarity(Gc)
    if not ip:
        print("  nonplanar"); break
