import os
import logging
from typing import List, Tuple, Dict, Any, Optional
from sqlalchemy.orm import Session
from app.db import models

class SafetyGuard:
    """Handles loop detection, cancellation checks, and task watchdogs."""
    
    def __init__(self, db: Optional[Session] = None, session_id: Optional[int] = None):
        self.db = db
        self.session_id = session_id
        self.action_history: List[Tuple] = []

    def check_cancellation(self) -> bool:
        """Returns True if user has requested cancellation."""
        if not self.db or not self.session_id:
            return False
        try:
            # Fresh query to bypass stale cache
            session = self.db.query(models.Session).filter(models.Session.id == self.session_id).first()
            if session:
                self.db.refresh(session)
                return session.is_cancelled
        except Exception as e:
            logging.warning(f"[SafetyGuard] Cancellation check failed: {e}")
        return False

    def detect_loop(self, tool_calls: List[Any]) -> bool:
        """Returns True if the exact same tool set repeats 3 times sequentially."""
        sigs = []
        for tc in tool_calls:
            tc_func = tc.get("function", {}) if isinstance(tc, dict) else getattr(tc, "function", None)
            name = tc_func.get("name") if isinstance(tc_func, dict) else getattr(tc_func, "name", "")
            args = tc_func.get("arguments") if isinstance(tc_func, dict) else getattr(tc_func, "arguments", "")
            sigs.append((name, args))
            
        current_sig = tuple(sorted(sigs))
        self.action_history.append(current_sig)
        if len(self.action_history) > 10:
            self.action_history.pop(0)
            
        return self.action_history.count(current_sig) >= 3

    def should_activate_watchdog(self, assistant: Any, sync_workspace_id: str) -> bool:
        """Checks if .ai_todo.md has unchecked items."""
        if not assistant or not assistant.mirror or not sync_workspace_id:
            return False
        try:
            workspace = assistant.mirror.get_workspace_path(sync_workspace_id)
            todo_path = os.path.join(workspace, ".ai_todo.md")
            if os.path.exists(todo_path):
                with open(todo_path, "r") as f:
                    content = f.read()
                    return "[ ]" in content
        except Exception as e:
            logging.warning(f"[SafetyGuard] Watchdog error: {e}")
        return False
