#!/usr/bin/env python3
"""
Reaction-Based Correction Monitoring
Detects 👎 reactions on ARIA's messages as implicit correction signals.

This is Phase 2 of the correction capture system.
"""

import json
import yaml
from datetime import datetime
from pathlib import Path
from typing import Optional

CORRECTIONS_DIR = Path("/home/aria/.openclaw/workspace/agency/corrections")
REACTIONS_LOG = CORRECTIONS_DIR / "reaction_signals.jsonl"

# Reaction types and their correction signal strength
CORRECTION_REACTIONS = {
    "👎": {"type": "negative", "weight": 0.8, "description": "Explicit disapproval"},
    "❌": {"type": "negative", "weight": 0.9, "description": "Rejection/wrong"},
    "🤦": {"type": "negative", "weight": 0.7, "description": "Facepalm/mistake"},
    "🙄": {"type": "negative", "weight": 0.5, "description": "Eye roll/annoyance"},
    "😕": {"type": "negative", "weight": 0.4, "description": "Confusion"},
    "🚫": {"type": "negative", "weight": 0.85, "description": "Prohibited/stop"},
}

POSITIVE_REACTIONS = {
    "👍": {"type": "positive", "weight": 0.8, "description": "Approval"},
    "✅": {"type": "positive", "weight": 0.9, "description": "Correct/done"},
    "❤️": {"type": "positive", "weight": 0.7, "description": "Love/great"},
    "🎉": {"type": "positive", "weight": 0.8, "description": "Celebration"},
    "🔥": {"type": "positive", "weight": 0.75, "description": "Fire/excellent"},
}


def log_reaction_signal(
    message_id: str,
    message_content: str,
    reaction_emoji: str,
    reactor_username: str,
    channel_id: str,
    timestamp: str,
    context: Optional[dict] = None
) -> dict:
    """
    Log a reaction as a potential correction signal.
    """
    is_correction = reaction_emoji in CORRECTION_REACTIONS
    is_positive = reaction_emoji in POSITIVE_REACTIONS
    
    if is_correction:
        signal_info = CORRECTION_REACTIONS[reaction_emoji]
    elif is_positive:
        signal_info = POSITIVE_REACTIONS[reaction_emoji]
    else:
        signal_info = {"type": "neutral", "weight": 0.0, "description": "Unknown"}
    
    entry = {
        "timestamp": timestamp,
        "logged_at": datetime.utcnow().isoformat(),
        "message_id": message_id,
        "message_preview": message_content[:200] if message_content else "",
        "reaction": reaction_emoji,
        "reactor": reactor_username,
        "channel_id": channel_id,
        "signal_type": signal_info["type"],
        "weight": signal_info["weight"],
        "description": signal_info["description"],
        "context": context or {},
    }
    
    # Append to JSONL log
    CORRECTIONS_DIR.mkdir(exist_ok=True)
    with open(REACTIONS_LOG, 'a') as f:
        f.write(json.dumps(entry) + "\n")
    
    return entry


def analyze_reaction_patterns(days: int = 7) -> dict:
    """
    Analyze reaction patterns to find repeated correction signals.
    Repeated 👎 on similar message types = systemic issue.
    """
    if not REACTIONS_LOG.exists():
        return {"patterns": [], "summary": "No reaction data yet"}
    
    entries = []
    with open(REACTIONS_LOG) as f:
        for line in f:
            if line.strip():
                entries.append(json.loads(line))
    
    # Group by signal type
    negatives = [e for e in entries if e["signal_type"] == "negative"]
    positives = [e for e in entries if e["signal_type"] == "positive"]
    
    # Find patterns (messages with multiple negative reactions)
    message_reactions = {}
    for entry in negatives:
        msg_id = entry["message_id"]
        if msg_id not in message_reactions:
            message_reactions[msg_id] = {
                "preview": entry["message_preview"],
                "reactions": [],
                "total_weight": 0,
            }
        message_reactions[msg_id]["reactions"].append(entry)
        message_reactions[msg_id]["total_weight"] += entry["weight"]
    
    # Messages with high correction signal
    flagged = [
        {
            "message_id": msg_id,
            "preview": data["preview"],
            "reaction_count": len(data["reactions"]),
            "total_weight": data["total_weight"],
            "reactors": [r["reactor"] for r in data["reactions"]],
        }
        for msg_id, data in message_reactions.items()
        if data["total_weight"] >= 1.5 or len(data["reactions"]) >= 2
    ]
    
    return {
        "total_negative": len(negatives),
        "total_positive": len(positives),
        "ratio": len(negatives) / max(len(positives), 1),
        "flagged_messages": sorted(flagged, key=lambda x: -x["total_weight"]),
        "needs_review": len(flagged) > 0,
    }


def get_correction_candidates() -> list:
    """
    Get messages that have accumulated enough negative reactions
    to warrant creating a correction.
    """
    analysis = analyze_reaction_patterns()
    
    # Messages with weight >= 2.0 or 3+ reactions are strong candidates
    candidates = [
        msg for msg in analysis.get("flagged_messages", [])
        if msg["total_weight"] >= 2.0 or msg["reaction_count"] >= 3
    ]
    
    return candidates


if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == "analyze":
        result = analyze_reaction_patterns()
        print(json.dumps(result, indent=2))
    elif len(sys.argv) > 1 and sys.argv[1] == "candidates":
        candidates = get_correction_candidates()
        print(json.dumps(candidates, indent=2))
    else:
        print("Usage:")
        print("  reaction_monitor.py analyze    - Analyze reaction patterns")
        print("  reaction_monitor.py candidates - Get correction candidates")
