"""
Messaging Style System

This module provides dynamic, personality-driven messaging styles for NPC conversations.
Characters have base messaging traits that are modified per-relationship and by mood states.

See docs/plans/2025-11-13-dynamic-messaging-styles-design.md for full design documentation.
"""

import random
import json


def initialize_messaging_traits():
    """
    Generate random base messaging traits for a new character.

    Returns:
        dict: Base messaging traits (0-100 scale)
    """
    return {
        'verbosity': random.randint(30, 70),        # Most people are moderately verbose
        'inquisitiveness': random.randint(20, 80),
        'expressiveness': random.randint(20, 80),
        'responsiveness': random.randint(40, 80),   # Most people are at least somewhat responsive
        'openness': random.randint(20, 60),          # Most start somewhat guarded
        'emoji_usage': random.randint(10, 90),
        'formality': random.randint(20, 80),
        'response_timing': random.randint(40, 85)
    }


def initialize_messaging_patterns():
    """
    Generate random messaging patterns for a new character.

    Returns:
        dict: Messaging patterns (time preferences, typing style, etc.)
    """
    return {
        'time_of_day_preference': random.choice(['morning', 'night', 'neutral']),
        'weekend_availability': random.randint(30, 90),
        'typing_style': random.choice(['proper', 'casual', 'chaotic'])
    }


def initialize_relationship_modifiers(relationship=None, character=None):
    """
    Initialize messaging modifiers for a new relationship.
    Can apply relationship-type-specific starting modifiers.

    Args:
        relationship: relationshipClass instance (optional)
        character: personClass instance (optional, needed for relationship-type modifiers)

    Returns:
        dict: Initial messaging modifiers
    """
    modifiers = {
        # Permanent/evolving modifiers
        'verbosity': 0,
        'inquisitiveness': 0,
        'expressiveness': 0,
        'responsiveness': 0,
        'openness': 0,
        'emoji_usage': 0,
        'formality': 0,
        'response_timing': 0,

        # Contextual state
        'mood_state': 'neutral',
        'current_topic_engagement': 0,
    }

    # Apply relationship-type-specific starting modifiers if character provided
    if character and hasattr(character, 'relationships') and character.relationships:
        primary_relationship = character.relationships[0].lower()

        # Boss/professional: start more formal
        if primary_relationship in ['boss', 'teacher', 'coworker']:
            modifiers['formality'] += 20
            modifiers['emoji_usage'] -= 15
            modifiers['openness'] -= 10

        # Romantic: start more expressive
        elif primary_relationship in ['partner', 'girlfriend', 'boyfriend', 'spouse']:
            modifiers['expressiveness'] += 15
            modifiers['emoji_usage'] += 10
            modifiers['openness'] += 10

        # Family: start more casual
        elif primary_relationship in ['mother', 'father', 'sibling']:
            modifiers['formality'] -= 15
            modifiers['openness'] += 5

    return modifiers


def calculate_effective_traits(character, relationship):
    """
    Calculate final trait values: base + relationship modifier + mood modifier.

    Args:
        character: personClass instance with messaging_traits
        relationship: relationshipClass instance with messaging_modifiers (or None)

    Returns:
        dict: Effective trait values (0-100, clamped)
    """
    if not hasattr(character, 'messaging_traits'):
        # Character doesn't have traits yet, return defaults
        return initialize_messaging_traits()

    base = character.messaging_traits
    effective = {}

    # Get relationship modifiers if available
    rel_mods = {}
    mood_state = 'neutral'

    if relationship and hasattr(relationship, 'messaging_modifiers'):
        rel_mods = relationship.messaging_modifiers
        mood_state = rel_mods.get('mood_state', 'neutral')

    # Calculate effective value for each trait
    for trait in base.keys():
        relationship_modifier = rel_mods.get(trait, 0) if isinstance(rel_mods.get(trait, 0), (int, float)) else 0
        mood_modifier = get_mood_modifier(character, mood_state, trait)

        effective_value = base[trait] + relationship_modifier + mood_modifier
        effective[trait] = max(0, min(100, effective_value))  # Clamp 0-100

    return effective


def get_mood_modifier(character, mood_state, trait):
    """
    Get temporary mood-based adjustment for a specific trait.

    Args:
        character: personClass instance
        mood_state: str - 'great', 'bad', 'stressed', or 'neutral'
        trait: str - trait name

    Returns:
        int: Modifier value (-50 to +50)
    """
    mood_effects = {
        'great': {
            'expressiveness': 15,
            'verbosity': 10,
            'emoji_usage': 20,
            'inquisitiveness': 10,
            'responsiveness': 10
        },
        'bad': {
            'expressiveness': -20,
            'responsiveness': -15,
            'verbosity': -10,
            'openness': -10,
            'emoji_usage': -15
        },
        'stressed': {
            'responsiveness': -25,
            'verbosity': 20,  # Rambles when stressed
            'openness': -10,
            'formality': -10  # More casual/sloppy when stressed
        },
        'neutral': {}
    }

    return mood_effects.get(mood_state, {}).get(trait, 0)


def get_messaging_style_prompt(character, relationship, player):
    """
    Generate natural language style instructions for AI prompt based on calculated traits.

    Args:
        character: personClass instance
        relationship: relationshipClass instance (or None)
        player: playerClass instance

    Returns:
        str: Natural language instructions for AI prompt
    """
    effective_traits = calculate_effective_traits(character, relationship)
    instructions = []

    # Verbosity
    if effective_traits['verbosity'] < 30:
        instructions.append("Keep responses extremely brief - 1-2 short sentences max, often just a few words.")
    elif effective_traits['verbosity'] > 70:
        instructions.append("You tend to ramble and share lots of details. Don't hold back - elaborate freely.")

    # Inquisitiveness
    if effective_traits['inquisitiveness'] < 30:
        instructions.append("You rarely ask questions. Just respond without pushing the conversation forward.")
    elif effective_traits['inquisitiveness'] > 70:
        instructions.append("You're naturally curious - frequently ask follow-up questions and show genuine interest.")

    # Expressiveness
    if effective_traits['expressiveness'] < 30:
        instructions.append("Keep tone neutral and understated. No excitement or emphasis.")
    elif effective_traits['expressiveness'] > 70:
        instructions.append("Be animated and enthusiastic! Use exclamation marks, show excitement, be expressive.")

    # Responsiveness
    if effective_traits['responsiveness'] < 30:
        instructions.append("Give minimal effort responses. Don't build on topics or match their energy.")
    elif effective_traits['responsiveness'] > 70:
        instructions.append("Engage fully with what they say. Build on their points, match their energy.")

    # Openness
    if effective_traits['openness'] < 30:
        instructions.append("Stay surface-level. Avoid sharing personal details or deep thoughts.")
    elif effective_traits['openness'] > 70:
        instructions.append("Feel free to share personal details, thoughts, and feelings openly - even TMI sometimes.")

    # Emoji usage
    if effective_traits['emoji_usage'] < 20:
        instructions.append("Never use emojis.")
    elif 40 <= effective_traits['emoji_usage'] < 70:
        instructions.append("Use an emoji occasionally when it fits (0-1 per message).")
    elif effective_traits['emoji_usage'] >= 70:
        instructions.append("Use emojis frequently to express yourself (2-4 per message is normal for you).")

    # Formality
    if effective_traits['formality'] < 30:
        instructions.append("Text casually - lowercase, abbreviations (lol, idk, ur), minimal punctuation.")
    elif effective_traits['formality'] > 70:
        instructions.append("Use proper grammar, spelling, and punctuation. Text like you're writing an email.")

    return " ".join(instructions)


def update_conversation_messaging_modifiers(relationship, sentiment, conversation_length, topic_engagement=0):
    """
    Update messaging modifiers based on conversation dynamics.
    Called after each AI response to evolve the relationship's messaging style.

    Args:
        relationship: relationshipClass instance
        sentiment: str - 'positive', 'negative', or 'neutral'
        conversation_length: int - total messages in conversation
        topic_engagement: int - optional, -30 to +30 for current topic interest
    """
    # Validate inputs
    if not relationship or not hasattr(relationship, 'messaging_modifiers'):
        return

    # Clamp topic_engagement to valid range
    topic_engagement = max(-30, min(30, topic_engagement))

    # Positive conversations increase openness, expressiveness, responsiveness
    if sentiment == "positive":
        relationship.messaging_modifiers['openness'] += 1
        relationship.messaging_modifiers['expressiveness'] += 1
        relationship.messaging_modifiers['responsiveness'] += 1

    # Negative conversations decrease engagement
    elif sentiment == "negative":
        relationship.messaging_modifiers['responsiveness'] -= 3
        relationship.messaging_modifiers['openness'] -= 2
        relationship.messaging_modifiers['expressiveness'] -= 2

    # Neutral conversations have small positive drift
    else:
        relationship.messaging_modifiers['responsiveness'] += 0.5

    # Long conversations increase comfort and casualness
    if conversation_length > 20:
        relationship.messaging_modifiers['verbosity'] += 1
        relationship.messaging_modifiers['formality'] -= 1
        relationship.messaging_modifiers['openness'] += 1

    # Very long conversations increase even more
    if conversation_length > 50:
        relationship.messaging_modifiers['formality'] -= 2
        relationship.messaging_modifiers['openness'] += 2

    # Update topic engagement (resets each conversation)
    relationship.messaging_modifiers['current_topic_engagement'] = topic_engagement

    # Cap all modifiers at -40 to +40
    for key in relationship.messaging_modifiers:
        if isinstance(relationship.messaging_modifiers[key], (int, float)):
            relationship.messaging_modifiers[key] = max(-40, min(40, relationship.messaging_modifiers[key]))


def set_mood_state(character, player, mood):
    """
    Set character's mood state across all their relationships.
    Mood affects all conversations with this character.

    Args:
        character: personClass instance
        player: playerClass instance
        mood: str - 'great', 'bad', 'stressed', or 'neutral'
    """
    import logging
    logger = logging.getLogger(__name__)

    # Validate mood value
    VALID_MOODS = {'great', 'bad', 'stressed', 'neutral'}
    if mood not in VALID_MOODS:
        logger.warning(f"Invalid mood state '{mood}', defaulting to 'neutral'")
        mood = 'neutral'

    # Find relationship with this character
    from functions import get_relationship

    relationship = get_relationship(player, character.id)
    if relationship and hasattr(relationship, 'messaging_modifiers'):
        relationship.messaging_modifiers['mood_state'] = mood
        print(f"Set {character.firstname}'s mood to '{mood}'")


def decay_messaging_modifiers(relationship, decay_rate=0.1):
    """
    Gradually return messaging modifiers toward neutral (0).
    Called periodically (weekly recommended) to prevent permanent extremes.

    Args:
        relationship: relationshipClass instance
        decay_rate: float - how much to decay (0.1 = 10% toward 0 each call)
    """
    if not hasattr(relationship, 'messaging_modifiers'):
        return

    for trait in relationship.messaging_modifiers:
        # Only decay numeric modifiers (not mood_state, etc.)
        if isinstance(relationship.messaging_modifiers[trait], (int, float)):
            current = relationship.messaging_modifiers[trait]
            # Move toward 0
            relationship.messaging_modifiers[trait] = current * (1 - decay_rate)

            # Round to 0 if very close
            if abs(relationship.messaging_modifiers[trait]) < 0.5:
                relationship.messaging_modifiers[trait] = 0


def apply_event_modifiers(relationship, event_type):
    """
    Apply messaging modifier changes for major relationship/life events.

    Args:
        relationship: relationshipClass instance
        event_type: str - type of event triggering modifiers
    """
    import logging
    logger = logging.getLogger(__name__)

    if not relationship or not hasattr(relationship, 'messaging_modifiers'):
        return

    event_effects = {
        # Relationship milestones
        'start_dating': {
            'openness': 15,
            'expressiveness': 10,
            'emoji_usage': 10,
            'inquisitiveness': 10
        },
        'breakup': {
            'responsiveness': -40,
            'openness': -30,
            'emoji_usage': -20,
            'expressiveness': -25
        },
        'become_best_friends': {
            'openness': 20,
            'responsiveness': 15,
            'formality': -15,
            'emoji_usage': 10
        },
        'major_fight': {
            'responsiveness': -25,
            'openness': -15,
            'expressiveness': -10,
            'formality': 5
        },

        # Life events (affect mood more than permanent modifiers)
        'got_promoted': {
            'mood_state': 'great'
        },
        'lost_job': {
            'mood_state': 'stressed'
        },
        'parent_died': {
            'mood_state': 'bad',
            'responsiveness': -15,
            'openness': -10
        },
        'had_baby': {
            'mood_state': 'great',
            'verbosity': 10  # New parents talk a lot about their baby
        }
    }

    if event_type not in event_effects:
        logger.warning(f"Unknown event type '{event_type}' for messaging modifiers")
        return

    effects = event_effects[event_type]
    for key, value in effects.items():
        if key == 'mood_state':
            relationship.messaging_modifiers[key] = value
        else:
            relationship.messaging_modifiers[key] += value

    # Cap modifiers
    for key in relationship.messaging_modifiers:
        if isinstance(relationship.messaging_modifiers[key], (int, float)):
            relationship.messaging_modifiers[key] = max(-40, min(40, relationship.messaging_modifiers[key]))

    print(f"Applied '{event_type}' messaging modifiers: {effects}")


def get_debug_messaging_info(character, relationship):
    """
    Get detailed debug information about a character's messaging style.
    Useful for testing and debugging.

    Args:
        character: personClass instance
        relationship: relationshipClass instance (or None)

    Returns:
        dict: Debug information
    """
    base = character.messaging_traits if hasattr(character, 'messaging_traits') else {}
    mods = relationship.messaging_modifiers if relationship and hasattr(relationship, 'messaging_modifiers') else {}
    effective = calculate_effective_traits(character, relationship)

    return {
        'character_name': f"{character.firstname} {character.lastname}",
        'base_traits': base,
        'relationship_modifiers': mods,
        'effective_traits': effective,
        'mood_state': mods.get('mood_state', 'neutral') if mods else 'neutral',
        'prompt_instructions': get_messaging_style_prompt(character, relationship, None)
    }
