"""Compare original Phase 1 (tricky-everywhere only) and new Phase 1
(isolated, prefer cross-level) on the same case."""
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,
    is_both_k_everywhere, tricky_odd_faces, lowest_depth_neighbor_flip,
)
from full_resolution_check import (
    isolated_odd_faces, any_lowest_depth_neighbor_flip,
)


def show_apex(face, G, emb, levels, k):
    pairs = []
    for (u, v) in edges_of_face(face):
        r = apex_levels_for_edge(G, emb, u, v, levels)
        if r is None:
            pairs.append(None)
        else:
            (la, lb), _ = r
            pairs.append(tuple(sorted([la - k, lb - k])))
    return pairs


def trace(label, G_initial, levels, nodes_k, k, target_fn, flip_fn,
          max_steps=15):
    print(f"\n=== {label} ===")
    Gc = G_initial.copy()
    ip, emb_c = nx.check_planarity(Gc)
    states = []
    for step in range(max_steps):
        faces = faces_of_subgraph(Gc, emb_c, nodes_k)
        outer = identify_outer_face(faces, Gc, emb_c, levels, k)
        depths = face_depths(faces, outer)
        targets = target_fn(faces, Gc, emb_c, levels, k, depths, outer)
        targets_summary = []
        for cf, f, d in targets:
            pairs = show_apex(f, Gc, emb_c, levels, k)
            te = all(p == (0, 0) for p in pairs)
            targets_summary.append((f, d, "TE" if te else "mixed"))
        cur_state = tuple(sorted(Gc.subgraph(nodes_k).edges()))
        repeating = cur_state in states
        states.append(cur_state)
        print(f"step {step}: targets={targets_summary} repeat={repeating}")
        if repeating:
            print("  CYCLE")
            return
        if not targets:
            print("  done")
            return
        cf_t, face_t, d_t = max(targets, key=lambda x: x[2])
        flip = flip_fn(face_t, Gc, emb_c, levels, k, depths, faces, outer)
        if flip is None:
            print("  no flip")
            return
        u, v, w, x, _ = flip
        Gc.remove_edge(u, v)
        Gc.add_edge(w, x)
        ip, emb_c = nx.check_planarity(Gc)


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)}, k={k}")
print(f"Initial L_1 edges: {sorted(G.subgraph(nodes_k).edges())}")

# Original Phase 1: tricky-everywhere target
def orig_target(faces, G, emb, levels, k, depths, outer):
    return tricky_odd_faces(faces, G, emb, levels, k, depths, outer)


# Original flip: lowest_depth_neighbor_flip (filters to (k,k) only)
def orig_flip(face, G, emb, levels, k, depths, faces, outer):
    return lowest_depth_neighbor_flip(face, G, emb, levels, k, depths, faces,
                                       outer)

trace("ORIGINAL Phase 1 (tricky-everywhere only, (k,k) flips)",
      G, levels, nodes_k, k, orig_target, orig_flip)


def new_target(faces, G, emb, levels, k, depths, outer):
    return isolated_odd_faces(faces, depths, outer)


def new_flip(face, G, emb, levels, k, depths, faces, outer):
    return any_lowest_depth_neighbor_flip(face, G, emb, levels, k, depths,
                                            faces, outer)

trace("NEW Phase 1 (isolated, prefer cross-level)",
      G, levels, nodes_k, k, new_target, new_flip)
