#!/usr/bin/env python3
"""
Aria Brain Layers — Identity-Layer vs User-Layer Klassifikator (KAR-625)

Foundation-Tool für die Company-Brain / Aria-Distribution-Strategie.
Klassifiziert jede Brain-Note in zwei Schichten:

  • IDENTITY-Layer  — generisch, verkäuflich, user-unabhängig
                      (Aria-Persona, Werte, Tool-Konventionen, Skills-Doku,
                       generische Architektur-Audits)
  • USER-Layer      — Kais-spezifisch, NICHT verkäuflich
                      (Kais-Modell, Daily-Logs, Projekte, Business-Wissen,
                       Feedback, Memory mit PII)

Ein Drittes: MIXED — nominell Identity-Layer, enthält aber User-PII.
Das sind die Refactor-Targets für die Layer-Trennung (z.B. SOUL.md, das
generische Werte mit Kais-Mission vermischt).

Der Klassifikator ist die automatisierte Ist-Analyse für die spätere
per-User-Scoping-Architektur. Er ändert NICHTS — read-only Audit.

Usage:
  aria-brain-layers.py                 # Mensch-lesbarer Report
  aria-brain-layers.py --json          # Maschinen-Output
  aria-brain-layers.py --list mixed    # nur Mixed-Files listen (Refactor-Targets)
"""

import os
import re
import sys
import json
import argparse
from pathlib import Path

BRAIN_DIR = Path(os.path.expandvars("$HOME/aria/brain"))

# --- Layer-Heuristik ----------------------------------------------------------

# Root-Identity-Files: generische Aria-Schicht (Persona/Werte/Tools/Skills).
# CORRECTIONS + MEMORIES + USER sind bewusst NICHT hier — die tragen Kais-Muster.
IDENTITY_ROOT = {
    "SOUL.md", "IDENTITY.md", "TOOLS.md", "SELF-IMPROVEMENT.md",
    "HOOKS.md", "HEARTBEAT.md", "ENGINEERING.md", "CLAUDE.md",
}

# Pfad-Präfixe, die per se User-Layer sind (Kais-Content):
USER_PREFIXES = (
    "06-Daily", "00-Inbox", "01-Projekte", "03-Recherchen",
    "04-Feedback",
)
# Root-Files die User-Layer sind:
USER_ROOT = {"USER.md", "CORRECTIONS.md", "MEMORIES.md", "HANDOFF.md"}

# 02-Wissen / 05-Referenzen sind gemischt: Aria-Self-Audits = Identity,
# Business-/BMW-/Kadi-Wissen = User. Wird per Content entschieden.
AMBIGUOUS_PREFIXES = ("02-Wissen", "05-Referenzen")

# PII / Kais-spezifische Marker. Treffer in einem Identity-Layer-File => MIXED.
PII_MARKERS = re.compile(
    r"\b(Kais|Aseckzai|aseckzai@gmail|KADiCon|Kadi-v2|Kadi\b|BMW|Durrani|"
    r"1164395546|kaiss78|srv1649305|Hetzner|"
    r"dvvlyqlvaxcnsuemjksv|qiamvqfaszbgohczjsuz|nghepoidagwamsesrcdl)\b",
    re.IGNORECASE,
)
# Marker, die auf generische Aria-Self-Doku hindeuten (Identity-Signal):
IDENTITY_SIGNAL = re.compile(
    r"\b(Aria-Architektur|Aria-Self|gbrain|openclaw|hermes|superpowers|"
    r"skill|persona|prompt-injection|brain-schema|distribution)\b",
    re.IGNORECASE,
)


def classify(rel_path: str, text: str) -> tuple[str, int]:
    """Gibt (layer, pii_hits) zurück. layer in {identity, user, mixed}."""
    name = Path(rel_path).name
    pii_hits = len(PII_MARKERS.findall(text))

    # 1. Harte User-Root-Files
    if name in USER_ROOT:
        return "user", pii_hits

    # 2. Harte User-Pfade
    if rel_path.startswith(USER_PREFIXES):
        return "user", pii_hits

    # 3. Identity-Root-Files: Identity, aber MIXED wenn PII drin
    if name in IDENTITY_ROOT:
        return ("mixed" if pii_hits > 0 else "identity"), pii_hits

    # 4. Ambiguous (02-Wissen / 05-Referenzen): per Content
    if rel_path.startswith(AMBIGUOUS_PREFIXES):
        id_signal = len(IDENTITY_SIGNAL.findall(text))
        # Generische Aria-Self-Doku ohne (oder mit wenig) PII => identity
        if id_signal >= 3 and pii_hits <= id_signal:
            return ("mixed" if pii_hits > 0 else "identity"), pii_hits
        return "user", pii_hits

    # 5. Default: alles andere ist User-Layer (konservativ — im Zweifel privat)
    return "user", pii_hits


def main() -> int:
    ap = argparse.ArgumentParser(description="Aria Brain Identity/User-Layer Klassifikator")
    ap.add_argument("--json", action="store_true", help="JSON-Output")
    ap.add_argument("--list", choices=["identity", "user", "mixed"],
                    help="Nur Files dieser Schicht listen")
    args = ap.parse_args()

    if not BRAIN_DIR.is_dir():
        print(f"FEHLER: {BRAIN_DIR} existiert nicht", file=sys.stderr)
        return 1

    buckets: dict[str, list[dict]] = {"identity": [], "user": [], "mixed": []}
    per_folder: dict[str, dict[str, int]] = {}

    for md in BRAIN_DIR.rglob("*.md"):
        if "/.git/" in str(md):
            continue
        rel = str(md.relative_to(BRAIN_DIR))
        try:
            text = md.read_text(encoding="utf-8", errors="ignore")
        except Exception:
            continue
        layer, pii = classify(rel, text)
        buckets[layer].append({"path": rel, "pii_hits": pii})
        top = rel.split("/")[0] if "/" in rel else "(root)"
        per_folder.setdefault(top, {"identity": 0, "user": 0, "mixed": 0})
        per_folder[top][layer] += 1

    total = sum(len(v) for v in buckets.values())

    if args.list:
        for item in sorted(buckets[args.list], key=lambda x: -x["pii_hits"]):
            print(f"{item['pii_hits']:>3} PII  {item['path']}")
        return 0

    if args.json:
        out = {
            "total": total,
            "counts": {k: len(v) for k, v in buckets.items()},
            "per_folder": per_folder,
            "mixed_files": sorted(buckets["mixed"], key=lambda x: -x["pii_hits"]),
        }
        print(json.dumps(out, ensure_ascii=False, indent=2))
        return 0

    # Mensch-lesbar
    print("=== ARIA BRAIN — LAYER-KLASSIFIKATION (KAR-625) ===")
    print(f"Brain: {BRAIN_DIR}")
    print(f"Notes total: {total}\n")
    print("Schicht-Verteilung:")
    for k in ("identity", "user", "mixed"):
        n = len(buckets[k])
        pct = (100 * n / total) if total else 0
        print(f"  {k:<9}: {n:>4}  ({pct:4.1f}%)")
    print("\nPro Top-Folder (identity / user / mixed):")
    for folder in sorted(per_folder):
        c = per_folder[folder]
        print(f"  {folder:<14}: {c['identity']:>3} / {c['user']:>3} / {c['mixed']:>3}")
    if buckets["mixed"]:
        print("\nMIXED-Files (Identity-Layer mit User-PII = Refactor-Targets):")
        for item in sorted(buckets["mixed"], key=lambda x: -x["pii_hits"])[:25]:
            print(f"  {item['pii_hits']:>3} PII-Treffer  {item['path']}")
    print("\nHinweis: read-only Audit. Physische Layer-Trennung ist ein")
    print("irreversibler Schritt und braucht Kais' Go (siehe Constitution).")
    print("===================================================")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
