"""Dump one cycling case to see what's going on."""
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, level_sources
from depth_monovariant_check import (
    faces_of_subgraph, canonical_face, edges_of_face,
    apex_levels_for_edge, identify_outer_face, face_depths,
    is_both_k_everywhere, tricky_odd_faces, lowest_depth_neighbor_flip,
)


def dump(G, emb, levels, nodes_k, k, source_label):
    print(f"  source: {source_label}, levels:")
    by_level = defaultdict(list)
    for v, lv in levels.items():
        by_level[lv].append(v)
    for lv in sorted(by_level):
        print(f"    L_{lv} = {sorted(by_level[lv])}")
    print(f"  examining L_{k} = {sorted(nodes_k)}")
    L_k = G.subgraph(nodes_k)
    print(f"  L_k edges: {sorted(L_k.edges())}")
    faces = faces_of_subgraph(G, emb, nodes_k)
    print(f"  faces of L_k (inherited embedding):")
    for f in faces:
        print(f"    {f}  len={len(f)}  canon={canonical_face(f)}")
    outer = identify_outer_face(faces, G, emb, levels, k)
    print(f"  outer face: {outer}")
    depths = face_depths(faces, outer)
    print(f"  depths: {depths}")
    print(f"  edge-by-edge apex-level pairs:")
    for f in faces:
        cf = canonical_face(f)
        if cf == outer:
            continue
        if len(f) < 3:
            continue
        print(f"    face {f} (depth={depths.get(cf)}, len={len(f)}):")
        for (u, v) in edges_of_face(f):
            result = apex_levels_for_edge(G, emb, u, v, levels)
            if result is None:
                print(f"      ({u},{v}): no apex")
                continue
            (la, lb), (w, x) = result
            print(f"      ({u},{v}): apexes ({w}@L{la}, {x}@L{lb})")
    tricky = tricky_odd_faces(faces, G, emb, levels, k, depths, outer)
    print(f"  tricky odd faces: {[(f, d) for cf, f, d in tricky]}")
    if tricky:
        cf_t, face_t, d_t = max(tricky, key=lambda x: x[2])
        print(f"  picking deepest tricky face: {face_t} at depth {d_t}")
        flip = lowest_depth_neighbor_flip(face_t, G, emb, levels, k,
                                           depths, faces, outer)
        print(f"  flip choice: {flip}")


# n=10, tri_idx=6, source face (0,4,2), k=1
tris = enumerate_all_triangulations(10)
G = tris[6]
ip, emb = nx.check_planarity(G)
print(f"G edges: {sorted(G.edges())}")
source = {0, 4, 2}
levels = compute_levels(G, source)
by_level = defaultdict(list)
for v, lv in levels.items():
    by_level[lv].append(v)
nodes_k = by_level[1]
dump(G, emb, levels, nodes_k, 1, ('face', (0, 4, 2)))

print("\n--- after one flip ---")
flip_choice = None
faces = faces_of_subgraph(G, emb, nodes_k)
outer = identify_outer_face(faces, G, emb, levels, 1)
depths = face_depths(faces, outer)
tricky = tricky_odd_faces(faces, G, emb, levels, 1, depths, outer)
if tricky:
    cf_t, face_t, d_t = max(tricky, key=lambda x: x[2])
    flip_choice = lowest_depth_neighbor_flip(face_t, G, emb, levels, 1,
                                              depths, faces, outer)
if flip_choice:
    u, v, w, x, _ = flip_choice
    Gp = G.copy()
    Gp.remove_edge(u, v)
    Gp.add_edge(w, x)
    print(f"Flipped ({u},{v}) -> ({w},{x})")
    ip2, emb_p = nx.check_planarity(Gp)
    dump(Gp, emb_p, levels, nodes_k, 1, ('face', (0, 4, 2)))
