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."""
        current_sig = tuple(sorted([(tc.function.name, tc.function.arguments) for tc in tool_calls]))
        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
