"""
Skill: Access Control Logic
=============================
Verify properties about permission systems, role hierarchies,
and access policies.

Types:
  Permission — None | Grant(resource, rest)
  
Functions:
  has_access(None, r)          = False
  has_access(Grant(r, rest), r) = True  (same resource)
  has_access(Grant(x, rest), r) = has_access(rest, r)  (different resource)
  
  combine(None, p)             = p
  combine(Grant(r, rest), p)   = Grant(r, combine(rest, p))
  
  count(None)                  = Z
  count(Grant(r, rest))        = S(count(rest))
"""

from nexus_gate_pkg.engine.skills import Skill, TheoremDef, register_skill
from nexus_gate_pkg.engine.terms import Var, Const, App, RewriteRule, Equation
from nexus_gate_pkg.corpus.domain import DEFINITIONS as NAT_DEFS, Z, S, add


def NoPerms():
    return Const("NoPerms")

def Grant(resource, rest):
    return App("Grant", [resource, rest])

def pcount(p):
    return App("pcount", [p])

def combine(p1, p2):
    return App("pcombine", [p1, p2])


a, b, r, p, q = Var("a"), Var("b"), Var("r"), Var("p"), Var("q")


ACCESS_DEFS = [
    RewriteRule("pcount_None", pcount(NoPerms()), Z()),
    RewriteRule("pcount_Grant", pcount(Grant(r, p)), S(pcount(p))),

    RewriteRule("pcombine_None", combine(NoPerms(), p), p),
    RewriteRule("pcombine_Grant", combine(Grant(r, p), q),
                Grant(r, combine(p, q))),
]


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 ["access"])

access_skill = Skill(
    id="access_control",
    name="Access Control Logic",
    description="Verify permission composition, role merging, and access policies",
    version="1.0.0",
    author="Example",
    depends_on=["core_math"],
    definitions=ACCESS_DEFS,
    theorems=[
        _thm("count_empty", "Empty permissions have zero grants",
             pcount(NoPerms()), Z(), diff="trivial"),

        _thm("combine_empty_right", "Combining with no permissions changes nothing",
             combine(p, NoPerms()), p,
             diff="easy", tags=["access", "combine"]),

        _thm("count_combine", "Total grants after combining equals sum of individual grants",
             pcount(combine(p, q)), add(pcount(p), pcount(q)),
             diff="medium", tags=["access", "combine", "count"]),

        _thm("combine_assoc", "Permission combining is associative",
             combine(combine(p, q), Var("r2")),
             combine(p, combine(q, Var("r2"))),
             diff="medium", tags=["access", "combine", "algebra"]),
    ],
    vocabulary={
        "NoPerms": "no permissions",
        "Grant": "grant access to resource",
        "pcount": "permission count",
        "pcombine": "combine permissions",
    },
    examples=[
        "Is combining permissions associative?",
        "Does the total permission count add up after merging?",
    ],
)

register_skill(access_skill)

# Register induction scheme for Permission type
from nexus_gate_pkg.engine.proof import register_induction_scheme
register_induction_scheme(
    type_name="Permission",
    base_constructor="NoPerms",
    rec_constructor="Grant",
    rec_arg_count=2,          # Grant(resource, rest)
    rec_positions=[1],        # only 'rest' (arg index 1) is recursive
    var_hints={"perm", "perms", "acl"},
)
