#!/usr/bin/env python3
"""
Curator Auto-Archivierung: Archiviert Skills nach 14 Tagen Inaktivität.

Liest `.curator_state` und `.usage.json` aus ~/.hermes/skills/, prüft
auf Inaktivität (>14 Tage last_used_at), schließt aus (pinned, system)
und verschiebt in .archive/<Kategorie>/.
"""

import json
import os
import shutil
from datetime import datetime, timezone
from pathlib import Path

HERMES_SKILLS_DIR = Path.home() / ".hermes" / "skills"
CURATOR_STATE_FILE = HERMES_SKILLS_DIR / ".curator_state"
USAGE_JSON_FILE = HERMES_SKILLS_DIR / ".usage.json"
ARCHIVE_DIR = HERMES_SKILLS_DIR / ".archive"
LOG_DIR = Path.home() / ".hermes" / "logs" / "curator"


def load_json(path: Path) -> dict:
    """JSON-Datei laden."""
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)


def save_json(path: Path, data: dict) -> None:
    """JSON-Datei speichern (mit Pretty-Print)."""
    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
        f.write("\n")


def is_stale(skill_usage: dict, threshold_days: int = 14) -> bool:
    """Prüft, ob ein Skill älter als threshold_days ist."""
    last_used = skill_usage.get("last_used_at")
    if not last_used:
        return False

    # ISO-Format mit optionaler Zeitzone
    last_used_str = last_used.replace("Z", "+00:00")
    try:
        last_used_dt = datetime.fromisoformat(last_used_str)
    except ValueError:
        return False

    now = datetime.now(timezone.utc)
    delta = now - last_used_dt
    return delta.days >= threshold_days


def is_excluded(skill_name: str, excluded: list) -> bool:
    """Prüft, ob ein Skill ausgeschlossen ist."""
    return skill_name in excluded


def is_pinned(skill_usage: dict) -> bool:
    """Prüft, ob ein Skill angepinnt ist."""
    return skill_usage.get("pinned", False) is True


def get_skill_category(skill_name: str) -> str:
    """
    Ermittelt die Kategorie eines Skills basierend auf dem Verzeichnisnamen.
    Gibt 'unknown' zurück, wenn keine Kategorie gefunden wird.
    """
    # Versuche, die Kategorie aus dem Verzeichnis zu ermitteln
    # z.B. 'betrieb-playbook' → 'betrieb-playbook' (direkt unter skills/)
    # 'apple' (in .archive/apple/) → 'apple'
    # Falls der Skill direkt in skills/ liegt ohne Unterverzeichnis:
    return "unknown"


def ensure_archive_category(category: str) -> Path:
    """Erstellt das Archiv-Verzeichnis für eine Kategorie, falls nötig."""
    category_path = ARCHIVE_DIR / category
    category_path.mkdir(parents=True, exist_ok=True)
    return category_path


def move_skill_to_archive(skill_name: str, category: str) -> Path:
    """
    Verschiebt ein Skill-Verzeichnis in das Archiv.
    Gibt den neuen Pfad zurück.
    """
    source = HERMES_SKILLS_DIR / skill_name
    target_category = ensure_archive_category(category)
    target = target_category / skill_name

    if source.exists():
        shutil.move(str(source), str(target))

    return target


def archive_skill(skill_name: str, usage_data: dict) -> dict:
    """
    Archiviert einen Skill:
    - Setzt state auf 'archived'
    - Setzt archived_at auf aktuelle Zeit
    - Verschiebt das Verzeichnis nach .archive/
    Gibt das aktualisierte Usage-Dict zurück.
    """
    usage_data[skill_name]["state"] = "archived"
    usage_data[skill_name]["archived_at"] = datetime.now(timezone.utc).isoformat()
    return usage_data


def log_archive_action(skill_name: str, category: str, success: bool, message: str) -> None:
    """Protokolliert eine Archivierungsaktion."""
    LOG_DIR.mkdir(parents=True, exist_ok=True)
    log_file = LOG_DIR / f"archive-{datetime.now(timezone.utc).date().isoformat()}.log"

    timestamp = datetime.now(timezone.utc).isoformat()
    status = "SUCCESS" if success else "FAILED"
    log_line = f"[{timestamp}] {status} | {skill_name} ({category}) | {message}\n"

    with open(log_file, "a", encoding="utf-8") as f:
        f.write(log_line)


def main() -> None:
    """Hauptfunktion: Archiviert stale Skills."""
    # 1. Config laden
    if not CURATOR_STATE_FILE.exists():
        print(f"Fehler: {CURATOR_STATE_FILE} nicht gefunden.")
        return

    curator_state = load_json(CURATOR_STATE_FILE)
    archivierung = curator_state.get("archivierung", {})
    if not archivierung.get("enabled", False):
        print("Archivierung ist nicht aktiviert.")
        return

    threshold_days = archivierung.get("threshold_days", 14)
    excluded_skills = archivierung.get("excluded_skills", [])

    # 2. Usage-Daten laden
    if not USAGE_JSON_FILE.exists():
        print(f"Fehler: {USAGE_JSON_FILE} nicht gefunden.")
        return

    usage_data = load_json(USAGE_JSON_FILE)

    # 3. Skills prüfen
    archived_count = 0
    skipped_count = 0

    for skill_name, skill_usage in usage_data.items():
        # Ausschlusskriterien prüfen
        if is_excluded(skill_name, excluded_skills):
            print(f"Übersprungen (Exkludiert): {skill_name}")
            skipped_count += 1
            continue

        if is_pinned(skill_usage):
            print(f"Übersprungen (Gepinnt): {skill_name}")
            skipped_count += 1
            continue

        # Inaktivität prüfen
        if not is_stale(skill_usage, threshold_days):
            print(f"Übersprungen (Aktiv): {skill_name}")
            skipped_count += 1
            continue

        # Archivierung durchführen
        category = get_skill_category(skill_name) or "unknown"
        print(f"Archiviere: {skill_name} → {category}")

        try:
            # Usage aktualisieren
            usage_data = archive_skill(skill_name, usage_data)

            # Verzeichnis verschieben
            move_skill_to_archive(skill_name, category)

            # Erfolg protokollieren
            log_archive_action(skill_name, category, True, "Skill archiviert")

            archived_count += 1
        except Exception as e:
            log_archive_action(skill_name, category, False, str(e))
            print(f"Fehler beim Archivieren von {skill_name}: {e}")

    # 4. Usage-Daten speichern
    save_json(USAGE_JSON_FILE, usage_data)

    # 5. Archivierungs-Zeitstempel aktualisieren
    curator_state["archivierung"]["last_archive_run_at"] = datetime.now(timezone.utc).isoformat()
    save_json(CURATOR_STATE_FILE, curator_state)

    print(f"\nArchivierung abgeschlossen: {archived_count} archiviert, {skipped_count} übersprungen.")


if __name__ == "__main__":
    main()
