#!/usr/bin/env python3
"""
Auditor — Stufe 4: Roh-Report aus scan.json rendern.

Ohne Judge-Pass landen alle Scanner-Befunde in Sektion 3 "Nur gemeldet".
Der Report-Output-Pfad wird über die Loader-API aufgelöst.

Aufruf:
    python render-raw-report.py [scan.json] [output.md] [--run-type geplant|manuell] [--duration mm:ss]
    python render-raw-report.py --scan <pfad> --output <pfad>
"""

from __future__ import annotations

import argparse
import json
import sys
from datetime import datetime
from pathlib import Path

_SKILL_DIR = Path(__file__).resolve().parent
_SKILLS_ROOT = _SKILL_DIR.parent
if str(_SKILLS_ROOT) not in sys.path:
    sys.path.insert(0, str(_SKILLS_ROOT))

from _lib.config_loader import load_skill_config  # noqa: E402


def load_evals_map(skill_dir: Path):
    evals_path = skill_dir / "evals.json"
    if not evals_path.exists():
        # Keine lokale evals.json — leere Map, Labels fallen auf ID-Namen zurück
        return {}, "unknown"
    data = json.loads(evals_path.read_text(encoding="utf-8"))
    eval_map = {e["id"]: e for e in data.get("evals", [])}
    for s in data.get("secondary", []):
        eval_map[s["id"]] = s
    return eval_map, data.get("version", "unknown")


def render_e01(items, label):
    if not items:
        return f"- **{label}:** keine Befunde."
    lines = [f"- **{label}** ({len(items)} Dateien ohne eingehende Wikilinks):"]
    for it in items:
        lines.append(f"  - `{it['path']}` (type: {it.get('type','?')})")
    return "\n".join(lines)


def render_e02(data, label):
    fehlend = data.get("fehlend", [])
    if not fehlend:
        return f"- **{label}:** keine Befunde."
    lines = [f"- **{label}** ({len(fehlend)} Pflichten ohne Skill):"]
    for f in fehlend:
        lines.append(f"  - `{f.get('pflicht', '?')}` (fehlende Skills: {', '.join(f.get('fehlende_skills', []))})")
    return "\n".join(lines)


def render_e03(items, label):
    if not items:
        return f"- **{label}:** keine Befunde."
    lines = [f"- **{label}** (Top-10 nach Jaccard-Ähnlichkeit):"]
    for it in items[:10]:
        lines.append(f"  - `{it['skill_a']}` ↔ `{it['skill_b']}` — Jaccard {it['jaccard']:.3f}")
    return "\n".join(lines)


def render_e04(items, label):
    if not items:
        return f"- **{label}:** keine Befunde."
    lines = [f"- **{label}** ({len(items)} Dateien):"]
    for it in items:
        lines.append(f"  - `{it['path']}` (updated: {it.get('updated','?')})")
    return "\n".join(lines)


def render_e05(data, label):
    geister = data.get("geisterskills", [])
    if not geister:
        return f"- **{label}:** keine neuen Skills im Prüf-Fenster."
    lines = [f"- **{label}** ({len(geister)} Skills im Fenster, Judge-Pass empfohlen):"]
    for s in geister:
        lines.append(f"  - `{s['name']}` ({s['path']})")
    return "\n".join(lines)


def render_e06(items, label):
    if not items:
        return f"- **{label}:** keine toten Wikilinks."
    lines = [f"- **{label}** ({len(items)} tote Wikilinks):"]
    for it in items:
        lines.append(f"  - `{it['source']}` → `[[{it['target']}]]`")
    return "\n".join(lines)


def render_s01(items, label):
    if not items:
        return f"- **{label}:** keine Umlaut-Ersatz-Verstöße."
    lines = [f"- **{label}** ({len(items)} Dateien mit ae/oe/ue-Verstoß):"]
    for it in items:
        hits = ", ".join(sorted(set(it.get("verdaechtig", []))))
        lines.append(f"  - `{it['path']}` (Feld: {it.get('field','?')}) — Treffer: {hits}")
    return "\n".join(lines)


def get_output_path(args, cfg, today: str) -> Path:
    """Bestimmt den Ausgabepfad für den Report."""
    if args.output_flag or args.output:
        return Path(args.output_flag or args.output)
    reports_dir = cfg.paths.get("reports_dir")
    if reports_dir:
        return reports_dir / f"{today}.md"
    # Fallback: skill-lokal
    return _SKILL_DIR / "reports" / f"{today}.md"


def main(argv: list[str] | None = None) -> int:
    ap = argparse.ArgumentParser(description="Auditor Roh-Report Renderer.")
    ap.add_argument("scan", nargs="?", help="Pfad zur scan.json (positional, alt)")
    ap.add_argument("output", nargs="?", help="Ausgabepfad (positional, alt)")
    ap.add_argument("--scan", dest="scan_flag", help="Pfad zur scan.json")
    ap.add_argument("--output", dest="output_flag", help="Ausgabepfad für den Report")
    ap.add_argument("--run-type", default="manuell", choices=["geplant", "manuell"])
    ap.add_argument("--duration", default="—")
    ap.add_argument("--vault", help="Vault-Root für die Config-Auflösung")
    args = ap.parse_args(argv)

    scan_arg = args.scan_flag or args.scan
    scan_path = Path(scan_arg) if scan_arg else _SKILL_DIR / "scan.json"

    vault_root = Path(args.vault) if args.vault else None
    cfg = load_skill_config(
        skill_dir=_SKILL_DIR,
        vault_root=vault_root,
        bundle_root=None,
        default_paths={"reports_dir": "{system}/Auditor/reports"},
    )

    scan = json.loads(scan_path.read_text(encoding="utf-8"))
    eval_map, evals_version = load_evals_map(_SKILL_DIR)
    today = datetime.now().strftime("%Y-%m-%d")

    output_path = get_output_path(args, cfg, today)

    results = scan.get("eval_results", {})

    def _label(key: str) -> str:
        return eval_map.get(key, {}).get("label", key)

    sections = []
    # Eval-Keys mit echten Umlauten (Bundle-Format)
    sections.append(render_e01(results.get("E01-tote-zahnräder", results.get("E01-tote-zahnraeder", [])), _label("E01-tote-zahnräder") or "tote Zahnräder"))
    sections.append(render_e02(results.get("E02-pflicht-ohne-ausführung", {}), _label("E02-pflicht-ohne-ausführung") or "Pflicht ohne Ausführung"))
    sections.append(render_e03(results.get("E03-doppelzahnrad", []), _label("E03-doppelzahnrad") or "Doppelzahnrad"))
    sections.append(render_e04(results.get("E04-rostige-zahnräder", results.get("E04-rostige-zahnraeder", [])), _label("E04-rostige-zahnräder") or "rostige Zahnräder"))
    sections.append(render_e05(results.get("E05-geisterskill", {}), _label("E05-geisterskill") or "Geisterskill"))
    sections.append(render_e06(results.get("E06-tote-links", []), _label("E06-tote-links") or "tote Links"))
    sections.append(render_s01(results.get("S01-umlaute", []), _label("S01-umlaute") or "Umlaut-Verstoß"))

    n_e01 = len(results.get("E01-tote-zahnräder", results.get("E01-tote-zahnraeder", [])))
    n_e02 = len(results.get("E02-pflicht-ohne-ausführung", {}).get("fehlend", []))
    n_e03 = len(results.get("E03-doppelzahnrad", []))
    n_e04 = len(results.get("E04-rostige-zahnräder", results.get("E04-rostige-zahnraeder", [])))
    n_e05 = len(results.get("E05-geisterskill", {}).get("geisterskills", []))
    n_e06 = len(results.get("E06-tote-links", []))
    n_s01 = len(results.get("S01-umlaute", []))
    total_findings = n_e01 + n_e02 + n_e03 + n_e04 + n_e05 + n_e06 + n_s01

    body = f"""---
type: auditor-report
description: "Wöchentlicher Auditor-Report vom {today}. Roh-Befunde aus scan.py ohne Judge-Klassifikation."
tags:
  - auditor
  - second-brain
  - auto-research
created: {today}
updated: {today}
agent_ready: true
---

# Auditor-Report — {today}

**Lauf-Typ:** {args.run_type}
**Dauer:** {args.duration}
**Evals-Version:** {evals_version}
**Befunde gesamt:** {total_findings} ({n_e01} E01, {n_e02} E02, {n_e03} E03, {n_e04} E04, {n_e05} E05, {n_e06} E06, {n_s01} S01)

Dieser Report enthält Scanner-Rohbefunde ohne Judge-Klassifikation. Alle Befunde landen in Sektion 3. Der Judge-Pass erfolgt mittwochs via `/auditor-judge`.

---

## 1. Selbst erledigt

Keine Reparaturen in diesem Lauf. Judge-Pass für Autonomie-Gabelung erforderlich.

---

## 2. Entwurf zur Diskussion

Keine Entwürfe in diesem Lauf.

---

## 3. Nur gemeldet (Scanner-Rohbefunde)

{chr(10).join(sections)}

---

## 4. Unentschieden / Daten-Lücken

- **Judge-Pass nicht aktiv.** Alle Befunde sind Scanner-Rohdaten ohne semantische Klassifikation.
- **Stage 3 deaktiviert.** Selbst-Reparatur ist opt-in (siehe `skill.config.yaml` → `enable_self_repair`).

---

## 5. Wirehead-Status

- **Stage-3-Status:** deaktiviert (Bundle-Default)
- **Änderungen an Skill-Definition:** keine

---

## Verknüpfungen

- [[.claude/skills/auditor/SKILL|Auditor SKILL]]
"""

    output_path.parent.mkdir(parents=True, exist_ok=True)
    tmp = output_path.with_suffix(".tmp")
    tmp.write_text(body, encoding="utf-8")
    tmp.replace(output_path)
    print(f"Report geschrieben: {output_path}")
    print(f"Befunde gesamt: {total_findings}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
