"""Clarification Manager for handling requirement clarification and planning."""
import json
from datetime import datetime
from typing import Dict, List, Optional, Any, Set
from dataclasses import dataclass, asdict
import logging

logger = logging.getLogger(__name__)

@dataclass
class ClarificationQuestion:
    """Represents a clarification question and its context."""
    id: str
    question: str
    context: str
    category: str  # 'objective', 'scope', 'technical', 'business', 'constraint'
    priority: int
    status: str
    answer: Optional[str]
    created_at: str
    updated_at: str
    answered_at: Optional[str] = None

@dataclass
class RequirementAnalysis:
    """Represents an analysis of requirements and their clarity."""
    id: str
    requirement_id: str
    clarity_score: float
    ambiguities: List[str]
    assumptions: List[str]
    dependencies: List[str]
    risks: List[str]
    created_at: str
    updated_at: str

@dataclass
class DevelopmentPlan:
    """Represents a development plan with clear objectives and steps."""
    id: str
    title: str
    description: str
    objectives: List[str]
    success_criteria: List[str]
    constraints: List[str]
    phases: List[Dict[str, Any]]
    dependencies: List[str]
    estimated_timeline: Dict[str, Any]
    status: str
    created_at: str
    updated_at: str

class ClarificationManager:
    """Manages requirement clarification and development planning."""
    
    def __init__(self, context_manager, intelligence_manager,
                 product_manager, engineering_manager):
        """Initialize the Clarification Manager."""
        self.context_manager = context_manager
        self.intelligence_manager = intelligence_manager
        self.product_manager = product_manager
        self.engineering_manager = engineering_manager
        self.questions: Dict[str, ClarificationQuestion] = {}
        self.analyses: Dict[str, RequirementAnalysis] = {}
        self.plans: Dict[str, DevelopmentPlan] = {}
        self.load_clarification_data()

    def load_clarification_data(self):
        """Load clarification data from context database."""
        context = self.context_manager.get_project_context()
        clarification_data = context.get('clarification_data', {})
        
        # Load questions
        for q_dict in clarification_data.get('questions', []):
            question = ClarificationQuestion(**q_dict)
            self.questions[question.id] = question
            
        # Load analyses
        for a_dict in clarification_data.get('analyses', []):
            analysis = RequirementAnalysis(**a_dict)
            self.analyses[analysis.id] = analysis
            
        # Load plans
        for p_dict in clarification_data.get('plans', []):
            plan = DevelopmentPlan(**p_dict)
            self.plans[plan.id] = plan

    def save_clarification_data(self):
        """Save clarification data to context database."""
        clarification_data = {
            'questions': [asdict(q) for q in self.questions.values()],
            'analyses': [asdict(a) for a in self.analyses.values()],
            'plans': [asdict(p) for p in self.plans.values()]
        }
        
        self.context_manager.update_project_context({
            'clarification_data': clarification_data
        })

    def analyze_request(self, request: str) -> Dict[str, Any]:
        """Analyze a request for clarity and generate clarifying questions."""
        analysis = {
            'timestamp': datetime.now().isoformat(),
            'request': request,
            'clarity_analysis': self._analyze_clarity(request),
            'required_clarifications': [],
            'suggested_questions': []
        }
        
        # Check for missing objectives
        if not self._has_clear_objectives(request):
            analysis['required_clarifications'].append('objectives')
            analysis['suggested_questions'].append(
                self.create_question(
                    "What are the specific objectives or goals you want to achieve?",
                    request,
                    'objective'
                )
            )
        
        # Check for scope clarity
        if not self._has_clear_scope(request):
            analysis['required_clarifications'].append('scope')
            analysis['suggested_questions'].append(
                self.create_question(
                    "What is the scope of this request? What should be included or excluded?",
                    request,
                    'scope'
                )
            )
        
        # Check for technical constraints
        if not self._has_technical_constraints(request):
            analysis['required_clarifications'].append('technical_constraints')
            analysis['suggested_questions'].append(
                self.create_question(
                    "Are there any technical constraints or requirements we should be aware of?",
                    request,
                    'technical'
                )
            )
        
        # Check for business context
        if not self._has_business_context(request):
            analysis['required_clarifications'].append('business_context')
            analysis['suggested_questions'].append(
                self.create_question(
                    "What is the business context or value proposition for this request?",
                    request,
                    'business'
                )
            )
        
        return analysis

    def create_question(self, question: str, context: str,
                       category: str, priority: int = 1) -> ClarificationQuestion:
        """Create a new clarification question."""
        question_id = f"question_{len(self.questions) + 1}"
        now = datetime.now().isoformat()
        
        clarification = ClarificationQuestion(
            id=question_id,
            question=question,
            context=context,
            category=category,
            priority=priority,
            status="pending",
            answer=None,
            created_at=now,
            updated_at=now
        )
        
        self.questions[question_id] = clarification
        self.save_clarification_data()
        
        return clarification

    def record_answer(self, question_id: str, answer: str) -> ClarificationQuestion:
        """Record an answer to a clarification question."""
        if question_id not in self.questions:
            raise ValueError(f"Question {question_id} not found")
            
        question = self.questions[question_id]
        now = datetime.now().isoformat()
        
        question.answer = answer
        question.status = "answered"
        question.answered_at = now
        question.updated_at = now
        
        self.save_clarification_data()
        
        # Add insight about answered question
        self.context_manager.add_insight(
            f"Clarification received for {question.category}: {question.question}",
            'clarification',
            'clarification_manager'
        )
        
        return question

    def analyze_requirement(self, requirement_id: str) -> RequirementAnalysis:
        """Analyze a requirement for clarity and completeness."""
        requirement = self.product_manager.requirements[requirement_id]
        now = datetime.now().isoformat()
        
        analysis_id = f"analysis_{requirement_id}"
        
        # Analyze requirement clarity
        clarity_score = self._calculate_clarity_score(requirement)
        ambiguities = self._identify_ambiguities(requirement)
        assumptions = self._identify_assumptions(requirement)
        dependencies = self._identify_dependencies(requirement)
        risks = self._identify_risks(requirement)
        
        analysis = RequirementAnalysis(
            id=analysis_id,
            requirement_id=requirement_id,
            clarity_score=clarity_score,
            ambiguities=ambiguities,
            assumptions=assumptions,
            dependencies=dependencies,
            risks=risks,
            created_at=now,
            updated_at=now
        )
        
        self.analyses[analysis_id] = analysis
        self.save_clarification_data()
        
        return analysis

    def create_development_plan(self, title: str, description: str,
                              objectives: List[str], success_criteria: List[str],
                              constraints: List[str]) -> DevelopmentPlan:
        """Create a development plan based on clarified requirements."""
        plan_id = f"plan_{len(self.plans) + 1}"
        now = datetime.now().isoformat()
        
        # Generate phases based on objectives
        phases = self._generate_development_phases(objectives)
        
        # Identify dependencies between phases
        dependencies = self._identify_phase_dependencies(phases)
        
        # Estimate timeline
        timeline = self._estimate_timeline(phases)
        
        plan = DevelopmentPlan(
            id=plan_id,
            title=title,
            description=description,
            objectives=objectives,
            success_criteria=success_criteria,
            constraints=constraints,
            phases=phases,
            dependencies=dependencies,
            estimated_timeline=timeline,
            status="draft",
            created_at=now,
            updated_at=now
        )
        
        self.plans[plan_id] = plan
        self.save_clarification_data()
        
        # Add insight about new plan
        self.context_manager.add_insight(
            f"Created development plan: {title}",
            'planning',
            'clarification_manager'
        )
        
        return plan

    def _analyze_clarity(self, text: str) -> Dict[str, Any]:
        """Analyze text clarity and identify potential issues."""
        words = text.lower().split()
        
        analysis = {
            'length': len(words),
            'ambiguous_terms': [],
            'missing_context': [],
            'clarity_score': 0.0
        }
        
        # Check for ambiguous terms
        ambiguous_terms = {
            'it', 'this', 'that', 'these', 'those',
            'something', 'anything', 'everything',
            'soon', 'later', 'some', 'many', 'few'
        }
        
        analysis['ambiguous_terms'] = [
            word for word in words
            if word in ambiguous_terms
        ]
        
        # Check for missing context
        context_indicators = {
            'because', 'when', 'if', 'while',
            'for', 'to', 'so that', 'in order to'
        }
        
        has_context = any(
            indicator in text.lower()
            for indicator in context_indicators
        )
        
        if not has_context:
            analysis['missing_context'].append('purpose')
        
        # Calculate clarity score with weighted factors
        clarity_factors = {
            'no_ambiguous_terms': len(analysis['ambiguous_terms']) == 0,
            'has_context': has_context,
            'sufficient_length': len(words) >= 10,
            'no_missing_context': len(analysis['missing_context']) == 0
        }
        
        # Weight factors differently
        weights = {
            'no_ambiguous_terms': 0.4,
            'has_context': 0.3,
            'sufficient_length': 0.2,
            'no_missing_context': 0.1
        }
        
        # Calculate base score
        base_score = sum(
            weights[factor] for factor, value in clarity_factors.items()
            if value
        )
        
        # Apply penalties for ambiguous terms
        num_ambiguous = len(analysis['ambiguous_terms'])
        if num_ambiguous > 0:
            # Each ambiguous term reduces the score by 10%
            penalty = min(0.1 * num_ambiguous, 0.5)  # Cap penalty at 50%
            base_score *= (1 - penalty)
        
        # Apply bonuses for comprehensive text
        if len(words) >= 30:  # Bonus for detailed explanation
            base_score *= 1.2
        
        # Check for key sections in complete context
        key_sections = {
            'goal': 'goal' in text.lower() or 'objective' in text.lower(),
            'requirements': 'requirements' in text.lower() or 'must' in text.lower(),
            'value': 'value' in text.lower() or 'benefit' in text.lower()
        }
        
        # Count how many key sections are present
        num_key_sections = sum(key_sections.values())
        if num_key_sections >= 2:  # Bonus for having at least 2 key sections
            base_score *= 1.2
        if num_key_sections == 3:  # Additional bonus for having all key sections
            base_score *= 1.2
        
        # Check for specific details
        detail_indicators = {
            'metrics': any(word in text.lower() for word in ['time', 'speed', 'rate', 'percentage', 'ms']),
            'specifics': any(word in text.lower() for word in ['database', 'query', 'api', 'interface', 'function']),
            'outcomes': any(word in text.lower() for word in ['improve', 'increase', 'reduce', 'optimize'])
        }
        
        # Apply bonus for detailed specifications
        num_details = sum(detail_indicators.values())
        if num_details >= 2:
            base_score *= 1.1
        
        # Cap the final score at 1.0
        analysis['clarity_score'] = min(base_score, 1.0)
        return analysis

    def _has_clear_objectives(self, text: str) -> bool:
        """Check if text has clear objectives."""
        objective_indicators = {
            'goal', 'objective', 'aim', 'purpose',
            'achieve', 'create', 'implement', 'develop'
        }
        return any(indicator in text.lower() for indicator in objective_indicators)

    def _has_clear_scope(self, text: str) -> bool:
        """Check if text has clear scope definition."""
        scope_indicators = {
            'include', 'exclude', 'scope', 'boundary',
            'limit', 'cover', 'contain', 'involve'
        }
        return any(indicator in text.lower() for indicator in scope_indicators)

    def _has_technical_constraints(self, text: str) -> bool:
        """Check if text mentions technical constraints."""
        constraint_indicators = {
            'must', 'should', 'require', 'need',
            'compatible', 'support', 'performance',
            'security', 'scalability'
        }
        return any(indicator in text.lower() for indicator in constraint_indicators)

    def _has_business_context(self, text: str) -> bool:
        """Check if text provides business context."""
        context_indicators = {
            'business', 'user', 'customer', 'market',
            'value', 'benefit', 'roi', 'cost',
            'revenue', 'profit', 'stakeholder'
        }
        return any(indicator in text.lower() for indicator in context_indicators)

    def _calculate_clarity_score(self, requirement: Any) -> float:
        """Calculate clarity score for a requirement."""
        # Implement scoring logic
        return 0.8  # Placeholder

    def _identify_ambiguities(self, requirement: Any) -> List[str]:
        """Identify ambiguous aspects of a requirement."""
        # Implement ambiguity detection
        return []  # Placeholder

    def _identify_assumptions(self, requirement: Any) -> List[str]:
        """Identify assumptions in a requirement."""
        # Implement assumption detection
        return []  # Placeholder

    def _identify_dependencies(self, requirement: Any) -> List[str]:
        """Identify dependencies of a requirement."""
        # Implement dependency detection
        return []  # Placeholder

    def _identify_risks(self, requirement: Any) -> List[str]:
        """Identify risks associated with a requirement."""
        # Implement risk detection
        return []  # Placeholder

    def _generate_development_phases(self, objectives: List[str]) -> List[Dict[str, Any]]:
        """Generate development phases based on objectives."""
        # Implement phase generation
        return []  # Placeholder

    def _identify_phase_dependencies(self, phases: List[Dict[str, Any]]) -> List[str]:
        """Identify dependencies between development phases."""
        # Implement dependency identification
        return []  # Placeholder

    def _estimate_timeline(self, phases: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Estimate timeline for development phases."""
        # Implement timeline estimation
        return {}  # Placeholder 