"""
QUALITY-FIRST Step 4 Persona Generation Routes
Prioritizes persona quality over cost optimization.
Uses multiple specialized API calls for maximum quality and accuracy.
"""

import asyncio
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, HTTPException, Depends, BackgroundTasks
from pydantic import BaseModel
from loguru import logger

from services.persona.core_persona.core_persona_service import CorePersonaService
from services.persona.enhanced_linguistic_analyzer import EnhancedLinguisticAnalyzer
from services.persona.persona_quality_improver import PersonaQualityImprover
from middleware.auth_middleware import get_current_user

router = APIRouter()

# Initialize services
core_persona_service = CorePersonaService()
linguistic_analyzer = EnhancedLinguisticAnalyzer()  # Will fail if spaCy not available
quality_improver = PersonaQualityImprover()

class QualityFirstPersonaRequest(BaseModel):
    """Quality-first request model for persona generation."""
    onboarding_data: Dict[str, Any]
    selected_platforms: List[str] = ["linkedin", "blog"]
    user_preferences: Optional[Dict[str, Any]] = None
    quality_threshold: float = 85.0  # Minimum quality score required

class QualityFirstPersonaResponse(BaseModel):
    """Quality-first response model for persona generation."""
    success: bool
    core_persona: Optional[Dict[str, Any]] = None
    platform_personas: Optional[Dict[str, Any]] = None
    quality_metrics: Optional[Dict[str, Any]] = None
    linguistic_analysis: Optional[Dict[str, Any]] = None
    api_call_count: Optional[int] = None
    execution_time_ms: Optional[int] = None
    quality_validation_passed: Optional[bool] = None
    error: Optional[str] = None

@router.post("/step4/generate-personas-quality-first", response_model=QualityFirstPersonaResponse)
async def generate_writing_personas_quality_first(
    request: QualityFirstPersonaRequest,
    current_user: Dict[str, Any] = Depends(get_current_user)
):
    """
    QUALITY-FIRST persona generation with multiple specialized API calls for maximum quality.
    
    QUALITY-FIRST APPROACH:
    1. Enhanced linguistic analysis (spaCy required)
    2. Core persona generation with detailed prompts
    3. Individual platform adaptations (specialized for each platform)
    4. Comprehensive quality assessment using AI
    5. Quality validation and improvement if needed
    
    Total API calls: 1 (core) + N (platforms) + 1 (quality) = N + 2 calls
    Quality priority: MAXIMUM (no compromises)
    """
    import time
    start_time = time.time()
    api_call_count = 0
    quality_validation_passed = False
    
    try:
        logger.info(f"🎯 Starting QUALITY-FIRST persona generation for user: {current_user.get('user_id', 'unknown')}")
        logger.info(f"📋 Selected platforms: {request.selected_platforms}")
        logger.info(f"🎖️ Quality threshold: {request.quality_threshold}%")
        
        # Step 1: Enhanced linguistic analysis (REQUIRED for quality)
        logger.info("Step 1: Enhanced linguistic analysis...")
        text_samples = extract_text_samples_for_analysis(request.onboarding_data)
        if text_samples:
            linguistic_analysis = await asyncio.get_event_loop().run_in_executor(
                None,
                linguistic_analyzer.analyze_writing_style,
                text_samples
            )
            logger.info("✅ Enhanced linguistic analysis completed")
        else:
            logger.warning("⚠️ No text samples found for linguistic analysis")
            linguistic_analysis = {}
        
        # Step 2: Generate core persona with enhanced analysis
        logger.info("Step 2: Generating core persona with enhanced linguistic insights...")
        enhanced_onboarding_data = request.onboarding_data.copy()
        enhanced_onboarding_data['linguistic_analysis'] = linguistic_analysis
        
        core_persona = await asyncio.get_event_loop().run_in_executor(
            None, 
            core_persona_service.generate_core_persona, 
            enhanced_onboarding_data
        )
        api_call_count += 1
        
        if "error" in core_persona:
            raise Exception(f"Core persona generation failed: {core_persona['error']}")
        
        logger.info("✅ Core persona generated successfully")
        
        # Step 3: Generate individual platform adaptations (specialized for each platform)
        logger.info(f"Step 3: Generating specialized platform adaptations for: {request.selected_platforms}")
        platform_tasks = []
        
        for platform in request.selected_platforms:
            task = asyncio.create_task(
                generate_specialized_platform_persona_async(
                    core_persona, 
                    platform, 
                    enhanced_onboarding_data,
                    linguistic_analysis
                )
            )
            platform_tasks.append((platform, task))
        
        # Wait for all platform personas to complete
        platform_results = await asyncio.gather(
            *[task for _, task in platform_tasks],
            return_exceptions=True
        )
        
        # Process platform results
        platform_personas = {}
        for i, (platform, task) in enumerate(platform_tasks):
            result = platform_results[i]
            if isinstance(result, Exception):
                logger.error(f"❌ Platform {platform} generation failed: {str(result)}")
                raise Exception(f"Platform {platform} generation failed: {str(result)}")
            elif "error" in result:
                logger.error(f"❌ Platform {platform} generation failed: {result['error']}")
                raise Exception(f"Platform {platform} generation failed: {result['error']}")
            else:
                platform_personas[platform] = result
                api_call_count += 1
        
        logger.info(f"✅ Platform adaptations generated for {len(platform_personas)} platforms")
        
        # Step 4: Comprehensive AI-based quality assessment
        logger.info("Step 4: Comprehensive AI-based quality assessment...")
        quality_metrics = await assess_persona_quality_ai_based(
            core_persona, 
            platform_personas,
            linguistic_analysis,
            request.user_preferences
        )
        api_call_count += 1
        
        # Step 5: Quality validation
        logger.info("Step 5: Quality validation...")
        overall_quality = quality_metrics.get('overall_score', 0)
        
        if overall_quality >= request.quality_threshold:
            quality_validation_passed = True
            logger.info(f"✅ Quality validation PASSED: {overall_quality}% >= {request.quality_threshold}%")
        else:
            logger.warning(f"⚠️ Quality validation FAILED: {overall_quality}% < {request.quality_threshold}%")
            
            # Attempt quality improvement
            logger.info("🔄 Attempting quality improvement...")
            improved_personas = await attempt_quality_improvement(
                core_persona,
                platform_personas,
                quality_metrics,
                request.quality_threshold
            )
            
            if improved_personas:
                core_persona = improved_personas.get('core_persona', core_persona)
                platform_personas = improved_personas.get('platform_personas', platform_personas)
                
                # Re-assess quality after improvement
                quality_metrics = await assess_persona_quality_ai_based(
                    core_persona, 
                    platform_personas,
                    linguistic_analysis,
                    request.user_preferences
                )
                api_call_count += 1
                
                final_quality = quality_metrics.get('overall_score', 0)
                if final_quality >= request.quality_threshold:
                    quality_validation_passed = True
                    logger.info(f"✅ Quality improvement SUCCESSFUL: {final_quality}% >= {request.quality_threshold}%")
                else:
                    logger.warning(f"⚠️ Quality improvement INSUFFICIENT: {final_quality}% < {request.quality_threshold}%")
            else:
                logger.error("❌ Quality improvement failed")
        
        execution_time_ms = int((time.time() - start_time) * 1000)
        
        # Log quality-first performance metrics
        total_platforms = len(request.selected_platforms)
        successful_platforms = len([p for p in platform_personas.values() if "error" not in p])
        logger.info(f"🎯 QUALITY-FIRST persona generation completed in {execution_time_ms}ms")
        logger.info(f"📊 API calls made: {api_call_count} (quality-focused approach)")
        logger.info(f"🎖️ Final quality score: {quality_metrics.get('overall_score', 0)}%")
        logger.info(f"✅ Quality validation: {'PASSED' if quality_validation_passed else 'FAILED'}")
        logger.info(f"🎯 Success rate: {successful_platforms}/{total_platforms} platforms successful")
        
        return QualityFirstPersonaResponse(
            success=True,
            core_persona=core_persona,
            platform_personas=platform_personas,
            quality_metrics=quality_metrics,
            linguistic_analysis=linguistic_analysis,
            api_call_count=api_call_count,
            execution_time_ms=execution_time_ms,
            quality_validation_passed=quality_validation_passed
        )
        
    except Exception as e:
        execution_time_ms = int((time.time() - start_time) * 1000)
        logger.error(f"❌ Quality-first persona generation error: {str(e)}")
        return QualityFirstPersonaResponse(
            success=False,
            api_call_count=api_call_count,
            execution_time_ms=execution_time_ms,
            quality_validation_passed=False,
            error=f"Quality-first persona generation failed: {str(e)}"
        )

async def generate_specialized_platform_persona_async(
    core_persona: Dict[str, Any],
    platform: str,
    onboarding_data: Dict[str, Any],
    linguistic_analysis: Dict[str, Any]
) -> Dict[str, Any]:
    """
    Generate specialized platform persona with enhanced context.
    """
    try:
        # Add linguistic analysis to onboarding data for platform-specific generation
        enhanced_data = onboarding_data.copy()
        enhanced_data['linguistic_analysis'] = linguistic_analysis
        
        return await asyncio.get_event_loop().run_in_executor(
            None,
            core_persona_service._generate_single_platform_persona,
            core_persona,
            platform,
            enhanced_data
        )
    except Exception as e:
        logger.error(f"Error generating specialized {platform} persona: {str(e)}")
        return {"error": f"Failed to generate specialized {platform} persona: {str(e)}"}

async def assess_persona_quality_ai_based(
    core_persona: Dict[str, Any],
    platform_personas: Dict[str, Any],
    linguistic_analysis: Dict[str, Any],
    user_preferences: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
    """
    AI-based quality assessment using the persona quality improver.
    """
    try:
        # Use the actual PersonaQualityImprover for AI-based assessment
        assessment_result = await asyncio.get_event_loop().run_in_executor(
            None,
            quality_improver.assess_persona_quality_comprehensive,
            core_persona,
            platform_personas,
            linguistic_analysis,
            user_preferences
        )
        
        return assessment_result
        
    except Exception as e:
        logger.error(f"AI-based quality assessment error: {str(e)}")
        # Fallback to enhanced rule-based assessment
        return await assess_persona_quality_enhanced_rule_based(
            core_persona, platform_personas, linguistic_analysis
        )

async def assess_persona_quality_enhanced_rule_based(
    core_persona: Dict[str, Any],
    platform_personas: Dict[str, Any],
    linguistic_analysis: Dict[str, Any]
) -> Dict[str, Any]:
    """
    Enhanced rule-based quality assessment with linguistic analysis.
    """
    try:
        # Calculate quality scores with linguistic insights
        core_completeness = calculate_enhanced_completeness_score(core_persona, linguistic_analysis)
        platform_consistency = calculate_enhanced_consistency_score(core_persona, platform_personas, linguistic_analysis)
        platform_optimization = calculate_enhanced_platform_optimization_score(platform_personas, linguistic_analysis)
        linguistic_quality = calculate_linguistic_quality_score(linguistic_analysis)
        
        # Weighted overall score (linguistic quality is important)
        overall_score = int((
            core_completeness * 0.25 +
            platform_consistency * 0.25 +
            platform_optimization * 0.25 +
            linguistic_quality * 0.25
        ))
        
        # Generate enhanced recommendations
        recommendations = generate_enhanced_quality_recommendations(
            core_completeness, platform_consistency, platform_optimization, linguistic_quality, linguistic_analysis
        )
        
        return {
            "overall_score": overall_score,
            "core_completeness": core_completeness,
            "platform_consistency": platform_consistency,
            "platform_optimization": platform_optimization,
            "linguistic_quality": linguistic_quality,
            "recommendations": recommendations,
            "assessment_method": "enhanced_rule_based",
            "linguistic_insights": linguistic_analysis
        }
        
    except Exception as e:
        logger.error(f"Enhanced rule-based quality assessment error: {str(e)}")
        return {
            "overall_score": 70,
            "core_completeness": 70,
            "platform_consistency": 70,
            "platform_optimization": 70,
            "linguistic_quality": 70,
            "recommendations": ["Quality assessment completed with default metrics"],
            "error": str(e)
        }

def calculate_enhanced_completeness_score(core_persona: Dict[str, Any], linguistic_analysis: Dict[str, Any]) -> int:
    """Calculate enhanced completeness score with linguistic insights."""
    required_fields = ['writing_style', 'content_characteristics', 'brand_voice', 'target_audience']
    present_fields = sum(1 for field in required_fields if field in core_persona and core_persona[field])
    base_score = int((present_fields / len(required_fields)) * 100)
    
    # Boost score if linguistic analysis is available and comprehensive
    if linguistic_analysis and linguistic_analysis.get('analysis_completeness', 0) > 0.8:
        base_score = min(base_score + 10, 100)
    
    return base_score

def calculate_enhanced_consistency_score(
    core_persona: Dict[str, Any], 
    platform_personas: Dict[str, Any], 
    linguistic_analysis: Dict[str, Any]
) -> int:
    """Calculate enhanced consistency score with linguistic insights."""
    if not platform_personas:
        return 50
    
    # Check if brand voice elements are consistent across platforms
    core_voice = core_persona.get('brand_voice', {}).get('keywords', [])
    consistency_scores = []
    
    for platform, persona in platform_personas.items():
        if 'error' not in persona:
            platform_voice = persona.get('brand_voice', {}).get('keywords', [])
            # Enhanced consistency check with linguistic analysis
            overlap = len(set(core_voice) & set(platform_voice))
            consistency_score = min(overlap * 10, 100)
            
            # Boost if linguistic analysis shows good style consistency
            if linguistic_analysis and linguistic_analysis.get('style_consistency', 0) > 0.8:
                consistency_score = min(consistency_score + 5, 100)
            
            consistency_scores.append(consistency_score)
    
    return int(sum(consistency_scores) / len(consistency_scores)) if consistency_scores else 75

def calculate_enhanced_platform_optimization_score(
    platform_personas: Dict[str, Any], 
    linguistic_analysis: Dict[str, Any]
) -> int:
    """Calculate enhanced platform optimization score."""
    if not platform_personas:
        return 50
    
    optimization_scores = []
    for platform, persona in platform_personas.items():
        if 'error' not in persona:
            # Check for platform-specific optimizations
            has_optimizations = any(key in persona for key in [
                'platform_optimizations', 'content_guidelines', 'engagement_strategies'
            ])
            base_score = 90 if has_optimizations else 60
            
            # Boost if linguistic analysis shows good adaptation potential
            if linguistic_analysis and linguistic_analysis.get('adaptation_potential', 0) > 0.8:
                base_score = min(base_score + 10, 100)
            
            optimization_scores.append(base_score)
    
    return int(sum(optimization_scores) / len(optimization_scores)) if optimization_scores else 75

def calculate_linguistic_quality_score(linguistic_analysis: Dict[str, Any]) -> int:
    """Calculate linguistic quality score from enhanced analysis."""
    if not linguistic_analysis:
        return 50
    
    # Score based on linguistic analysis completeness and quality indicators
    completeness = linguistic_analysis.get('analysis_completeness', 0.5)
    style_consistency = linguistic_analysis.get('style_consistency', 0.5)
    vocabulary_sophistication = linguistic_analysis.get('vocabulary_sophistication', 0.5)
    
    return int((completeness + style_consistency + vocabulary_sophistication) / 3 * 100)

def generate_enhanced_quality_recommendations(
    core_completeness: int,
    platform_consistency: int,
    platform_optimization: int,
    linguistic_quality: int,
    linguistic_analysis: Dict[str, Any]
) -> List[str]:
    """Generate enhanced quality recommendations with linguistic insights."""
    recommendations = []
    
    if core_completeness < 85:
        recommendations.append("Enhance core persona completeness with more detailed writing style characteristics")
    
    if platform_consistency < 80:
        recommendations.append("Improve brand voice consistency across platform adaptations")
    
    if platform_optimization < 85:
        recommendations.append("Strengthen platform-specific optimizations for better engagement")
    
    if linguistic_quality < 80:
        recommendations.append("Improve linguistic quality and writing style sophistication")
    
    # Add linguistic-specific recommendations
    if linguistic_analysis:
        if linguistic_analysis.get('style_consistency', 0) < 0.7:
            recommendations.append("Enhance writing style consistency across content samples")
        
        if linguistic_analysis.get('vocabulary_sophistication', 0) < 0.7:
            recommendations.append("Increase vocabulary sophistication for better engagement")
    
    if not recommendations:
        recommendations.append("Your personas show excellent quality across all metrics!")
    
    return recommendations

async def attempt_quality_improvement(
    core_persona: Dict[str, Any],
    platform_personas: Dict[str, Any],
    quality_metrics: Dict[str, Any],
    quality_threshold: float
) -> Optional[Dict[str, Any]]:
    """
    Attempt to improve persona quality if it doesn't meet the threshold.
    """
    try:
        logger.info("🔄 Attempting persona quality improvement...")
        
        # Use PersonaQualityImprover for actual improvement
        improvement_result = await asyncio.get_event_loop().run_in_executor(
            None,
            quality_improver.improve_persona_quality,
            core_persona,
            platform_personas,
            quality_metrics
        )
        
        if improvement_result and "error" not in improvement_result:
            logger.info("✅ Persona quality improvement successful")
            return improvement_result
        else:
            logger.warning("⚠️ Persona quality improvement failed or no improvement needed")
            return None
            
    except Exception as e:
        logger.error(f"❌ Error during quality improvement: {str(e)}")
        return None

def extract_text_samples_for_analysis(onboarding_data: Dict[str, Any]) -> List[str]:
    """Extract comprehensive text samples for linguistic analysis."""
    text_samples = []
    
    # Extract from website analysis
    website_analysis = onboarding_data.get('websiteAnalysis', {})
    if isinstance(website_analysis, dict):
        for key, value in website_analysis.items():
            if isinstance(value, str) and len(value) > 50:
                text_samples.append(value)
            elif isinstance(value, list):
                for item in value:
                    if isinstance(item, str) and len(item) > 50:
                        text_samples.append(item)
    
    # Extract from competitor research
    competitor_research = onboarding_data.get('competitorResearch', {})
    if isinstance(competitor_research, dict):
        competitors = competitor_research.get('competitors', [])
        for competitor in competitors:
            if isinstance(competitor, dict):
                summary = competitor.get('summary', '')
                if isinstance(summary, str) and len(summary) > 50:
                    text_samples.append(summary)
    
    # Extract from sitemap analysis
    sitemap_analysis = onboarding_data.get('sitemapAnalysis', {})
    if isinstance(sitemap_analysis, dict):
        for key, value in sitemap_analysis.items():
            if isinstance(value, str) and len(value) > 50:
                text_samples.append(value)
    
    logger.info(f"📝 Extracted {len(text_samples)} text samples for linguistic analysis")
    return text_samples
