# Mood System Analysis & Issues

## Overview
After examining the Miku Discord bot's mood, mood rotation, and emoji nickname system, I've identified several critical issues that explain why they don't function correctly.

---

## System Architecture

### 1. **Dual Mood System**
The bot has TWO independent mood systems:
- **DM Mood**: Global mood for all direct messages (`globals.DM_MOOD`)
- **Server Mood**: Per-server mood tracked in `ServerConfig` objects

### 2. **Mood Rotation**
- **DM Mood**: Rotates every 2 hours (via `rotate_dm_mood()`)
- **Server Mood**: Rotates every 1 hour per server (via `rotate_server_mood()`)

### 3. **Nickname System**
Nicknames show mood emojis via the `MOOD_EMOJIS` dictionary in `utils/moods.py`

---

## 🔴 CRITICAL ISSUES FOUND

### Issue #1: Nickname Update Logic Conflict
**Location**: `utils/moods.py` lines 143-163

**Problem**: The `update_all_server_nicknames()` function uses **DM mood** to update **all server** nicknames:

```python
async def update_all_server_nicknames():
    """Update nickname for all servers to show current DM mood"""
    try:
        mood = globals.DM_MOOD.lower()  # ❌ Uses DM mood
        print(f"🔍 DM mood is: {mood}")
        emoji = MOOD_EMOJIS.get(mood, "")
        
        nickname = f"Hatsune Miku{emoji}"
        print(f"🔍 New nickname will be: {nickname}")
        
        for guild in globals.client.guilds:  # ❌ Updates ALL servers
            me = guild.get_member(globals.BOT_USER.id)
            if me is not None:
                try:
                    await me.edit(nick=nickname)
```

**Impact**: 
- Server nicknames show DM mood instead of their own server mood
- All servers get the same nickname despite having independent moods
- The per-server mood system is functionally broken for nicknames

**Expected Behavior**: Each server should display its own mood emoji based on `server_config.current_mood_name`

---

### Issue #2: DM Mood Rotation Updates Server Nicknames
**Location**: `utils/moods.py` lines 121-142

**Problem**: The `rotate_dm_mood()` function is called by the DM mood scheduler but doesn't update any nicknames:

```python
async def rotate_dm_mood():
    """Rotate DM mood automatically (no keyword triggers)"""
    try:
        old_mood = globals.DM_MOOD
        new_mood = old_mood
        attempts = 0
        
        while new_mood == old_mood and attempts < 5:
            new_mood = random.choice(globals.AVAILABLE_MOODS)
            attempts += 1
        
        globals.DM_MOOD = new_mood
        globals.DM_MOOD_DESCRIPTION = load_mood_description(new_mood)
        
        print(f"🔄 DM mood rotated from {old_mood} to {new_mood}")
        
        # Note: We don't update server nicknames here because servers have their own independent moods.
        # DM mood only affects direct messages to users.
```

**Impact**:
- Comment says "servers have their own independent moods"
- But `update_all_server_nicknames()` uses DM mood anyway
- Inconsistent design philosophy

---

### Issue #3: Incorrect Nickname Function Called After Server Mood Rotation
**Location**: `server_manager.py` line 647

**Problem**: After rotating a server's mood, the system calls `update_server_nickname()` which is correct, BUT there's confusion in the codebase:

```python
async def rotate_server_mood(guild_id: int):
    """Rotate mood for a specific server"""
    try:
        # ... mood rotation logic ...
        
        server_manager.set_server_mood(guild_id, new_mood_name, load_mood_description(new_mood_name))
        
        # Update nickname for this specific server
        await update_server_nickname(guild_id)  # ✅ Correct function
        
        print(f"🔄 Rotated mood for server {guild_id} from {old_mood_name} to {new_mood_name}")
```

**Analysis**: This part is actually correct, but...

---

### Issue #4: `nickname_mood_emoji()` Function Ambiguity
**Location**: `utils/moods.py` lines 165-171

**Problem**: This function can call either server-specific OR all-server update:

```python
async def nickname_mood_emoji(guild_id: int = None):
    """Update nickname with mood emoji for a specific server or all servers"""
    if guild_id is not None:
        # Update nickname for specific server
        await update_server_nickname(guild_id)
    else:
        # Update nickname for all servers (using DM mood)
        await update_all_server_nicknames()
```

**Impact**:
- If called without `guild_id`, it overwrites all server nicknames with DM mood
- Creates confusion about which mood system is active
- This function might be called incorrectly from various places

---

### Issue #5: Mood Detection in bot.py May Not Trigger Nickname Updates
**Location**: `bot.py` lines 469-512

**Problem**: When mood is auto-detected from keywords in messages, nickname updates are scheduled but may race with the rotation system:

```python
if detected and detected != server_config.current_mood_name:
    print(f"🔄 Auto mood detection for server {message.guild.name}: {server_config.current_mood_name} -> {detected}")
    
    # Block direct transitions to asleep unless from sleepy
    if detected == "asleep" and server_config.current_mood_name != "sleepy":
        print("❌ Ignoring asleep mood; server wasn't sleepy before.")
    else:
        # Update server mood
        server_manager.set_server_mood(message.guild.id, detected)
        
        # Update nickname for this server
        from utils.moods import update_server_nickname
        globals.client.loop.create_task(update_server_nickname(message.guild.id))
```

**Analysis**: This part looks correct, but creates a task that may conflict with hourly rotation.

---

### Issue #6: No Emoji for "neutral" Mood
**Location**: `utils/moods.py` line 16

```python
MOOD_EMOJIS = {
    "asleep": "💤",
    "neutral": "",  # ❌ Empty string
    "bubbly": "🫧",
    # ... etc
}
```

**Impact**: When bot is in neutral mood, nickname becomes just "Hatsune Miku" with no emoji, making it hard to tell if the system is working.

**Recommendation**: Add an emoji like "🎤" or "✨" for neutral mood.

---

## 🔧 ROOT CAUSE ANALYSIS

The core problem is **architectural confusion** between two competing systems:

1. **Original Design Intent**: Servers should have independent moods with per-server nicknames
2. **Broken Implementation**: `update_all_server_nicknames()` uses global DM mood for all servers
3. **Mixed Signals**: Comments say servers are independent, but code says otherwise

---

## 🎯 RECOMMENDED FIXES

### Fix #1: Remove `update_all_server_nicknames()` Entirely
This function violates the per-server mood architecture. It should never be called.

**Action**: 
- Delete or deprecate `update_all_server_nicknames()`
- Ensure all nickname updates go through `update_server_nickname(guild_id)`

---

### Fix #2: Update `nickname_mood_emoji()` to Only Support Server-Specific Updates

**Current Code**:
```python
async def nickname_mood_emoji(guild_id: int = None):
    if guild_id is not None:
        await update_server_nickname(guild_id)
    else:
        await update_all_server_nicknames()  # ❌ Remove this
```

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

---

### Fix #3: Add Neutral Mood Emoji

**Current**:
```python
"neutral": "",
```

**Fixed**:
```python
"neutral": "🎤",  # Or ✨, 🎵, etc.
```

---

### Fix #4: Audit All Calls to Nickname Functions

Search for any calls to:
- `update_all_server_nicknames()` - should not exist
- `nickname_mood_emoji()` - must always pass guild_id

**FOUND ISSUES**:

#### ❌ `api.py` - THREE broken endpoints:
1. **Line 113-114**: `/mood` endpoint sets DM mood but updates ALL server nicknames
2. **Line 126-127**: `/mood/reset` endpoint sets DM mood but updates ALL server nicknames  
3. **Line 139-140**: `/mood/calm` endpoint sets DM mood but updates ALL server nicknames

**Code**:
```python
@app.post("/mood")
async def set_mood_endpoint(data: MoodSetRequest):
    # Update DM mood
    globals.DM_MOOD = data.mood
    globals.DM_MOOD_DESCRIPTION = load_mood_description(data.mood)
    
    # ❌ WRONG: Updates ALL servers with DM mood
    from utils.moods import update_all_server_nicknames
    globals.client.loop.create_task(update_all_server_nicknames())
```

**Impact**: 
- API endpoints that change DM mood incorrectly change ALL server nicknames
- This is the smoking gun! When you use the API/dashboard to change mood, it breaks server nicknames
- Confirms that DM mood and server moods should be completely independent

**Fix**: 
- Remove nickname update calls from these endpoints
- DM mood should NOT affect server nicknames at all
- If you want to update server nicknames, use the per-server endpoints

#### ✅ `api.py` also has CORRECT per-server endpoints (line 145+):
- `/servers/{guild_id}/mood` - Gets server mood (correct)
- Likely has POST endpoints for setting server mood (need to verify)

**Locations checked**:
- ✅ `bot.py` - Uses `update_server_nickname(guild_id)` correctly
- ✅ `server_manager.py` - Rotation calls correct function
- ❌ `api.py` - DM mood endpoints incorrectly update all servers
- ⚠️ `command_router.py` - Imports `nickname_mood_emoji` but doesn't seem to use it

---

### Fix #5: Add Logging to Verify Mood/Nickname Sync

Add debug logging to `update_server_nickname()` to track:
- What mood the server thinks it has
- What emoji is being applied
- Whether the Discord API call succeeds

---

### Fix #6: Consider Removing DM Mood Entirely (Optional)

**Question**: Should DMs have their own mood system?

**Current Design**: 
- DMs use `globals.DM_MOOD`
- DM mood rotates every 2 hours
- DM mood does NOT affect nicknames (correctly)

**Recommendation**: This is fine IF the nickname system stops using it. The current separation is logical.

---

## 📋 VERIFICATION CHECKLIST

After fixes, verify:

1. [ ] Each server maintains its own mood independently
2. [ ] Server nicknames update when server mood changes
3. [ ] Hourly mood rotation updates the correct server's nickname
4. [ ] Keyword mood detection updates the correct server's nickname
5. [ ] DM mood changes do NOT affect any server nicknames
6. [ ] Neutral mood shows an emoji (or document that empty is intentional)
7. [ ] No race conditions between rotation and manual mood changes

---

## 🧪 TESTING PROCEDURE

1. **Test Server Mood Independence**:
   - Join multiple servers
   - Manually trigger mood change in one server
   - Verify other servers maintain their moods

2. **Test Nickname Updates**:
   - Trigger mood rotation
   - Check nickname shows correct emoji
   - Compare against `MOOD_EMOJIS` dictionary

3. **Test DM Mood Isolation**:
   - Send DM to bot
   - Wait for DM mood rotation
   - Verify server nicknames don't change

4. **Test Mood Detection**:
   - Send message with mood keywords
   - Verify mood changes and nickname updates
   - Check logs for correct mood detection

---

## 📊 SUMMARY

| Component | Status | Issue |
|-----------|--------|-------|
| Server Mood System | ⚠️ **Partially Broken** | Nicknames use wrong mood when API called |
| DM Mood System | ✅ **Working** | Isolated correctly in bot logic |
| Mood Rotation | ✅ **Working** | Logic is correct |
| Nickname Updates | 🔴 **BROKEN** | API endpoints use DM mood for servers |
| Mood Detection | ✅ **Working** | Keywords trigger correctly |
| Emoji System | ⚠️ **Minor Issue** | Neutral has no emoji |
| Per-Server API | ✅ **Working** | `/servers/{guild_id}/mood` endpoints correct |
| Global DM API | 🔴 **BROKEN** | `/mood` endpoints incorrectly update servers |

**KEY FINDING**: The bug is primarily in the **API layer**, not the core bot logic!

When you (or a dashboard) calls:
- `/mood` endpoint → Changes DM mood → Updates ALL server nicknames ❌
- `/mood/reset` endpoint → Resets DM mood → Updates ALL server nicknames ❌
- `/mood/calm` endpoint → Calms DM mood → Updates ALL server nicknames ❌

This explains why it "doesn't seem like they function right" - the API is sabotaging the per-server system!

---

## 🚀 PRIORITY FIX ORDER

1. **🔥 CRITICAL**: Fix API endpoints in `api.py` - Remove `update_all_server_nicknames()` calls from:
   - `/mood` endpoint (line 113-114)
   - `/mood/reset` endpoint (line 126-127)
   - `/mood/calm` endpoint (line 139-140)

2. **HIGH**: Deprecate `update_all_server_nicknames()` function in `utils/moods.py`
   - Add deprecation warning
   - Eventually delete it entirely

3. **HIGH**: Fix `nickname_mood_emoji()` to require `guild_id`
   - Remove the `guild_id=None` default
   - Remove the DM mood branch

4. **MEDIUM**: Add neutral mood emoji - user experience

5. **LOW**: Add debug logging - future maintenance

**IMMEDIATE ACTION**: Fix the three API endpoints. This is the root cause of the visible bug.

---

## 📝 CODE LOCATIONS REFERENCE

- **Mood definitions**: `utils/moods.py`
- **Server config**: `server_manager.py`
- **Bot message handling**: `bot.py`
- **LLM mood usage**: `utils/llm.py`
- **Global DM mood**: `globals.py`
- **Mood files**: `moods/*.txt`
