# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
# progressTracker.py
# Progress tracking for adaptive Dynamic mode

import logging
from typing import Dict, Any, List
from datetime import datetime, timezone

logger = logging.getLogger(__name__)

class ProgressTracker:
    """Tracks what has been accomplished and what's still needed"""
    
    def __init__(self):
        self.completedObjectives = []
        self.partialAchievements = []
        self.failedAttempts = []
        self.learningInsights = []
        self.currentPhase = "plan"
    
    def updateOperation(self, result: Any, validation: Dict[str, Any], taskIntent: Dict[str, Any]):
        """Updates progress tracking based on action result - tracks per TASK, not workflow"""
        try:
            schemaCompliant = validation.get('schemaCompliant', True)
            overallSuccess = validation.get('overallSuccess', None)
            qualityScore = validation.get('qualityScore', None)
            improvementSuggestions = validation.get('improvementSuggestions', [])
            
            # Get task objective from taskIntent (task-level, not workflow-level)
            # Fallback to 'Unknown' if task objective not available
            taskObjective = taskIntent.get('taskObjective', 'Unknown')
            
            # If validation is not schema compliant, treat as indeterminate (do not count as failure)
            if not schemaCompliant or overallSuccess is None or qualityScore is None:
                self.partialAchievements.append({
                    "objective": taskObjective,
                    "partialAchievement": "Validation indeterminate (schema non-compliant or missing fields)",
                    "missingFields": validation.get('missingFields', []),
                    "timestamp": datetime.now(timezone.utc).timestamp()
                })
                self.currentPhase = "partial"
                logger.info(f"Indeterminate validation (no penalty): {taskObjective}")
            elif overallSuccess and qualityScore > 0.7:
                # Successful completion
                self.completedObjectives.append({
                    "objective": taskObjective,
                    "achievement": f"Quality score: {qualityScore:.2f}",
                    "qualityScore": qualityScore,
                    "timestamp": datetime.now(timezone.utc).timestamp()
                })
                self.currentPhase = "completed"
                logger.info(f"Task objective completed: {taskObjective}")
                
            elif qualityScore > 0.3:
                # Partial achievement
                self.partialAchievements.append({
                    "objective": taskObjective,
                    "partialAchievement": f"Quality score: {qualityScore:.2f}",
                    "missingParts": improvementSuggestions,
                    "timestamp": datetime.now(timezone.utc).timestamp()
                })
                self.currentPhase = "partial"
                logger.info(f"Partial achievement: {taskObjective}")
                
            else:
                # Failed attempt
                self.failedAttempts.append({
                    "objective": taskObjective,
                    "failureReason": f"Quality score: {qualityScore:.2f}",
                    "learningOpportunity": improvementSuggestions,
                    "timestamp": datetime.now(timezone.utc).timestamp()
                })
                self.currentPhase = "failed"
                logger.info(f"Failed attempt: {taskObjective}")
            
            # Extract learning insights
            if improvementSuggestions:
                for suggestion in improvementSuggestions:
                    if suggestion not in self.learningInsights:
                        self.learningInsights.append(suggestion)
            
        except Exception as e:
            logger.error(f"Error updating progress: {str(e)}")
    
    def getCurrentProgress(self) -> Dict[str, Any]:
        """Gets current progress state"""
        return {
            "completedObjectives": self.completedObjectives,
            "partialAchievements": self.partialAchievements,
            "failedAttempts": self.failedAttempts,
            "learningInsights": self.learningInsights,
            "currentPhase": self.currentPhase,
            "nextActionsSuggested": self._getNextActionSuggestions()
        }
    
    def shouldContinue(self, progress: Dict[str, Any], validation: Dict[str, Any]) -> bool:
        """Determines if the task should continue"""
        try:
            # If we have completed objectives, don't continue
            if progress.get('completedObjectives'):
                return False
            
            # If we have too many failed attempts, don't continue
            if len(progress.get('failedAttempts', [])) >= 3:
                return False
            
            # If validation shows success, don't continue
            if validation.get('schemaCompliant', True) and validation.get('overallSuccess', False):
                return False
            
            # If validation is not schema compliant, allow one refinement pass without counting as failure
            if not validation.get('schemaCompliant', True):
                return True

            # Otherwise, continue
            return True
            
        except Exception as e:
            logger.error(f"Error checking if should continue: {str(e)}")
            return True  # Default to continue on error
    
    def _getNextActionSuggestions(self) -> List[str]:
        """Suggests next actions based on progress"""
        suggestions = []
        
        # If we have failed attempts, suggest avoiding those actions
        if self.failedAttempts:
            suggestions.append("Avoid actions that have failed before")
        
        # If we have partial achievements, suggest building on them
        if self.partialAchievements:
            suggestions.append("Build on partial achievements")
        
        # If we have learning insights, suggest applying them
        if self.learningInsights:
            suggestions.extend(self.learningInsights[:3])  # Top 3 insights
        
        # Default suggestions
        if not suggestions:
            suggestions.append("Try a different approach")
            suggestions.append("Focus on user intent")
        
        return suggestions
    
    def getProgressSummary(self) -> Dict[str, Any]:
        """Gets a summary of progress"""
        return {
            "totalCompleted": len(self.completedObjectives),
            "totalPartial": len(self.partialAchievements),
            "totalFailed": len(self.failedAttempts),
            "totalInsights": len(self.learningInsights),
            "currentPhase": self.currentPhase,
            "successRate": len(self.completedObjectives) / max(len(self.completedObjectives) + len(self.failedAttempts), 1)
        }
    
    def reset(self):
        """Resets progress tracking"""
        self.completedObjectives = []
        self.partialAchievements = []
        self.failedAttempts = []
        self.learningInsights = []
        self.currentPhase = "plan"
