"""
Skill: Core Mathematics
========================
Natural numbers, lists, and binary trees.
Ships with the engine as the foundation for other skills.
"""

from nexus_gate_pkg.engine.skills import Skill, TheoremDef, register_skill
from nexus_gate_pkg.engine.terms import Var, Const, App, Equation
from nexus_gate_pkg.corpus.domain import (
    DEFINITIONS as NAT_LIST_DEFS,
    Z, S, Nil, Cons, add, append, rev, length, map_f,
)
from nexus_gate_pkg.corpus.trees import (
    TREE_DEFINITIONS,
    Leaf, Node, mirror, tree_size, flatten,
)


def _thm(name, desc, lhs, rhs, ctx=None, diff="medium", tags=None):
    return TheoremDef(name, desc, lhs, rhs, context=ctx or [], difficulty=diff, tags=tags or [])


core_math = Skill(
    id="core_math",
    name="Core Mathematics",
    description="Natural numbers, lists, and binary trees — the foundation",
    version="2.0.0",
    author="Kolmogorov Engine",
    definitions=NAT_LIST_DEFS + TREE_DEFINITIONS,
    theorems=[
        # Nat — trivial
        _thm("add_zero_left", "Adding zero on the left does nothing",
             add(Z(), Var("n")), Var("n"), diff="trivial", tags=["nat","add"]),
        _thm("add_one_left", "Adding one on the left is successor",
             add(S(Z()), Var("n")), S(Var("n")), diff="trivial", tags=["nat","add"]),
        # Nat — easy
        _thm("add_zero_right", "Adding zero on the right does nothing",
             add(Var("n"), Z()), Var("n"), diff="easy", tags=["nat","add"]),
        _thm("add_succ_right", "Successor distributes over addition",
             add(Var("n"), S(Var("m"))), S(add(Var("n"), Var("m"))), diff="easy", tags=["nat","add"]),
        _thm("add_one_right", "Adding one on the right is successor",
             add(Var("n"), S(Z())), S(Var("n")), diff="easy", tags=["nat","add"]),
        # Nat — medium
        _thm("add_assoc", "Addition is associative",
             add(add(Var("a"), Var("b")), Var("c")),
             add(Var("a"), add(Var("b"), Var("c"))),
             diff="medium", tags=["nat","add","algebra"]),
        _thm("add_comm", "Addition is commutative",
             add(Var("n"), Var("m")), add(Var("m"), Var("n")),
             ctx=[
                 Equation("add_zero_right", add(Var("a"), Z()), Var("a")),
                 Equation("add_succ_right", add(Var("a"), S(Var("b"))), S(add(Var("a"), Var("b")))),
             ],
             diff="medium", tags=["nat","add","algebra"]),
        # List — trivial
        _thm("append_nil_left", "Appending to empty list does nothing",
             append(Nil(), Var("xs")), Var("xs"), diff="trivial", tags=["list","append"]),
        _thm("length_nil", "Empty list has length zero",
             length(Nil()), Z(), diff="trivial", tags=["list","length"]),
        _thm("map_nil", "Mapping over empty list gives empty",
             map_f(Var("f"), Nil()), Nil(), diff="trivial", tags=["list","map"]),
        _thm("rev_nil", "Reversing empty list gives empty",
             rev(Nil()), Nil(), diff="trivial", tags=["list","rev"]),
        # List — easy
        _thm("append_nil_right", "Appending empty list does nothing",
             append(Var("xs"), Nil()), Var("xs"), diff="easy", tags=["list","append"]),
        _thm("rev_singleton", "Reversing singleton gives same",
             rev(Cons(Var("x"), Nil())), Cons(Var("x"), Nil()),
             ctx=[Equation("append_nil_right", append(Var("a"), Nil()), Var("a"))],
             diff="easy", tags=["list","rev"]),
        # List — medium
        _thm("append_assoc", "Append is associative",
             append(append(Var("xs"), Var("ys")), Var("zs")),
             append(Var("xs"), append(Var("ys"), Var("zs"))),
             diff="medium", tags=["list","append","algebra"]),
        _thm("length_append", "Length distributes over append",
             length(append(Var("xs"), Var("ys"))),
             add(length(Var("xs")), length(Var("ys"))),
             diff="medium", tags=["list","length","append"]),
        _thm("length_map", "Map preserves length",
             length(map_f(Var("f"), Var("xs"))), length(Var("xs")),
             diff="medium", tags=["list","length","map"]),
        _thm("map_append", "Map distributes over append",
             map_f(Var("f"), append(Var("xs"), Var("ys"))),
             append(map_f(Var("f"), Var("xs")), map_f(Var("f"), Var("ys"))),
             diff="medium", tags=["list","map","append"]),
        # List — hard
        _thm("length_rev", "Reverse preserves length",
             length(rev(Var("xs"))), length(Var("xs")),
             ctx=[
                 Equation("length_append",
                     length(append(Var("a"), Var("b"))),
                     add(length(Var("a")), length(Var("b")))),
                 Equation("add_comm",
                     add(Var("a"), Var("b")), add(Var("b"), Var("a"))),
             ],
             diff="hard", tags=["list","length","rev"]),
        _thm("rev_rev", "Double reverse is identity",
             rev(rev(Var("xs"))), Var("xs"),
             ctx=[
                 Equation("rev_append",
                     rev(append(Var("a"), Var("b"))),
                     append(rev(Var("b")), rev(Var("a")))),
                 Equation("append_nil_right", append(Var("a"), Nil()), Var("a")),
             ],
             diff="hard", tags=["list","rev"]),
        # Tree — trivial
        _thm("mirror_leaf", "Mirroring a leaf gives a leaf",
             mirror(Leaf()), Leaf(), diff="trivial", tags=["tree","mirror"]),
        # Tree — medium
        _thm("mirror_mirror", "Double mirror is identity",
             mirror(mirror(Var("t"))), Var("t"), diff="medium", tags=["tree","mirror"]),
        _thm("size_mirror", "Mirror preserves size",
             tree_size(mirror(Var("t"))), tree_size(Var("t")),
             ctx=[Equation("add_comm", add(Var("a"), Var("b")), add(Var("b"), Var("a")))],
             diff="medium", tags=["tree","mirror","size"]),
        # Tree — hard
        _thm("length_flatten", "Flattening preserves element count",
             length(flatten(Var("t"))), tree_size(Var("t")),
             ctx=[
                 Equation("length_append",
                     length(append(Var("a"), Var("b"))),
                     add(length(Var("a")), length(Var("b")))),
                 Equation("add_succ_right",
                     add(Var("k"), S(Var("j"))), S(add(Var("k"), Var("j")))),
             ],
             diff="hard", tags=["tree","flatten","length"]),
    ],
    vocabulary={
        "Z": "zero", "S": "successor", "add": "addition",
        "Nil": "empty list", "Cons": "prepend", "append": "concatenate",
        "rev": "reverse", "length": "length", "map": "map function",
        "Leaf": "empty tree", "Node": "tree node", "mirror": "mirror",
        "tsize": "tree size", "flatten": "flatten to list",
    },
    examples=[
        "Is addition commutative?",
        "Does reversing a list twice give back the original?",
        "Does mirroring a tree preserve its size?",
    ],
)

register_skill(core_math)
