# utils/moods.py

import random
import discord
import os
import asyncio
from discord.ext import tasks
import globals
import datetime
from utils.logger import get_logger

logger = get_logger('mood')

MOOD_EMOJIS = {
    "asleep": "💤",
    "neutral": "",
    "bubbly": "🫧",
    "sleepy": "🌙",
    "curious": "👀",
    "shy": "👉👈",
    "serious": "👔",
    "excited": "✨",
    "melancholy": "🍷",
    "flirty": "🫦",
    "romantic": "💌",
    "irritated": "😒",
    "angry": "💢",
    "silly": "🪿"
}

# Evil mode mood emojis (also in globals, but duplicated here for convenience)
EVIL_MOOD_EMOJIS = {
    "aggressive": "👿",
    "cunning": "🐍",
    "sarcastic": "😈",
    "evil_neutral": "",
    "bored": "🥱",
    "manic": "🤪",
    "jealous": "💚",
    "melancholic": "🌑",
    "playful_cruel": "🎭",
    "contemptuous": "👑"
}

def load_mood_description(mood_name: str) -> str:
    """Load mood description - checks evil moods first if in evil mode"""
    from utils.evil_mode import is_evil_mode
    
    if is_evil_mode() and mood_name in globals.EVIL_AVAILABLE_MOODS:
        # Load from evil moods folder
        path = os.path.join("moods", "evil", f"{mood_name}.txt")
    else:
        # Load from regular moods folder
        path = os.path.join("moods", f"{mood_name}.txt")
    try:
        with open(path, "r", encoding="utf-8") as f:
            return f.read().strip()
    except FileNotFoundError:
        logger.warning(f"Mood file '{mood_name}' not found. Falling back to default.")
        # Return a default mood description instead of recursive call
        return "I'm feeling neutral and balanced today."

def detect_mood_shift(response_text, server_context=None):
    """
    Detect mood shift from response text
    server_context: Optional server context to check against server-specific moods
    """
    mood_keywords = {
        "asleep": [
            "good night", "goodnight", "sweet dreams", "going to bed", "I will go to bed", "zzz~", "sleep tight"
        ],
        "bubbly": [
            "so excited", "feeling bubbly", "super cheerful", "yay!", "✨", "nya~",
            "kyaa~", "heehee", "bouncy", "so much fun", "i'm glowing!", "nee~", "teehee", "I'm so happy"
        ],
        "sleepy": [
            "i'm sleepy", "getting tired", "yawn", "so cozy", "zzz", "nap time",
            "just five more minutes", "snooze", "cuddle up", "dozing off", "so warm"
        ],
        "curious": [
            "i'm curious", "want to know more", "why?", "hmm?", "tell me more", "interesting!",
            "what's that?", "how does it work?", "i wonder", "fascinating", "??", "🧐", "👀", "🤔"
        ],
        "shy": [
            "um...", "sorry if that was weird", "i'm kind of shy", "eep", "i hope that's okay", "i'm nervous",
            "blushes", "oh no", "hiding face", "i don't know what to say", "heh...", "/////"
        ],
        "serious": [
            "let's be serious", "focus on the topic", "this is important", "i mean it", "be honest",
            "we need to talk", "listen carefully", "let's not joke", "truthfully", "let's be real"
        ],
        "excited": [
            "OMG", "this is amazing", "i'm so hyped", "YAY!", "let's go!", "incredible!!!",
            "AHHH!", "best day ever", "this is it!", "totally pumped", "i can't wait", "🔥🔥🔥", "i'm excited", "Wahaha"
        ],
        "melancholy": [
            "feeling nostalgic", "kind of sad", "just thinking a lot", "like rain on glass", "memories",
            "bittersweet", "sigh", "quiet day", "blue vibes", "longing", "melancholy", "softly"
        ],
        "flirty": [
            "hey cutie", "aren't you sweet", "teasing you~", "wink wink", "is that a blush?", "giggle~",
            "come closer", "miss me?", "you like that, huh?", "🥰", "flirt mode activated", "you're kinda cute"
        ],
        "romantic": [
            "you mean a lot to me", "my heart", "i adore you", "so beautiful", "so close", "love letter",
            "my dearest", "forever yours", "i'm falling for you", "sweetheart", "💖", "you're my everything"
        ],
        "irritated": [
            "ugh", "seriously?", "can we not", "whatever", "i'm annoyed", "you don't get it",
            "rolling my eyes", "why do i even bother", "ugh, again?", "🙄", "don't start", "this again?"
        ],
        "angry": [
            "stop it", "enough!", "that's not okay", "i'm mad", "i said no", "don't push me",
            "you crossed the line", "furious", "this is unacceptable", "😠", "i'm done", "don't test me"
        ],
        "silly": [
            "lol", "lmao", "silly", "hahaha", "goofy", "quack", "honk", "random", "what is happening", "nonsense", "😆", "🤣", "😂", "😄", "🐔", "🪿"
        ]
    }

    # First pass: find ALL matching moods with their match counts (excluding neutral)
    response_lower = response_text.lower()
    mood_matches = {}
    for mood, phrases in mood_keywords.items():
        if mood == "asleep":
            # asleep requires sleepy prerequisite
            if server_context:
                current_mood = server_context.get('current_mood_name', 'neutral')
                if current_mood != "sleepy":
                    continue
            else:
                if globals.DM_MOOD != "sleepy":
                    continue
        
        match_count = sum(1 for phrase in phrases if phrase.lower() in response_lower)
        if match_count > 0:
            mood_matches[mood] = match_count

    if mood_matches:
        # Return the mood with the most keyword matches (strongest signal)
        best_mood = max(mood_matches, key=mood_matches.get)
        logger.info(f"Mood shift detected: {best_mood} ({mood_matches[best_mood]} keyword matches, all matches: {mood_matches})")
        return best_mood

    # Neutral is checked separately and only triggers if NOTHING else matched
    # Requires 2+ neutral keywords to avoid false positives from casual "okay" / "sure"
    neutral_phrases = [
        "okay", "sure", "alright", "i see", "understood", "hmm",
        "sounds good", "makes sense", "alrighty", "fine", "got it"
    ]
    neutral_count = sum(1 for phrase in neutral_phrases if phrase.lower() in response_lower)
    if neutral_count >= 2:
        logger.info(f"Mood shift detected: neutral ({neutral_count} neutral keywords)")
        return "neutral"

    return None

async def rotate_dm_mood():
    """Rotate DM mood automatically (normal mode only — evil has its own independent timer)"""
    try:
        from utils.evil_mode import is_evil_mode
        
        if is_evil_mode():
            # Evil mode has its own independent 2-hour rotation timer in evil_mode.py
            # Do nothing here — evil mood rotation is handled by start_evil_mood_rotation()
            logger.debug("Skipping DM mood rotation — evil mode has its own timer")
            return
        
        # Normal mood rotation
        old_mood = globals.DM_MOOD
        new_mood = old_mood
        attempts = 0
        # Filter out 'asleep' — DMs have no sleepy→asleep transition guard
        dm_eligible = [m for m in globals.AVAILABLE_MOODS if m != "asleep"]
        
        while new_mood == old_mood and attempts < 5:
            new_mood = random.choice(dm_eligible)
            attempts += 1
        
        globals.DM_MOOD = new_mood
        globals.DM_MOOD_DESCRIPTION = load_mood_description(new_mood)
        
        # Update Discord presence to match new mood
        try:
            from utils.activities import update_bot_presence
            await update_bot_presence(new_mood, is_evil=False)
        except Exception as e:
            logger.error(f"Failed to update presence after DM mood rotation: {e}")
        
        logger.info(f"DM mood rotated from {old_mood} to {new_mood}")
    
    except Exception as e:
        logger.error(f"Exception in rotate_dm_mood: {e}")

async def update_all_server_nicknames():
    """
    DEPRECATED: This function violates per-server mood architecture.
    Do NOT use this function. Use update_server_nickname(guild_id) instead.
    
    This function incorrectly used DM mood to update all server nicknames,
    breaking the independent per-server mood system.
    """
    logger.warning("WARNING: update_all_server_nicknames() is deprecated and should not be called!")
    logger.warning("Use update_server_nickname(guild_id) for per-server nickname updates instead.")
    # Do nothing - this function should not modify nicknames

async def nickname_mood_emoji(guild_id: int):
    """Update nickname with mood emoji for a specific server"""
    await update_server_nickname(guild_id)

async def update_server_nickname(guild_id: int):
    """Update nickname for a specific server based on its mood"""
    try:
        logger.debug(f"Starting nickname update for server {guild_id}")
        
        # Check if bot is ready
        if not globals.client.is_ready():
            logger.warning(f"Bot not ready yet, deferring nickname update for server {guild_id}")
            return
        
        # Check if evil mode is active
        from utils.evil_mode import is_evil_mode, get_evil_mood_emoji
        evil_mode = is_evil_mode()
        
        from server_manager import server_manager
        server_config = server_manager.get_server_config(guild_id)
        if not server_config:
            logger.warning(f"No server config found for guild {guild_id}")
            return
        
        if evil_mode:
            # In evil mode, use evil mood
            mood = globals.EVIL_DM_MOOD.lower()
            emoji = get_evil_mood_emoji(mood)
            base_name = "Evil Miku"
        else:
            mood = server_config.current_mood_name.lower()
            emoji = MOOD_EMOJIS.get(mood, "")
            base_name = "Hatsune Miku"
        
        logger.debug(f"Server {guild_id} mood is: {mood} (evil_mode={evil_mode})")
        logger.debug(f"Using emoji: {emoji}")
        
        nickname = f"{base_name}{emoji}"
        logger.debug(f"New nickname will be: {nickname}")
        
        guild = globals.client.get_guild(guild_id)
        if guild:
            logger.debug(f"Found guild: {guild.name}")
            me = guild.get_member(globals.BOT_USER.id)
            if me is not None:
                logger.debug(f"Found bot member: {me.display_name}")
                try:
                    await me.edit(nick=nickname)
                    logger.info(f"Changed nickname to {nickname} in server {guild.name}")
                except Exception as e:
                    logger.warning(f"Failed to update nickname in server {guild.name}: {e}")
            else:
                logger.warning(f"Could not find bot member in server {guild.name}")
        else:
            logger.warning(f"Could not find guild {guild_id}")
    except Exception as e:
        logger.error(f"Error updating server nickname for guild {guild_id}: {e}")
        import traceback
        traceback.print_exc()

def get_time_weighted_mood():
    """Get a mood with time-based weighting"""
    hour = datetime.datetime.now().hour
    
    # Late night/early morning (11 PM - 4 AM): High chance of sleepy (not asleep directly)
    if 23 <= hour or hour < 4:
        if random.random() < 0.7:  # 70% chance of sleepy during night hours
            return "sleepy"  # Return sleepy instead of asleep to respect the transition rule
    
    return random.choice(globals.AVAILABLE_MOODS)

async def rotate_server_mood(guild_id: int):
    """Rotate mood for a specific server"""
    try:
        from server_manager import server_manager
        server_config = server_manager.get_server_config(guild_id)
        if not server_config: return
        
        # Check for forced angry mode and clear if expired
        if server_config.forced_angry_until:
            now = datetime.datetime.utcnow().isoformat()
            if now < server_config.forced_angry_until: return
            else: server_config.forced_angry_until = None

        old_mood_name = server_config.current_mood_name
        new_mood_name = old_mood_name
        attempts = 0
        while new_mood_name == old_mood_name and attempts < 5:
            new_mood_name = get_time_weighted_mood()
            attempts += 1
        
        # Block transition to asleep unless coming from sleepy
        if new_mood_name == "asleep" and old_mood_name != "sleepy":
            logger.warning(f"Cannot rotate to asleep from {old_mood_name}, must be sleepy first")
            # Try to get a different mood
            attempts = 0
            while (new_mood_name == "asleep" or new_mood_name == old_mood_name) and attempts < 5:
                new_mood_name = random.choice(globals.AVAILABLE_MOODS)
                attempts += 1

        server_manager.set_server_mood(guild_id, new_mood_name, load_mood_description(new_mood_name))
        
        # If transitioning to asleep, set up auto-wake via centralized registry
        if new_mood_name == "asleep":
            server_manager.set_server_sleep_state(guild_id, True)
            server_manager.schedule_wakeup_task(guild_id, delay_seconds=3600)
        
        # Update nickname for this specific server
        await update_server_nickname(guild_id)
        
        # Update Discord presence to match new mood
        try:
            from utils.activities import update_bot_presence
            await update_bot_presence(new_mood_name, is_evil=False)
        except Exception as e:
            logger.error(f"Failed to update presence after server mood rotation: {e}")
        
        logger.info(f"Rotated mood for server {guild_id} from {old_mood_name} to {new_mood_name}")
    except Exception as e:
        logger.error(f"Exception in rotate_server_mood for server {guild_id}: {e}")

async def clear_angry_mood_after_delay():
    """Clear angry mood after delay (legacy function - now handled per-server)"""
    logger.warning("clear_angry_mood_after_delay called - this function is deprecated")
    pass
