"""
Mental health assessment models and tools.
"""
from datetime import datetime
from enum import Enum
from typing import Dict, List, Literal, Optional, Tuple

from pydantic import Field, validator

from essencia.fields import EncryptedStr, EncryptedInt
from essencia.models.base import BaseModel
from essencia.models.bases import MongoModel


class AssessmentType(str, Enum):
    """Types of mental health assessments."""
    
    PHQ9 = "phq9"  # Patient Health Questionnaire-9
    GAD7 = "gad7"  # Generalized Anxiety Disorder-7
    MDQ = "mdq"  # Mood Disorder Questionnaire
    ASRS = "asrs"  # Adult ADHD Self-Report Scale
    PCL5 = "pcl5"  # PTSD Checklist for DSM-5
    AUDIT = "audit"  # Alcohol Use Disorders Identification Test
    DAST10 = "dast10"  # Drug Abuse Screening Test
    ISI = "isi"  # Insomnia Severity Index
    EPDS = "epds"  # Edinburgh Postnatal Depression Scale
    YMRS = "ymrs"  # Young Mania Rating Scale
    PANSS = "panss"  # Positive and Negative Syndrome Scale
    BPRS = "bprs"  # Brief Psychiatric Rating Scale
    HAM_D = "ham_d"  # Hamilton Depression Rating Scale
    HAM_A = "ham_a"  # Hamilton Anxiety Rating Scale
    CAGE = "cage"  # CAGE Questionnaire (alcoholism)
    MINI = "mini"  # Mini International Neuropsychiatric Interview
    # Personality assessments (open source)
    IPIP50 = "ipip50"  # International Personality Item Pool (50 items)
    BFI44 = "bfi44"  # Big Five Inventory (44 items)
    # Child/Adolescent scales
    SDQ = "sdq"  # Strengths and Difficulties Questionnaire
    SCARED = "scared"  # Screen for Child Anxiety Related Disorders
    CDI = "cdi"  # Children's Depression Inventory
    SNAP_IV = "snap_iv"  # SNAP-IV ADHD Rating Scale
    CBCL = "cbcl"  # Child Behavior Checklist


class SeverityLevel(str, Enum):
    """Severity levels for assessment results."""
    
    NONE = "none"
    MINIMAL = "minimal"
    MILD = "mild"
    MODERATE = "moderate"
    MODERATELY_SEVERE = "moderately_severe"
    SEVERE = "severe"
    VERY_SEVERE = "very_severe"


class AssessmentQuestion(BaseModel):
    """Individual question in an assessment."""
    
    question_id: str
    text: str
    text_pt: str  # Portuguese translation
    category: Optional[str] = None
    options: List[Dict[str, any]]  # value, label, label_pt
    required: bool = True
    clinical_note: Optional[str] = None


class AssessmentResponse(BaseModel):
    """Response to an assessment question."""
    
    question_id: str
    value: int
    text_value: Optional[str] = None
    answered_at: datetime = Field(default_factory=datetime.utcnow)


class MentalHealthAssessment(MongoModel):
    """Base model for mental health assessments."""
    
    patient_id: str
    assessment_type: AssessmentType
    administered_by: Optional[str] = None
    administered_at: datetime = Field(default_factory=datetime.utcnow)
    
    responses: List[AssessmentResponse]
    total_score: EncryptedInt
    severity: SeverityLevel
    
    # Clinical interpretation
    clinical_notes: Optional[EncryptedStr] = None
    risk_factors: List[str] = Field(default_factory=list)
    protective_factors: List[str] = Field(default_factory=list)
    recommendations: List[str] = Field(default_factory=list)
    
    # Follow-up
    requires_immediate_attention: bool = False
    next_assessment_date: Optional[datetime] = None
    
    class Settings:
        collection_name = "mental_health_assessments"
        indexes = [
            ("patient_id", -1),
            ("assessment_type", 1),
            ("administered_at", -1),
            [("patient_id", 1), ("assessment_type", 1), ("administered_at", -1)],
        ]


class PHQ9Assessment(MentalHealthAssessment):
    """Patient Health Questionnaire-9 for depression screening."""
    
    assessment_type: Literal[AssessmentType.PHQ9] = AssessmentType.PHQ9
    
    # PHQ-9 specific fields
    suicidal_ideation: bool = Field(False, description="Question 9 > 0")
    functional_impairment: Optional[str] = None
    
    @classmethod
    def get_questions(cls) -> List[AssessmentQuestion]:
        """Get PHQ-9 questions."""
        return [
            AssessmentQuestion(
                question_id="phq9_1",
                text="Little interest or pleasure in doing things",
                text_pt="Pouco interesse ou prazer em fazer as coisas",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_2",
                text="Feeling down, depressed, or hopeless",
                text_pt="Sentir-se para baixo, deprimido ou sem esperança",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_3",
                text="Trouble falling or staying asleep, or sleeping too much",
                text_pt="Dificuldade para adormecer ou permanecer dormindo, ou dormir demais",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_4",
                text="Feeling tired or having little energy",
                text_pt="Sentir-se cansado ou com pouca energia",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_5",
                text="Poor appetite or overeating",
                text_pt="Pouco apetite ou comer demais",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_6",
                text="Feeling bad about yourself or that you are a failure",
                text_pt="Sentir-se mal consigo mesmo ou achar que é um fracasso",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_7",
                text="Trouble concentrating on things",
                text_pt="Dificuldade para se concentrar nas coisas",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_8",
                text="Moving or speaking slowly or being fidgety/restless",
                text_pt="Mover-se ou falar lentamente ou estar inquieto/agitado",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ]
            ),
            AssessmentQuestion(
                question_id="phq9_9",
                text="Thoughts that you would be better off dead or of hurting yourself",
                text_pt="Pensar que seria melhor estar morto ou em se machucar",
                options=[
                    {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
                    {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
                    {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
                    {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
                ],
                clinical_note="Positive response requires immediate clinical attention"
            )
        ]
    
    @staticmethod
    def calculate_severity(total_score: int) -> SeverityLevel:
        """Calculate PHQ-9 severity level."""
        if total_score <= 4:
            return SeverityLevel.MINIMAL
        elif total_score <= 9:
            return SeverityLevel.MILD
        elif total_score <= 14:
            return SeverityLevel.MODERATE
        elif total_score <= 19:
            return SeverityLevel.MODERATELY_SEVERE
        else:
            return SeverityLevel.SEVERE
    
    def get_clinical_interpretation(self) -> Dict[str, any]:
        """Get clinical interpretation of PHQ-9 results."""
        interpretation = {
            "severity": self.severity,
            "total_score": self.total_score,
            "suicidal_ideation": self.suicidal_ideation,
            "treatment_recommendations": []
        }
        
        if self.severity == SeverityLevel.MINIMAL:
            interpretation["treatment_recommendations"].append("No treatment needed")
            interpretation["follow_up"] = "Reassess in 1 year or if symptoms worsen"
        elif self.severity == SeverityLevel.MILD:
            interpretation["treatment_recommendations"].append("Watchful waiting")
            interpretation["treatment_recommendations"].append("Repeat PHQ-9 at follow-up")
            interpretation["follow_up"] = "Reassess in 4-6 weeks"
        elif self.severity == SeverityLevel.MODERATE:
            interpretation["treatment_recommendations"].append("Treatment plan (counseling, medication)")
            interpretation["treatment_recommendations"].append("Consider referral to mental health specialist")
            interpretation["follow_up"] = "Reassess in 2-4 weeks"
        elif self.severity in [SeverityLevel.MODERATELY_SEVERE, SeverityLevel.SEVERE]:
            interpretation["treatment_recommendations"].append("Active treatment with medication and/or psychotherapy")
            interpretation["treatment_recommendations"].append("Referral to mental health specialist")
            interpretation["follow_up"] = "Reassess in 1-2 weeks"
        
        if self.suicidal_ideation:
            interpretation["immediate_action"] = True
            interpretation["safety_plan_needed"] = True
            interpretation["treatment_recommendations"].insert(0, "Immediate safety assessment required")
        
        return interpretation


class GAD7Assessment(MentalHealthAssessment):
    """Generalized Anxiety Disorder-7 scale."""
    
    assessment_type: Literal[AssessmentType.GAD7] = AssessmentType.GAD7
    
    @classmethod
    def get_questions(cls) -> List[AssessmentQuestion]:
        """Get GAD-7 questions."""
        options = [
            {"value": 0, "label": "Not at all", "label_pt": "Nenhuma vez"},
            {"value": 1, "label": "Several days", "label_pt": "Vários dias"},
            {"value": 2, "label": "More than half the days", "label_pt": "Mais da metade dos dias"},
            {"value": 3, "label": "Nearly every day", "label_pt": "Quase todos os dias"}
        ]
        
        return [
            AssessmentQuestion(
                question_id="gad7_1",
                text="Feeling nervous, anxious, or on edge",
                text_pt="Sentir-se nervoso, ansioso ou no limite",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_2",
                text="Not being able to stop or control worrying",
                text_pt="Não conseguir parar ou controlar a preocupação",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_3",
                text="Worrying too much about different things",
                text_pt="Preocupar-se demais com diferentes coisas",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_4",
                text="Trouble relaxing",
                text_pt="Dificuldade para relaxar",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_5",
                text="Being so restless that it's hard to sit still",
                text_pt="Estar tão inquieto que é difícil ficar parado",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_6",
                text="Becoming easily annoyed or irritable",
                text_pt="Ficar facilmente aborrecido ou irritado",
                options=options
            ),
            AssessmentQuestion(
                question_id="gad7_7",
                text="Feeling afraid as if something awful might happen",
                text_pt="Sentir medo como se algo terrível pudesse acontecer",
                options=options
            )
        ]
    
    @staticmethod
    def calculate_severity(total_score: int) -> SeverityLevel:
        """Calculate GAD-7 severity level."""
        if total_score <= 4:
            return SeverityLevel.MINIMAL
        elif total_score <= 9:
            return SeverityLevel.MILD
        elif total_score <= 14:
            return SeverityLevel.MODERATE
        else:
            return SeverityLevel.SEVERE


class SNAPIV_Assessment(MentalHealthAssessment):
    """SNAP-IV ADHD Rating Scale for children/adolescents."""
    
    assessment_type: Literal[AssessmentType.SNAP_IV] = AssessmentType.SNAP_IV
    
    # SNAP-IV specific scores
    inattention_score: EncryptedInt
    hyperactivity_score: EncryptedInt
    oppositional_score: Optional[EncryptedInt] = None
    
    @classmethod
    def get_questions(cls) -> List[AssessmentQuestion]:
        """Get SNAP-IV questions."""
        options = [
            {"value": 0, "label": "Not at all", "label_pt": "Nem um pouco"},
            {"value": 1, "label": "Just a little", "label_pt": "Só um pouco"},
            {"value": 2, "label": "Quite a bit", "label_pt": "Bastante"},
            {"value": 3, "label": "Very much", "label_pt": "Demais"}
        ]
        
        questions = []
        
        # Inattention items (1-9)
        inattention_items = [
            ("Often fails to give close attention to details", 
             "Frequentemente não presta atenção em detalhes"),
            ("Often has difficulty sustaining attention", 
             "Frequentemente tem dificuldade em manter atenção"),
            ("Often does not seem to listen when spoken to directly", 
             "Frequentemente parece não escutar quando falam diretamente"),
            ("Often does not follow through on instructions", 
             "Frequentemente não segue instruções completamente"),
            ("Often has difficulty organizing tasks", 
             "Frequentemente tem dificuldade para organizar tarefas"),
            ("Often avoids tasks requiring sustained mental effort", 
             "Frequentemente evita tarefas que exigem esforço mental"),
            ("Often loses things necessary for tasks", 
             "Frequentemente perde coisas necessárias para tarefas"),
            ("Often easily distracted by extraneous stimuli", 
             "Frequentemente se distrai facilmente"),
            ("Often forgetful in daily activities", 
             "Frequentemente é esquecido nas atividades diárias")
        ]
        
        for i, (text_en, text_pt) in enumerate(inattention_items, 1):
            questions.append(AssessmentQuestion(
                question_id=f"snap_inattention_{i}",
                text=text_en,
                text_pt=text_pt,
                category="inattention",
                options=options
            ))
        
        # Hyperactivity/Impulsivity items (10-18)
        hyperactivity_items = [
            ("Often fidgets with hands/feet or squirms", 
             "Frequentemente mexe mãos/pés ou se contorce"),
            ("Often leaves seat when remaining seated is expected", 
             "Frequentemente sai do lugar quando deveria ficar sentado"),
            ("Often runs about or climbs excessively", 
             "Frequentemente corre ou sobe nas coisas excessivamente"),
            ("Often has difficulty playing quietly", 
             "Frequentemente tem dificuldade para brincar quieto"),
            ("Often 'on the go' or acts as if 'driven by a motor'", 
             "Frequentemente 'a mil' ou 'ligado na tomada'"),
            ("Often talks excessively", 
             "Frequentemente fala demais"),
            ("Often blurts out answers before questions completed", 
             "Frequentemente responde antes da pergunta terminar"),
            ("Often has difficulty awaiting turn", 
             "Frequentemente tem dificuldade para esperar sua vez"),
            ("Often interrupts or intrudes on others", 
             "Frequentemente interrompe ou se intromete")
        ]
        
        for i, (text_en, text_pt) in enumerate(hyperactivity_items, 1):
            questions.append(AssessmentQuestion(
                question_id=f"snap_hyperactivity_{i}",
                text=text_en,
                text_pt=text_pt,
                category="hyperactivity",
                options=options
            ))
        
        return questions
    
    def calculate_subscores(self) -> Dict[str, float]:
        """Calculate SNAP-IV subscale scores."""
        inattention_responses = [r for r in self.responses if "inattention" in r.question_id]
        hyperactivity_responses = [r for r in self.responses if "hyperactivity" in r.question_id]
        
        inattention_avg = sum(r.value for r in inattention_responses) / len(inattention_responses)
        hyperactivity_avg = sum(r.value for r in hyperactivity_responses) / len(hyperactivity_responses)
        
        return {
            "inattention_average": round(inattention_avg, 2),
            "hyperactivity_average": round(hyperactivity_avg, 2),
            "meets_inattention_criteria": inattention_avg >= 2.0,
            "meets_hyperactivity_criteria": hyperactivity_avg >= 2.0
        }


class AssessmentService:
    """Service for mental health assessments."""

    # Registry will be lazily initialized
    _ASSESSMENT_REGISTRY = None

    @classmethod
    def _get_registry(cls):
        """Get or initialize the assessment registry lazily."""
        if cls._ASSESSMENT_REGISTRY is None:
            cls._ASSESSMENT_REGISTRY = {
                AssessmentType.PHQ9: PHQ9Assessment,
                AssessmentType.GAD7: GAD7Assessment,
                AssessmentType.SNAP_IV: SNAPIV_Assessment,
            }
            # Try to register Big Five assessments
            try:
                cls._ASSESSMENT_REGISTRY[AssessmentType.IPIP50] = IPIP50Assessment
                cls._ASSESSMENT_REGISTRY[AssessmentType.BFI44] = BFI44Assessment
            except NameError:
                pass  # Defined later in the module
        return cls._ASSESSMENT_REGISTRY

    @classmethod
    def _register_addiction_assessments(cls):
        """Register addiction assessments dynamically to avoid circular imports."""
        try:
            from essencia.models.addiction_assessments import (
                AUDITAssessment,
                DAST10Assessment,
                CAGEAssessment
            )
            registry = cls._get_registry()
            registry.update({
                AssessmentType.AUDIT: AUDITAssessment,
                AssessmentType.DAST10: DAST10Assessment,
                AssessmentType.CAGE: CAGEAssessment,
            })
        except ImportError:
            pass  # Addiction assessments not available

    @classmethod
    def _register_bigfive_assessments(cls):
        """Register Big Five assessments after they're defined."""
        registry = cls._get_registry()
        if AssessmentType.IPIP50 not in registry:
            registry[AssessmentType.IPIP50] = IPIP50Assessment
        if AssessmentType.BFI44 not in registry:
            registry[AssessmentType.BFI44] = BFI44Assessment

    @classmethod
    def get_assessment_class(cls, assessment_type: AssessmentType):
        """Get assessment class by type."""
        registry = cls._get_registry()
        # Ensure addiction assessments are registered
        if assessment_type in [AssessmentType.AUDIT, AssessmentType.DAST10, AssessmentType.CAGE]:
            cls._register_addiction_assessments()
        # Ensure Big Five assessments are registered
        if assessment_type in [AssessmentType.IPIP50, AssessmentType.BFI44]:
            cls._register_bigfive_assessments()
        return registry.get(assessment_type, MentalHealthAssessment)
    
    @classmethod
    def create_assessment(
        cls,
        assessment_type: AssessmentType,
        patient_id: str,
        responses: List[AssessmentResponse],
        administered_by: Optional[str] = None
    ) -> MentalHealthAssessment:
        """Create a new assessment with automatic scoring."""
        assessment_class = cls.get_assessment_class(assessment_type)
        
        # Calculate total score
        total_score = sum(r.value for r in responses)
        
        # Get severity based on assessment type
        if hasattr(assessment_class, 'calculate_severity'):
            severity = assessment_class.calculate_severity(total_score)
        else:
            severity = SeverityLevel.NONE
        
        # Create assessment
        assessment = assessment_class(
            patient_id=patient_id,
            administered_by=administered_by,
            responses=responses,
            total_score=total_score,
            severity=severity
        )
        
        # Check for immediate attention flags
        if assessment_type == AssessmentType.PHQ9:
            # Check suicidal ideation (question 9)
            q9_response = next((r for r in responses if r.question_id == "phq9_9"), None)
            if q9_response and q9_response.value > 0:
                assessment.suicidal_ideation = True
                assessment.requires_immediate_attention = True
        
        return assessment
    
    @staticmethod
    async def get_assessment_history(
        patient_id: str,
        assessment_type: Optional[AssessmentType] = None,
        limit: int = 10
    ) -> List[MentalHealthAssessment]:
        """Get assessment history for a patient."""
        query = {"patient_id": patient_id}
        if assessment_type:
            query["assessment_type"] = assessment_type
        
        assessments = await MentalHealthAssessment.find_many(
            query,
            sort=[("administered_at", -1)],
            limit=limit
        )
        
        return assessments
    
    @staticmethod
    def analyze_assessment_trends(
        assessments: List[MentalHealthAssessment]
    ) -> Dict[str, any]:
        """Analyze trends in assessment scores over time."""
        if not assessments:
            return {"trend": "no_data", "assessments_count": 0}
        
        # Sort by date
        sorted_assessments = sorted(assessments, key=lambda x: x.administered_at)
        
        scores = [a.total_score for a in sorted_assessments]
        dates = [a.administered_at for a in sorted_assessments]
        
        # Calculate trend
        if len(scores) < 2:
            trend = "insufficient_data"
        else:
            # Simple linear trend
            first_half_avg = sum(scores[:len(scores)//2]) / (len(scores)//2)
            second_half_avg = sum(scores[len(scores)//2:]) / (len(scores) - len(scores)//2)
            
            if second_half_avg < first_half_avg * 0.8:
                trend = "improving"
            elif second_half_avg > first_half_avg * 1.2:
                trend = "worsening"
            else:
                trend = "stable"
        
        # Find significant changes
        significant_changes = []
        for i in range(1, len(sorted_assessments)):
            prev = sorted_assessments[i-1]
            curr = sorted_assessments[i]
            
            # Check for severity level change
            if prev.severity != curr.severity:
                significant_changes.append({
                    "date": curr.administered_at,
                    "previous_severity": prev.severity,
                    "new_severity": curr.severity,
                    "score_change": curr.total_score - prev.total_score
                })
        
        return {
            "trend": trend,
            "assessments_count": len(assessments),
            "first_score": scores[0],
            "latest_score": scores[-1],
            "average_score": sum(scores) / len(scores),
            "min_score": min(scores),
            "max_score": max(scores),
            "significant_changes": significant_changes,
            "date_range": {
                "start": dates[0],
                "end": dates[-1]
            }
        }
    
    @staticmethod
    def get_recommended_assessments(
        patient_age: int,
        presenting_concerns: List[str]
    ) -> List[AssessmentType]:
        """Get recommended assessments based on age and concerns."""
        recommendations = []
        
        # Age-based recommendations
        if patient_age < 18:
            # Child/Adolescent assessments
            if any(concern in ["adhd", "attention", "hyperactivity"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.SNAP_IV)
            
            if any(concern in ["anxiety", "worry", "fear"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.SCARED)
            
            if any(concern in ["depression", "mood", "sadness"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.CDI)
            
            # Always include SDQ for general screening
            recommendations.append(AssessmentType.SDQ)
        
        else:
            # Adult assessments
            if any(concern in ["depression", "mood", "sadness"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.PHQ9)
            
            if any(concern in ["anxiety", "worry", "panic"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.GAD7)
            
            if any(concern in ["adhd", "attention", "focus"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.ASRS)
            
            if any(concern in ["trauma", "ptsd"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.PCL5)
            
            if any(concern in ["alcohol", "drinking"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.AUDIT)
            
            if any(concern in ["sleep", "insomnia"] 
                   for concern in presenting_concerns):
                recommendations.append(AssessmentType.ISI)
        
        return list(set(recommendations))  # Remove duplicates


class PersonalityFactor(str, Enum):
    """Big Five personality factors."""
    
    NEUROTICISM = "neuroticism"
    EXTRAVERSION = "extraversion"
    OPENNESS = "openness"
    AGREEABLENESS = "agreeableness"
    CONSCIENTIOUSNESS = "conscientiousness"


class BigFiveAssessmentBase(MentalHealthAssessment):
    """Base class for Big Five personality assessments."""
    
    # Factor scores (scaled 10-50 for raw, 20-80 for T-scores)
    neuroticism_score: EncryptedInt = Field(..., ge=20, le=80)
    extraversion_score: EncryptedInt = Field(..., ge=20, le=80)
    openness_score: EncryptedInt = Field(..., ge=20, le=80)
    agreeableness_score: EncryptedInt = Field(..., ge=20, le=80)
    conscientiousness_score: EncryptedInt = Field(..., ge=20, le=80)
    
    # Raw scores for reference
    neuroticism_raw: EncryptedInt = Field(..., ge=10, le=50)
    extraversion_raw: EncryptedInt = Field(..., ge=10, le=50)
    openness_raw: EncryptedInt = Field(..., ge=10, le=50)
    agreeableness_raw: EncryptedInt = Field(..., ge=10, le=50)
    conscientiousness_raw: EncryptedInt = Field(..., ge=10, le=50)
    
    # Personality profile interpretation
    personality_profile: EncryptedStr
    clinical_considerations: Optional[EncryptedStr] = None
    
    @staticmethod
    def interpret_t_score(t_score: int) -> str:
        """Interpret T-score level."""
        if t_score >= 65:
            return "Very High"
        elif t_score >= 56:
            return "High"
        elif t_score >= 45:
            return "Average"
        elif t_score >= 35:
            return "Low"
        else:
            return "Very Low"
    
    def get_personality_profile(self) -> Dict[str, any]:
        """Generate comprehensive personality profile."""
        profile = {
            "factors": {
                "neuroticism": {
                    "t_score": self.neuroticism_score,
                    "interpretation": self.interpret_t_score(self.neuroticism_score),
                    "description": self._get_factor_description(PersonalityFactor.NEUROTICISM, self.neuroticism_score)
                },
                "extraversion": {
                    "t_score": self.extraversion_score,
                    "interpretation": self.interpret_t_score(self.extraversion_score),
                    "description": self._get_factor_description(PersonalityFactor.EXTRAVERSION, self.extraversion_score)
                },
                "openness": {
                    "t_score": self.openness_score,
                    "interpretation": self.interpret_t_score(self.openness_score),
                    "description": self._get_factor_description(PersonalityFactor.OPENNESS, self.openness_score)
                },
                "agreeableness": {
                    "t_score": self.agreeableness_score,
                    "interpretation": self.interpret_t_score(self.agreeableness_score),
                    "description": self._get_factor_description(PersonalityFactor.AGREEABLENESS, self.agreeableness_score)
                },
                "conscientiousness": {
                    "t_score": self.conscientiousness_score,
                    "interpretation": self.interpret_t_score(self.conscientiousness_score),
                    "description": self._get_factor_description(PersonalityFactor.CONSCIENTIOUSNESS, self.conscientiousness_score)
                }
            },
            "clinical_relevance": self._get_clinical_relevance(),
            "strengths": self._identify_strengths(),
            "growth_areas": self._identify_growth_areas()
        }
        
        return profile
    
    def _get_factor_description(self, factor: PersonalityFactor, t_score: int) -> str:
        """Get descriptive interpretation for a factor score."""
        level = self.interpret_t_score(t_score)
        
        descriptions = {
            PersonalityFactor.NEUROTICISM: {
                "Very High": "Tendência a experimentar emoções negativas intensas, vulnerabilidade ao estresse",
                "High": "Propensão a ansiedade e instabilidade emocional",
                "Average": "Equilíbrio emocional típico",
                "Low": "Boa estabilidade emocional e resiliência",
                "Very Low": "Excepcional estabilidade emocional, raramente perturbado"
            },
            PersonalityFactor.EXTRAVERSION: {
                "Very High": "Extremamente sociável, busca constante por estimulação",
                "High": "Energético, sociável e assertivo",
                "Average": "Equilíbrio entre sociabilidade e introspecção",
                "Low": "Preferência por solidão e atividades calmas",
                "Very Low": "Altamente introvertido, evita estimulação social"
            },
            PersonalityFactor.OPENNESS: {
                "Very High": "Altamente criativo, imaginativo e aberto a novas experiências",
                "High": "Curioso, apreciador de arte e ideias abstratas",
                "Average": "Equilíbrio entre tradição e novidade",
                "Low": "Preferência por familiaridade e praticidade",
                "Very Low": "Forte preferência por rotina e convenção"
            },
            PersonalityFactor.AGREEABLENESS: {
                "Very High": "Extremamente cooperativo e confiante",
                "High": "Empático, altruísta e cooperativo",
                "Average": "Equilíbrio entre cooperação e assertividade",
                "Low": "Cético, competitivo e direto",
                "Very Low": "Altamente antagonista e desconfiado"
            },
            PersonalityFactor.CONSCIENTIOUSNESS: {
                "Very High": "Extremamente organizado, perfeccionista",
                "High": "Disciplinado, confiável e orientado a objetivos",
                "Average": "Equilíbrio entre estrutura e flexibilidade",
                "Low": "Espontâneo, flexível com regras",
                "Very Low": "Desorganizado, impulsivo"
            }
        }
        
        return descriptions.get(factor, {}).get(level, "")
    
    def _get_clinical_relevance(self) -> List[str]:
        """Identify clinically relevant personality patterns."""
        relevance = []
        
        # High neuroticism
        if self.neuroticism_score >= 65:
            relevance.append("Alto neuroticismo: maior risco para transtornos de ansiedade e depressão")
        
        # Low extraversion + high neuroticism
        if self.extraversion_score <= 35 and self.neuroticism_score >= 56:
            relevance.append("Padrão introversão + neuroticismo: risco para isolamento social e depressão")
        
        # Low conscientiousness
        if self.conscientiousness_score <= 35:
            relevance.append("Baixa conscienciosidade: possível impacto na adesão ao tratamento")
        
        # Very low agreeableness
        if self.agreeableness_score <= 35:
            relevance.append("Baixa amabilidade: pode afetar aliança terapêutica")
        
        # High openness + low conscientiousness
        if self.openness_score >= 65 and self.conscientiousness_score <= 40:
            relevance.append("Alta abertura + baixa conscienciosidade: risco para comportamentos impulsivos")
        
        return relevance
    
    def _identify_strengths(self) -> List[str]:
        """Identify personality strengths."""
        strengths = []
        
        if self.neuroticism_score <= 40:
            strengths.append("Estabilidade emocional")
        
        if self.extraversion_score >= 56:
            strengths.append("Habilidades sociais")
        
        if self.openness_score >= 56:
            strengths.append("Criatividade e flexibilidade cognitiva")
        
        if self.agreeableness_score >= 56:
            strengths.append("Empatia e cooperação")
        
        if self.conscientiousness_score >= 56:
            strengths.append("Organização e persistência")
        
        return strengths
    
    def _identify_growth_areas(self) -> List[str]:
        """Identify areas for potential growth."""
        areas = []
        
        if self.neuroticism_score >= 65:
            areas.append("Desenvolver estratégias de regulação emocional")
        
        if self.extraversion_score <= 35:
            areas.append("Expandir rede social gradualmente")
        
        if self.openness_score <= 35:
            areas.append("Explorar novas perspectivas com segurança")
        
        if self.agreeableness_score <= 35:
            areas.append("Praticar empatia e consideração pelos outros")
        
        if self.conscientiousness_score <= 35:
            areas.append("Desenvolver rotinas e hábitos estruturados")
        
        return areas


class IPIP50Assessment(BigFiveAssessmentBase):
    """International Personality Item Pool (50 items) - Open source Big Five assessment."""
    
    assessment_type: AssessmentType = Field(default=AssessmentType.IPIP50, frozen=True)
    
    @classmethod
    def get_questions(cls) -> List[AssessmentQuestion]:
        """Get IPIP-50 questions (complete inventory - public domain)."""
        questions = []
        
        # Extraversion items
        extraversion_items = [
            ("ipip_e1", "Am the life of the party", "Sou a alma da festa", False),
            ("ipip_e2", "Don't talk a lot", "Não falo muito", True),
            ("ipip_e3", "Feel comfortable around people", "Sinto-me confortável perto de pessoas", False),
            ("ipip_e4", "Keep in the background", "Fico em segundo plano", True),
            ("ipip_e5", "Start conversations", "Inicio conversas", False),
            ("ipip_e6", "Have little to say", "Tenho pouco a dizer", True),
            ("ipip_e7", "Talk to a lot of different people at parties", "Converso com muitas pessoas diferentes em festas", False),
            ("ipip_e8", "Don't like to draw attention to myself", "Não gosto de chamar atenção para mim", True),
            ("ipip_e9", "Don't mind being the center of attention", "Não me importo de ser o centro das atenções", False),
            ("ipip_e10", "Am quiet around strangers", "Fico quieto perto de estranhos", True)
        ]
        
        # Agreeableness items
        agreeableness_items = [
            ("ipip_a1", "Feel little concern for others", "Sinto pouca preocupação pelos outros", True),
            ("ipip_a2", "Am interested in people", "Tenho interesse nas pessoas", False),
            ("ipip_a3", "Insult people", "Insulto as pessoas", True),
            ("ipip_a4", "Sympathize with others' feelings", "Simpatizo com os sentimentos dos outros", False),
            ("ipip_a5", "Am not interested in other people's problems", "Não me interesso pelos problemas dos outros", True),
            ("ipip_a6", "Have a soft heart", "Tenho um coração mole", False),
            ("ipip_a7", "Am not really interested in others", "Não estou realmente interessado nos outros", True),
            ("ipip_a8", "Take time out for others", "Dedico tempo aos outros", False),
            ("ipip_a9", "Feel others' emotions", "Sinto as emoções dos outros", False),
            ("ipip_a10", "Make people feel at ease", "Faço as pessoas se sentirem à vontade", False)
        ]
        
        # Conscientiousness items
        conscientiousness_items = [
            ("ipip_c1", "Am always prepared", "Estou sempre preparado", False),
            ("ipip_c2", "Leave my belongings around", "Deixo minhas coisas espalhadas", True),
            ("ipip_c3", "Pay attention to details", "Presto atenção aos detalhes", False),
            ("ipip_c4", "Make a mess of things", "Faço bagunça das coisas", True),
            ("ipip_c5", "Get chores done right away", "Faço as tarefas imediatamente", False),
            ("ipip_c6", "Often forget to put things back in their proper place", "Frequentemente esqueço de colocar as coisas de volta no lugar", True),
            ("ipip_c7", "Like order", "Gosto de ordem", False),
            ("ipip_c8", "Shirk my duties", "Evito minhas obrigações", True),
            ("ipip_c9", "Follow a schedule", "Sigo uma programação", False),
            ("ipip_c10", "Am exacting in my work", "Sou exigente no meu trabalho", False)
        ]
        
        # Neuroticism items
        neuroticism_items = [
            ("ipip_n1", "Get stressed out easily", "Fico estressado facilmente", False),
            ("ipip_n2", "Am relaxed most of the time", "Estou relaxado na maior parte do tempo", True),
            ("ipip_n3", "Worry about things", "Me preocupo com as coisas", False),
            ("ipip_n4", "Seldom feel blue", "Raramente me sinto triste", True),
            ("ipip_n5", "Am easily disturbed", "Sou facilmente perturbado", False),
            ("ipip_n6", "Get upset easily", "Fico chateado facilmente", False),
            ("ipip_n7", "Change my mood a lot", "Mudo de humor frequentemente", False),
            ("ipip_n8", "Have frequent mood swings", "Tenho mudanças de humor frequentes", False),
            ("ipip_n9", "Get irritated easily", "Fico irritado facilmente", False),
            ("ipip_n10", "Often feel blue", "Frequentemente me sinto triste", False)
        ]
        
        # Openness items
        openness_items = [
            ("ipip_o1", "Have a rich vocabulary", "Tenho um vocabulário rico", False),
            ("ipip_o2", "Have difficulty understanding abstract ideas", "Tenho dificuldade em entender ideias abstratas", True),
            ("ipip_o3", "Have a vivid imagination", "Tenho uma imaginação vívida", False),
            ("ipip_o4", "Am not interested in abstract ideas", "Não me interesso por ideias abstratas", True),
            ("ipip_o5", "Have excellent ideas", "Tenho ideias excelentes", False),
            ("ipip_o6", "Do not have a good imagination", "Não tenho boa imaginação", True),
            ("ipip_o7", "Am quick to understand things", "Sou rápido para entender as coisas", False),
            ("ipip_o8", "Use difficult words", "Uso palavras difíceis", False),
            ("ipip_o9", "Spend time reflecting on things", "Passo tempo refletindo sobre as coisas", False),
            ("ipip_o10", "Am full of ideas", "Estou cheio de ideias", False)
        ]
        
        # Build questions list
        options = [
            {"value": 1, "label": "Very Inaccurate", "label_pt": "Muito Impreciso"},
            {"value": 2, "label": "Moderately Inaccurate", "label_pt": "Moderadamente Impreciso"},
            {"value": 3, "label": "Neither Accurate Nor Inaccurate", "label_pt": "Nem Preciso Nem Impreciso"},
            {"value": 4, "label": "Moderately Accurate", "label_pt": "Moderadamente Preciso"},
            {"value": 5, "label": "Very Accurate", "label_pt": "Muito Preciso"}
        ]
        
        # Add all items to questions
        for category, items in [
            ("extraversion", extraversion_items),
            ("agreeableness", agreeableness_items),
            ("conscientiousness", conscientiousness_items),
            ("neuroticism", neuroticism_items),
            ("openness", openness_items)
        ]:
            for item_id, text_en, text_pt, is_reversed in items:
                questions.append(AssessmentQuestion(
                    question_id=item_id,
                    text=text_en,
                    text_pt=text_pt,
                    category=category,
                    options=options,
                    clinical_note=f"Reversed item: {is_reversed}"
                ))
        
        return questions
    
    @staticmethod
    def calculate_t_score(raw_score: int, factor: PersonalityFactor) -> int:
        """Convert IPIP-50 raw score to T-score."""
        # IPIP-50 norms (approximate)
        norms = {
            PersonalityFactor.NEUROTICISM: {"mean": 30.0, "sd": 7.5},
            PersonalityFactor.EXTRAVERSION: {"mean": 33.5, "sd": 7.0},
            PersonalityFactor.OPENNESS: {"mean": 37.5, "sd": 6.0},
            PersonalityFactor.AGREEABLENESS: {"mean": 38.0, "sd": 5.5},
            PersonalityFactor.CONSCIENTIOUSNESS: {"mean": 36.5, "sd": 6.5}
        }
        
        mean = norms[factor]["mean"]
        sd = norms[factor]["sd"]
        
        t_score = 50 + 10 * ((raw_score - mean) / sd)
        return max(20, min(80, round(t_score)))


class BFI44Assessment(BigFiveAssessmentBase):
    """Big Five Inventory (44 items) - Open source personality assessment."""
    
    assessment_type: AssessmentType = Field(default=AssessmentType.BFI44, frozen=True)
    
    @classmethod
    def get_questions(cls) -> List[AssessmentQuestion]:
        """Get BFI-44 questions (complete inventory - open for academic use)."""
        questions = []
        
        # BFI-44 items with factor mapping
        bfi_items = [
            # Extraversion
            ("bfi_1", "extraversion", "Is talkative", "É conversador(a)", False),
            ("bfi_6", "extraversion", "Is reserved", "É reservado(a)", True),
            ("bfi_11", "extraversion", "Is full of energy", "É cheio(a) de energia", False),
            ("bfi_16", "extraversion", "Generates a lot of enthusiasm", "Gera muito entusiasmo", False),
            ("bfi_21", "extraversion", "Tends to be quiet", "Tende a ser quieto(a)", True),
            ("bfi_26", "extraversion", "Has an assertive personality", "Tem personalidade assertiva", False),
            ("bfi_31", "extraversion", "Is sometimes shy, inhibited", "Às vezes é tímido(a), inibido(a)", True),
            ("bfi_36", "extraversion", "Is outgoing, sociable", "É extrovertido(a), sociável", False),
            
            # Agreeableness
            ("bfi_2", "agreeableness", "Tends to find fault with others", "Tende a encontrar defeitos nos outros", True),
            ("bfi_7", "agreeableness", "Is helpful and unselfish with others", "É prestativo(a) e altruísta com os outros", False),
            ("bfi_12", "agreeableness", "Starts quarrels with others", "Começa brigas com os outros", True),
            ("bfi_17", "agreeableness", "Has a forgiving nature", "Tem natureza perdoadora", False),
            ("bfi_22", "agreeableness", "Is generally trusting", "É geralmente confiante", False),
            ("bfi_27", "agreeableness", "Can be cold and aloof", "Pode ser frio(a) e distante", True),
            ("bfi_32", "agreeableness", "Is considerate and kind to almost everyone", "É considerado(a) e gentil com quase todos", False),
            ("bfi_37", "agreeableness", "Is sometimes rude to others", "Às vezes é rude com os outros", True),
            ("bfi_42", "agreeableness", "Likes to cooperate with others", "Gosta de cooperar com os outros", False),
            
            # Conscientiousness
            ("bfi_3", "conscientiousness", "Does a thorough job", "Faz um trabalho completo", False),
            ("bfi_8", "conscientiousness", "Can be somewhat careless", "Pode ser um pouco descuidado(a)", True),
            ("bfi_13", "conscientiousness", "Is a reliable worker", "É um(a) trabalhador(a) confiável", False),
            ("bfi_18", "conscientiousness", "Tends to be disorganized", "Tende a ser desorganizado(a)", True),
            ("bfi_23", "conscientiousness", "Tends to be lazy", "Tende a ser preguiçoso(a)", True),
            ("bfi_28", "conscientiousness", "Perseveres until the task is finished", "Persevera até terminar a tarefa", False),
            ("bfi_33", "conscientiousness", "Does things efficiently", "Faz as coisas eficientemente", False),
            ("bfi_38", "conscientiousness", "Makes plans and follows through with them", "Faz planos e os segue", False),
            ("bfi_43", "conscientiousness", "Is easily distracted", "Se distrai facilmente", True),
            
            # Neuroticism
            ("bfi_4", "neuroticism", "Is depressed, blue", "É deprimido(a), triste", False),
            ("bfi_9", "neuroticism", "Is relaxed, handles stress well", "É relaxado(a), lida bem com estresse", True),
            ("bfi_14", "neuroticism", "Can be tense", "Pode ser tenso(a)", False),
            ("bfi_19", "neuroticism", "Worries a lot", "Se preocupa muito", False),
            ("bfi_24", "neuroticism", "Is emotionally stable, not easily upset", "É emocionalmente estável, não se aborrece facilmente", True),
            ("bfi_29", "neuroticism", "Can be moody", "Pode ser temperamental", False),
            ("bfi_34", "neuroticism", "Remains calm in tense situations", "Permanece calmo(a) em situações tensas", True),
            ("bfi_39", "neuroticism", "Gets nervous easily", "Fica nervoso(a) facilmente", False),
            
            # Openness
            ("bfi_5", "openness", "Is original, comes up with new ideas", "É original, tem novas ideias", False),
            ("bfi_10", "openness", "Is curious about many different things", "É curioso(a) sobre muitas coisas diferentes", False),
            ("bfi_15", "openness", "Is ingenious, a deep thinker", "É engenhoso(a), um(a) pensador(a) profundo(a)", False),
            ("bfi_20", "openness", "Has an active imagination", "Tem imaginação ativa", False),
            ("bfi_25", "openness", "Is inventive", "É inventivo(a)", False),
            ("bfi_30", "openness", "Values artistic, aesthetic experiences", "Valoriza experiências artísticas, estéticas", False),
            ("bfi_35", "openness", "Prefers work that is routine", "Prefere trabalho rotineiro", True),
            ("bfi_40", "openness", "Likes to reflect, play with ideas", "Gosta de refletir, brincar com ideias", False),
            ("bfi_41", "openness", "Has few artistic interests", "Tem poucos interesses artísticos", True),
            ("bfi_44", "openness", "Is sophisticated in art, music, or literature", "É sofisticado(a) em arte, música ou literatura", False)
        ]
        
        # Build questions with BFI scale
        options = [
            {"value": 1, "label": "Disagree strongly", "label_pt": "Discordo totalmente"},
            {"value": 2, "label": "Disagree a little", "label_pt": "Discordo um pouco"},
            {"value": 3, "label": "Neither agree nor disagree", "label_pt": "Nem concordo nem discordo"},
            {"value": 4, "label": "Agree a little", "label_pt": "Concordo um pouco"},
            {"value": 5, "label": "Agree strongly", "label_pt": "Concordo totalmente"}
        ]
        
        for item_id, category, text_en, text_pt, is_reversed in bfi_items:
            questions.append(AssessmentQuestion(
                question_id=item_id,
                text=f"I see myself as someone who {text_en.lower()}",
                text_pt=f"Eu me vejo como alguém que {text_pt.lower()}",
                category=category,
                options=options,
                clinical_note=f"Reversed item: {is_reversed}"
            ))
        
        return questions
    
    @staticmethod
    def calculate_t_score(raw_score: int, factor: PersonalityFactor) -> int:
        """Convert BFI-44 raw score to T-score."""
        # BFI-44 norms based on validation studies
        norms = {
            PersonalityFactor.NEUROTICISM: {"mean": 23.9, "sd": 6.1},
            PersonalityFactor.EXTRAVERSION: {"mean": 26.3, "sd": 6.4},
            PersonalityFactor.OPENNESS: {"mean": 35.9, "sd": 6.8},
            PersonalityFactor.AGREEABLENESS: {"mean": 33.6, "sd": 5.4},
            PersonalityFactor.CONSCIENTIOUSNESS: {"mean": 33.8, "sd": 5.9}
        }
        
        mean = norms[factor]["mean"]
        sd = norms[factor]["sd"]
        
        t_score = 50 + 10 * ((raw_score - mean) / sd)
        return max(20, min(80, round(t_score)))