"""
AI Engine utility functions
"""
from typing import Optional

from django.contrib.contenttypes.models import ContentType

from .models import SentimentResult


def get_sentiment_badge_class(sentiment: str) -> str:
    """
    Get Bootstrap badge class for sentiment.
    
    Args:
        sentiment: Sentiment value ('positive', 'neutral', 'negative')
    
    Returns:
        Bootstrap badge class
    """
    badge_classes = {
        'positive': 'bg-success',
        'neutral': 'bg-secondary',
        'negative': 'bg-danger',
    }
    return badge_classes.get(sentiment, 'bg-secondary')


def get_sentiment_icon(sentiment: str) -> str:
    """
    Get icon for sentiment.
    
    Args:
        sentiment: Sentiment value ('positive', 'neutral', 'negative')
    
    Returns:
        Icon class or emoji
    """
    icons = {
        'positive': '😊',
        'neutral': '😐',
        'negative': '😞',
    }
    return icons.get(sentiment, '😐')


def format_sentiment_score(score: float) -> str:
    """
    Format sentiment score for display.
    
    Args:
        score: Sentiment score (-1 to 1)
    
    Returns:
        Formatted score string
    """
    return f"{score:+.2f}"


def format_confidence(confidence: float) -> str:
    """
    Format confidence as percentage.
    
    Args:
        confidence: Confidence value (0 to 1)
    
    Returns:
        Formatted percentage string
    """
    return f"{confidence * 100:.1f}%"


def get_sentiment_color(sentiment: str) -> str:
    """
    Get color code for sentiment.
    
    Args:
        sentiment: Sentiment value ('positive', 'neutral', 'negative')
    
    Returns:
        Hex color code
    """
    colors = {
        'positive': '#28a745',  # Green
        'neutral': '#6c757d',   # Gray
        'negative': '#dc3545',  # Red
    }
    return colors.get(sentiment, '#6c757d')


def get_emotion_icon(emotion: str) -> str:
    """
    Get icon/emoji for emotion.
    
    Args:
        emotion: Emotion name
    
    Returns:
        Emoji representing the emotion
    """
    icons = {
        'joy': '😄',
        'anger': '😠',
        'sadness': '😢',
        'fear': '😨',
        'surprise': '😲',
        'disgust': '🤢',
        'trust': '🤝',
        'anticipation': '🤔',
    }
    return icons.get(emotion, '😐')


def has_sentiment_analysis(obj) -> bool:
    """
    Check if an object has sentiment analysis.
    
    Args:
        obj: Django model instance
    
    Returns:
        True if sentiment analysis exists
    """
    content_type = ContentType.objects.get_for_model(obj)
    return SentimentResult.objects.filter(
        content_type=content_type,
        object_id=obj.id
    ).exists()


def get_latest_sentiment(obj) -> Optional[SentimentResult]:
    """
    Get the latest sentiment analysis for an object.
    
    Args:
        obj: Django model instance
    
    Returns:
        SentimentResult instance or None
    """
    content_type = ContentType.objects.get_for_model(obj)
    return SentimentResult.objects.filter(
        content_type=content_type,
        object_id=obj.id
    ).first()


def get_sentiment_summary(sentiment_score: float) -> str:
    """
    Get human-readable sentiment summary.
    
    Args:
        sentiment_score: Sentiment score (-1 to 1)
    
    Returns:
        Human-readable summary
    """
    if sentiment_score >= 0.6:
        return "Very Positive"
    elif sentiment_score >= 0.2:
        return "Positive"
    elif sentiment_score >= -0.2:
        return "Neutral"
    elif sentiment_score >= -0.6:
        return "Negative"
    else:
        return "Very Negative"


def calculate_sentiment_trend(results: list) -> dict:
    """
    Calculate sentiment trend from a list of results.
    
    Args:
        results: List of SentimentResult instances
    
    Returns:
        Dictionary with trend information
    """
    if not results:
        return {
            'direction': 'stable',
            'change': 0,
            'description': 'No data'
        }
    
    # Calculate average scores for first and second half
    mid_point = len(results) // 2
    first_half = results[:mid_point]
    second_half = results[mid_point:]
    
    if not first_half or not second_half:
        return {
            'direction': 'stable',
            'change': 0,
            'description': 'Insufficient data'
        }
    
    first_avg = sum(float(r.sentiment_score) for r in first_half) / len(first_half)
    second_avg = sum(float(r.sentiment_score) for r in second_half) / len(second_half)
    
    change = second_avg - first_avg
    
    if change > 0.1:
        direction = 'improving'
        description = 'Sentiment is improving'
    elif change < -0.1:
        direction = 'declining'
        description = 'Sentiment is declining'
    else:
        direction = 'stable'
        description = 'Sentiment is stable'
    
    return {
        'direction': direction,
        'change': change,
        'description': description
    }


def get_top_keywords(results: list, limit: int = 10) -> list:
    """
    Get top keywords from a list of sentiment results.
    
    Args:
        results: List of SentimentResult instances
        limit: Maximum number of keywords to return
    
    Returns:
        List of (keyword, count) tuples
    """
    from collections import Counter
    
    all_keywords = []
    for result in results:
        all_keywords.extend(result.keywords)
    
    keyword_counts = Counter(all_keywords)
    return keyword_counts.most_common(limit)


def get_sentiment_distribution(results: list) -> dict:
    """
    Get sentiment distribution from a list of results.
    
    Args:
        results: List of SentimentResult instances
    
    Returns:
        Dictionary with sentiment counts and percentages
    """
    total = len(results)
    
    if total == 0:
        return {
            'positive': {'count': 0, 'percentage': 0},
            'neutral': {'count': 0, 'percentage': 0},
            'negative': {'count': 0, 'percentage': 0},
        }
    
    positive = sum(1 for r in results if r.sentiment == 'positive')
    neutral = sum(1 for r in results if r.sentiment == 'neutral')
    negative = sum(1 for r in results if r.sentiment == 'negative')
    
    return {
        'positive': {
            'count': positive,
            'percentage': round((positive / total) * 100, 1)
        },
        'neutral': {
            'count': neutral,
            'percentage': round((neutral / total) * 100, 1)
        },
        'negative': {
            'count': negative,
            'percentage': round((negative / total) * 100, 1)
        },
    }
