#!/usr/bin/env python3
"""Regression-Tests fuer aria-hook-manifest.py (KAR-686, AgentScope-Pattern #1).

Run: python3 /root/aria/scripts/tests/test_hook_manifest.py
Modul hat Bindestriche -> Load via importlib.
"""
import importlib.util
import sys
import tempfile
from pathlib import Path

SCRIPT = Path("/root/aria/scripts/aria-hook-manifest.py")
spec = importlib.util.spec_from_file_location("hookmani", SCRIPT)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)

PASS = "\033[32mPASS\033[0m"
FAIL = "\033[31mFAIL\033[0m"
results = []


def check(name, cond):
    results.append(bool(cond))
    print(f"  [{PASS if cond else FAIL}] {name}")


SETTINGS = {
    "hooks": {
        "PreToolUse": [
            {"matcher": "Bash", "hooks": [
                {"type": "command", "command": "bash /tmp/hk/pre-tool-safety.sh", "timeout": 5},
                {"type": "command", "command": "rtk hook claude"},
            ]},
            {"matcher": "Write|Edit", "hooks": [
                {"type": "command", "command": "bash /tmp/hk/tdd-guard.sh", "timeout": 5},
            ]},
        ],
        "SessionStart": [
            {"hooks": [{"type": "command", "command": "bash /tmp/hk/session-start.sh"}]},
        ],
    }
}

man = mod.build_manifest(SETTINGS)

# A: Anzahl Hooks (4 Commands total)
check("A 4 Hooks erfasst", len(man) == 4)

# B: Event-Reihenfolge kanonisch (SessionStart vor PreToolUse)
events_in_order = [r["event"] for r in man]
check("B SessionStart vor PreToolUse (kanonische Order)",
      events_in_order.index("SessionStart") < events_in_order.index("PreToolUse"))

# C: order-Index pro Event zaehlt Ausfuehrungsreihenfolge (die "Chain")
pre = [r for r in man if r["event"] == "PreToolUse"]
check("C PreToolUse order = 0,1,2 ueber Matcher-Gruppen hinweg",
      [r["order"] for r in pre] == [0, 1, 2])
check("C order=0 ist pre-tool-safety, order=2 ist tdd-guard",
      pre[0]["script_name"] == "pre-tool-safety.sh" and pre[2]["script_name"] == "tdd-guard.sh")

# D: externes Binary (rtk) erkannt, kein script_path
rtk = pre[1]
check("D rtk als extern erkannt (is_external, kein script_path)",
      rtk["is_external"] and rtk["script_path"] is None)

# E: Matcher korrekt zugeordnet
check("E tdd-guard hat Matcher Write|Edit", pre[2]["matcher"] == "Write|Edit")

# F: Validierung findet fehlende Scripts + Orphans
hk = Path(tempfile.mkdtemp())
(hk / "pre-tool-safety.sh").write_text("#!/bin/bash\n")
(hk / "session-start.sh").write_text("#!/bin/bash\n")
# tdd-guard.sh FEHLT absichtlich -> missing
(hk / "ein-orphan.sh").write_text("#!/bin/bash\n")  # nirgends registriert -> orphan
# settings zeigt auf /tmp/hk/... aber validate prueft script_path direkt; baue Manifest mit hk-Pfaden
settings2 = {"hooks": {
    "SessionStart": [{"hooks": [{"type": "command", "command": f"bash {hk}/session-start.sh"}]}],
    "PreToolUse": [{"matcher": "Bash", "hooks": [
        {"type": "command", "command": f"bash {hk}/pre-tool-safety.sh"},
        {"type": "command", "command": f"bash {hk}/tdd-guard.sh"},  # fehlt auf Disk
        {"type": "command", "command": "rtk hook claude"},
    ]}],
}}
man2 = mod.build_manifest(settings2)
v = mod.validate(man2, hk)
check("F missing erkennt fehlendes tdd-guard.sh", any("tdd-guard.sh" in m for m in v["missing"]))
check("F orphans erkennt ein-orphan.sh", "ein-orphan.sh" in v["orphans"])
check("F rtk-Binary NICHT als missing (extern)", not any("rtk" in m for m in v["missing"]))

# G: render erzeugt Markdown mit Auto-Gen-Marker + Event-Header
md = mod.render_markdown(man)
check("G render hat Auto-Gen-Warnung + Event-Header",
      "AUTO-GENERIERT" in md and "Event: `SessionStart`" in md and "| # | Matcher |" in md)

# H: splice_section — Erst-Insertion additiv (manuelle Tabelle bleibt), dann idempotenter Re-Run
hooks_md = ("# HOOKS\n\n## 2. Timers\n\n| t |\n|---|\n\n## 3. Claude Code Hooks\n\n"
            "| Hook | Owner |\n|---|---|\n| SessionStart | session-start.sh |\n\n## 4. Cron\n\nfoo\n")
spliced = mod.splice_section(hooks_md, md)
check("H1 Marker eingefügt", mod.MARKER_START in spliced and mod.MARKER_END in spliced)
check("H1 manuelle Detail-Tabelle NICHT zerstört", "| SessionStart | session-start.sh |" in spliced)
check("H1 Sektion 4 unangetastet", spliced.rstrip().endswith("foo"))
check("H1 Block steht in Sektion 3 (vor Sektion 4)",
      spliced.index(mod.MARKER_START) > spliced.index("## 3. Claude Code Hooks")
      and spliced.index(mod.MARKER_START) < spliced.index("## 4. Cron"))
# Re-Run muss zwischen Markern ersetzen, nicht doppelt einfügen
spliced2 = mod.splice_section(spliced, md)
check("H2 idempotent: genau 1 START-Marker nach Re-Run", spliced2.count(mod.MARKER_START) == 1)

# cleanup
for p in hk.glob("*"):
    p.unlink()
hk.rmdir()

print()
if all(results):
    print(f"All {len(results)} checks {PASS}")
    sys.exit(0)
print(f"{results.count(False)}/{len(results)} checks {FAIL}")
sys.exit(1)
