"""Confirm that the C_{28} counterexample to Conjecture 5.5 (face-length-≥-5
form) does NOT yield a counterexample to Conjecture 5.1.

Concretely:
  - The C_{28} fullerene is the dual of the 3rd 16-vertex triangulation
    with minimum degree 5 (in Sage's enumeration order).
  - Conjecture 5.1's hypothesis space is *reduced* duals of such
    triangulations: each reduced dual is obtained from the dual G' by
    deleting one pentagonal face's 5 boundary vertices and stitching in
    a spike vertex v_n + a merged edge (see Definition~\\ref{def:reduced-dual}).
  - For the conjecture-5.5 phenomenon to lift to a conjecture-5.1
    counterexample, we'd need: a reduction of C_{28} (= some choice of
    pentagonal face F_v and rotation index i ∈ {0,…,4}) such that the
    resulting reduced dual admits a chord-apex+Kempe colouring whose
    two distinguished Kempe cycles K_b, K_c both have constant h_φ.

This script enumerates every (F_v, i) reduction of C_{28} (and, for
completeness, every reduction of every other 16-vertex min-deg-5
triangulation's dual), enumerates every chord-apex+Kempe colouring of
each reduced dual, and reports any case where h_φ is constant on
either V(K_b) or V(K_c). The expected result (consistent with the
empirical near-proof in Remark~\\ref{rem:heawood-empirical}) is zero
such cases.

Run with: sage experiments/check_c28_no_chord_apex_kempe_constancy.py
"""
import os
import sys
import time

from sage.all import Graph
from sage.graphs.graph_generators import graphs

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)

from check_conj_final_scaled import (
    apply_reduction,
    proper_3_edge_colorings,
    matches_chord_apex_kempe,
    kempe_cycle_set,
    edge_idx,
)
from check_heawood_on_kempe import (
    dual_of, heawood_numbers, vertices_of_kempe,
)


# Canonical graph6 of the C_{28} fullerene counterexample (from
# experiments/verify_28_vertex_counterexample.py).
C28_GRAPH6 = ('[kG[A?_A?_?_?K?D?@_CO?o?@_??A??@C??O??AG?C????`???a'
              '???W???A_???F')


def is_c28(H):
    return H.canonical_label().graph6_string() == C28_GRAPH6


def check_reduction(H, named, label_for_print):
    """For one reduced dual H + named edges, enumerate every proper
    3-edge-colouring, filter to chord-apex+Kempe colourings, and check
    Heawood constancy on V(K_b), V(K_c), and V(K_b) ∪ V(K_c)."""
    H.is_planar(set_embedding=True)
    edges, colourings = proper_3_edge_colorings(H)
    cak = [c for c in colourings if matches_chord_apex_kempe(edges, c, named)]
    n_total = 0
    n_const_kb = 0
    n_const_kc = 0
    n_const_both = 0
    first_const = None
    merged_idx = edge_idx(edges, named['merged'])
    for col in cak:
        n_total += 1
        try:
            h = heawood_numbers(H, edges, col)
        except RuntimeError:
            continue
        a = col[merged_idx]
        bs = [c for c in range(3) if c != a]
        kc_b = kempe_cycle_set(edges, col, merged_idx, (a, bs[0]))
        kc_c = kempe_cycle_set(edges, col, merged_idx, (a, bs[1]))
        V_b = vertices_of_kempe(edges, kc_b)
        V_c = vertices_of_kempe(edges, kc_c)
        h_b = {h[v] for v in V_b}
        h_c = {h[v] for v in V_c}
        if len(h_b) == 1:
            n_const_kb += 1
        if len(h_c) == 1:
            n_const_kc += 1
        if len(h_b) == 1 and len(h_c) == 1:
            n_const_both += 1
            if first_const is None:
                first_const = (col, V_b, V_c, h)
    return n_total, n_const_kb, n_const_kc, n_const_both, first_const


def iterate_reductions(G, label):
    G.is_planar(set_embedding=True)
    D = dual_of(G)
    is_c = is_c28(D)
    D.is_planar(set_embedding=True)
    pent_faces = [f for f in D.faces() if len(f) == 5]
    print(f"\n[{label}] triangulation order = {G.order()}, "
          f"|V(D)|={D.order()}, |pent faces of D|={len(pent_faces)}"
          f"{' (= C_{28})' if is_c else ''}")
    n_red = 0
    n_total_cak = 0
    n_const_kb = 0
    n_const_kc = 0
    n_const_both = 0
    first = None
    for fi, face in enumerate(pent_faces):
        for i in range(5):
            res = apply_reduction(D, face, i, 9999)
            if res is None:
                continue
            n_red += 1
            t, ckb, ckc, both, fconst = check_reduction(
                res['H'], res['named'], f"{label}/F{fi}/i={i}")
            n_total_cak += t
            n_const_kb += ckb
            n_const_kc += ckc
            n_const_both += both
            if first is None and fconst is not None:
                first = (fi, i, fconst)
    print(f"  reductions tried        : {n_red}")
    print(f"  chord-apex+Kempe colours: {n_total_cak}")
    print(f"  constant on V(K_b)      : {n_const_kb}")
    print(f"  constant on V(K_c)      : {n_const_kc}")
    print(f"  constant on both        : {n_const_both}")
    if first is not None:
        fi, i, (col, V_b, V_c, h) = first
        print(f"  *** COUNTEREXAMPLE *** in pent-face #{fi}, i={i}")
        print(f"      colouring = {col}")
        print(f"      V(K_b) = {V_b}, h on V(K_b) = {{h[v] for v}} = "
              f"{{{', '.join(f'{v}:{h[v]:+d}' for v in V_b)}}}")
        print(f"      V(K_c) = {V_c}")
    return is_c, n_total_cak, n_const_both


def main():
    print("Checking reductions of all 16-vertex min-deg-5 triangulations.\n"
          "The triangulation whose dual is the C_{28} counterexample (to "
          "Conjecture 5.5)\nis the 3rd in Sage's enumeration order.\n")
    start = time.time()
    n_T = 16
    total_T = 0
    total_cak = 0
    total_const = 0
    saw_c28 = False
    try:
        gen = graphs.triangulations(n_T, minimum_degree=5)
    except Exception as ex:
        print(f"cannot enumerate triangulations({n_T}): {ex}")
        return
    for idx, T in enumerate(gen, start=1):
        is_c, t, both = iterate_reductions(T, f"T#{idx}")
        total_T += 1
        total_cak += t
        total_const += both
        if is_c:
            saw_c28 = True
    elapsed = time.time() - start
    print("\n" + "=" * 70)
    print(f"Across {total_T} triangulations on {n_T} vertices "
          f"(C_{{28}} {'YES seen' if saw_c28 else 'NOT seen'}):")
    print(f"  total chord-apex+Kempe colourings tried : {total_cak}")
    print(f"  total with h_φ constant on V(K_b)∧V(K_c): {total_const}")
    print(f"[{elapsed:.1f}s]")
    if total_const == 0:
        print("\n✓ No chord-apex+Kempe colouring of any reduction of any "
              "n_T = 16 triangulation\n  (including the one whose dual is "
              "the C_{28} counterexample) has h_φ\n  simultaneously "
              "constant on V(K_b) and V(K_c).")
    else:
        print(f"\n✗ {total_const} colouring(s) with full constancy found.")


if __name__ == '__main__':
    main()
