#!/usr/bin/env python3
"""Hindsight Nightly Dream Cycle — consolidation & contradiction detection.

Uses Hindsight REST API /reflect to check for:
1. Contradictions in stored facts
2. Blocked/stale TODOs
3. Potentially outdated facts

Silent when nothing notable (empty stdout = no message)."""
import json
import subprocess
from datetime import datetime, timezone

HINDSIGHT_URL = "http://127.0.0.1:9177/v1/default/banks/hermes"

def reflect(query, budget="low"):
    result = subprocess.run(
        ["curl", "-s", "-X", "POST", f"{HINDSIGHT_URL}/reflect",
         "-H", "Content-Type: application/json",
         "-d", json.dumps({"query": query, "budget": budget})],
        capture_output=True, text=True, timeout=120
    )
    try:
        data = json.loads(result.stdout)
        return data.get("text", "").strip()
    except (json.JSONDecodeError, KeyError):
        return ""

def recall(query, budget="low"):
    result = subprocess.run(
        ["curl", "-s", "-X", "POST", f"{HINDSIGHT_URL}/memories/recall",
         "-H", "Content-Type: application/json",
         "-d", json.dumps({"query": query, "budget": budget})],
        capture_output=True, text=True, timeout=60
    )
    try:
        data = json.loads(result.stdout)
        if isinstance(data, list):
            return "\n".join(str(item.get("text", item)) for item in data if item)
        text = data.get("text", data.get("results", ""))
        if isinstance(text, list):
            return "\n".join(str(item.get("text", item)) for item in text if item)
        return str(text).strip()
    except (json.JSONDecodeError, KeyError, AttributeError):
        return ""

def main():
    now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
    findings = []

    # 1. Contradiction detection
    contradiction = reflect(
        "Gibt es Widersprüche oder Konflikte zwischen den gespeicherten Fakten? "
        "Prüfe insbesondere IPs, VLANs, Credentials und Gerätestatus. "
        "Antworte KURZ: nur konkrete Widersprüche mit den beteiligten Fakten, "
        "oder 'Keine Widersprüche' wenn alles konsistent.",
        budget="mid"
    )
    if contradiction and "Keine Widersprüche" not in contradiction and "keine" not in contradiction.lower()[:20]:
        findings.append(("🔄 Widersprüche erkannt", contradiction))

    # 2. Blocked/stale TODOs
    todos = recall("TODO offen blockiert wartet ausstehend", budget="mid")
    if todos:
        todo_reflect = reflect(
            f"Welche der folgenden TODOs sind blockiert oder überfällig?\n{todos}\n"
            "Antworte KURZ: nur blockierte/überfällige Items mit Begründung, "
            "oder 'Keine blockierten TODOs' wenn nichts dringend.",
            budget="low"
        )
        if todo_reflect and "Keine blockierten" not in todo_reflect:
            findings.append(("📋 Blockierte/Überfällige TODOs", todo_reflect))

    # 3. Outdated facts
    stale = reflect(
        "Gibt es Fakten die sich möglicherweise geändert haben "
        "(z.B. IPs, Software-Versionen, Stati die 'kaputt' oder 'defekt' waren "
        "aber mittlerweile behoben sein könnten)? "
        "Antworte KURZ: nur potenziell veraltete Fakten, "
        "oder 'Keine veralteten Fakten' wenn alles aktuell.",
        budget="low"
    )
    if stale and "Keine veralteten" not in stale and "keine" not in stale.lower()[:20]:
        findings.append(("⚠️ Möglicherweise veraltete Fakten", stale))

    # 4. Self-improvement: learnings that contradict existing skills
    si = reflect(
        "Gibt es SOLUTION-Einträge oder gespeicherte Erfahrungen, die aufzeigen dass "
        "ein bestehender Skill (z.B. systematic-debugging, brainstorming, plan) "
        "einen Fehler, eine fehlende Methode oder eine veraltete Annahme enthält? "
        "Prüfe ob ein Learning einen Skill-Patch oder MEMORY.md-Update nahelegt. "
        "Antworte KURZ: nur konkrete Self-Improvement-Vorschläge mit Skill-Name "
        "und was geändert werden sollte, oder 'Keine Skill-Verbesserungen nötig'.",
        budget="mid"
    )
    if si and "Keine Skill-Verbesserungen" not in si and "keine" not in si.lower()[:20]:
        findings.append(("🔧 Self-Improvement-Vorschläge", si))

    if not findings:
        return

    print(f"🌙 Nightly Dream Cycle — {now}")
    print()
    for title, content in findings:
        print(f"**{title}**")
        print(content)
        print()

if __name__ == "__main__":
    main()
