#!/usr/bin/env python3
"""Regression-Tests fuer aria-skill-index.py (KAR-686, AgentScope-Pattern #3).

Run: python3 /root/aria/scripts/tests/test_skill_index.py
"""
import importlib.util
import sys
import tempfile
from pathlib import Path

SCRIPT = Path("/root/aria/scripts/aria-skill-index.py")
spec = importlib.util.spec_from_file_location("skillidx", 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}")


# Frontmatter-Parsing: inline + folded(>) + fehlend
inline = "---\nname: foo\ndescription: A short desc here\n---\n# Body\n"
folded = "---\nname: bar\ndescription: >\n  Eine lange\n  gefaltete Beschreibung.\n---\n# Body\n"
nofm = "# Kein Frontmatter\nnur text\n"

check("A inline description geparst", mod.parse_frontmatter(inline).get("description") == "A short desc here")
check("A folded name geparst", mod.parse_frontmatter(folded).get("name") == "bar")
check("A kein-Frontmatter -> {}", mod.parse_frontmatter(nofm) == {})

# A2: yaml-brechendes Frontmatter (ASCII-Quotes in quoted string + [[wikilinks]]) — Aria-real
yaml_breaker = ('---\nname: senior-review\n'
                'description: "Review im Stil, „mach mal Review", „Staff-Review" sagt. Siehe /review."\n'
                '---\n# Body\n')
bracket_breaker = ('---\nname: pre-task-inventory\n'
                   'description: Scannt Stack vor Aktion. Siehe [[back_active_memory]].\ntype: tool\n'
                   '---\n# Body\n')
fb1 = mod.parse_frontmatter(yaml_breaker)
fb2 = mod.parse_frontmatter(bracket_breaker)
check("A2 quote-breaker: name+description gerettet (Fallback)",
      fb1.get("name") == "senior-review" and "Staff-Review" in (fb1.get("description") or ""))
check("A2 wikilink-breaker: name+description gerettet (Fallback)",
      fb2.get("name") == "pre-task-inventory" and "[[back_active_memory]]" in (fb2.get("description") or ""))

# build_index über temp skill-dirs
root = Path(tempfile.mkdtemp())
(root / "foo").mkdir(); (root / "foo" / "SKILL.md").write_text(inline)
(root / "bar").mkdir(); (root / "bar" / "SKILL.md").write_text(folded)
(root / "leer").mkdir()  # kein SKILL.md -> wird ignoriert
(root / "nofm").mkdir(); (root / "nofm" / "SKILL.md").write_text(nofm)  # slug-fallback

idx = mod.build_index(root)
slugs = {r["slug"] for r in idx}
check("B 3 Skills mit SKILL.md indexiert (leer ignoriert)", len(idx) == 3 and "leer" not in slugs)

foo = next(r for r in idx if r["slug"] == "foo")
check("B foo: name+description+mtime+size gesetzt",
      foo["name"] == "foo" and foo["description"] == "A short desc here"
      and foo["mtime"] > 0 and foo["size_bytes"] > 0)

bar = next(r for r in idx if r["slug"] == "bar")
check("B bar: folded description zu einer Zeile normalisiert",
      bar["description"] == "Eine lange gefaltete Beschreibung." and bar["has_description"])

nofm_r = next(r for r in idx if r["slug"] == "nofm")
check("B nofm: name faellt auf slug zurueck, has_name=False",
      nofm_r["name"] == "nofm" and nofm_r["has_name"] is False and nofm_r["has_description"] is False)

# search: alle Terme muessen matchen
check("C search 'lange Beschreibung' findet bar", [r["slug"] for r in mod.search(idx, "lange Beschreibung")] == ["bar"])
check("C search 'short desc' findet foo", [r["slug"] for r in mod.search(idx, "short desc")] == ["foo"])
check("C search no-match -> leer", mod.search(idx, "zzz_kein_treffer") == [])

# cleanup
for p in root.rglob("*"):
    if p.is_file():
        p.unlink()
for p in sorted(root.rglob("*"), reverse=True):
    if p.is_dir():
        p.rmdir()
root.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)
