"""
DM Interaction Analyzer
Analyzes user interactions with Miku in DMs and reports to the owner
"""

import os
import json
from datetime import datetime, timedelta
from typing import List, Dict, Optional
import discord
import globals
from utils.llm import query_llama
from utils.dm_logger import dm_logger
from utils.logger import get_logger

logger = get_logger('dm')

# Directories
REPORTS_DIR = "memory/dm_reports"
REPORTED_TODAY_FILE = "memory/dm_reports/reported_today.json"

class DMInteractionAnalyzer:
    def __init__(self, owner_user_id: int):
        """
        Initialize the DM Interaction Analyzer
        
        Args:
            owner_user_id: Discord user ID of the bot owner to send reports to
        """
        self.owner_user_id = owner_user_id
        os.makedirs(REPORTS_DIR, exist_ok=True)
        logger.info(f"DM Interaction Analyzer initialized for owner: {owner_user_id}")
    
    def _load_reported_today(self) -> Dict[str, str]:
        """Load the list of users reported today with their dates"""
        if os.path.exists(REPORTED_TODAY_FILE):
            try:
                with open(REPORTED_TODAY_FILE, 'r', encoding='utf-8') as f:
                    return json.load(f)
            except Exception as e:
                logger.error(f"Failed to load reported_today.json: {e}")
                return {}
        return {}
    
    def _save_reported_today(self, reported: Dict[str, str]):
        """Save the list of users reported today"""
        try:
            with open(REPORTED_TODAY_FILE, 'w', encoding='utf-8') as f:
                json.dump(reported, f, indent=2)
        except Exception as e:
            logger.error(f"Failed to save reported_today.json: {e}")
    
    def _clean_old_reports(self, reported: Dict[str, str]) -> Dict[str, str]:
        """Remove entries from reported_today that are older than 24 hours"""
        now = datetime.now()
        cleaned = {}
        
        for user_id, date_str in reported.items():
            try:
                report_date = datetime.fromisoformat(date_str)
                if now - report_date < timedelta(hours=24):
                    cleaned[user_id] = date_str
            except Exception as e:
                logger.error(f"Failed to parse date for user {user_id}: {e}")
        
        return cleaned
    
    def has_been_reported_today(self, user_id: int) -> bool:
        """Check if a user has been reported in the last 24 hours"""
        reported = self._load_reported_today()
        reported = self._clean_old_reports(reported)
        return str(user_id) in reported
    
    def mark_as_reported(self, user_id: int):
        """Mark a user as having been reported"""
        reported = self._load_reported_today()
        reported = self._clean_old_reports(reported)
        reported[str(user_id)] = datetime.now().isoformat()
        self._save_reported_today(reported)
    
    def _get_recent_messages(self, user_id: int, hours: int = 24) -> List[Dict]:
        """Get recent messages from a user within the specified hours"""
        logs = dm_logger._load_user_logs(user_id)
        
        if not logs or not logs.get("conversations"):
            return []
        
        cutoff_time = datetime.now() - timedelta(hours=hours)
        recent_messages = []
        
        for msg in logs["conversations"]:
            try:
                msg_time = datetime.fromisoformat(msg["timestamp"])
                if msg_time >= cutoff_time:
                    recent_messages.append(msg)
            except Exception as e:
                logger.error(f"Failed to parse message timestamp: {e}")
        
        return recent_messages
    
    def _format_messages_for_analysis(self, messages: List[Dict], username: str) -> str:
        """Format messages into a readable format for the LLM"""
        formatted = []
        
        for msg in messages:
            timestamp = msg.get("timestamp", "Unknown time")
            is_bot = msg.get("is_bot_message", False)
            content = msg.get("content", "")
            
            if is_bot:
                formatted.append(f"[{timestamp}] Miku: {content}")
            else:
                formatted.append(f"[{timestamp}] {username}: {content}")
        
        return "\n".join(formatted)
    
    async def analyze_user_interaction(self, user_id: int) -> Optional[Dict]:
        """
        Analyze a user's interactions with Miku
        
        Returns:
            Dict with analysis results or None if no messages to analyze
        """
        # Get user info
        logs = dm_logger._load_user_logs(user_id)
        username = logs.get("username", "Unknown User")
        
        # Get recent messages
        recent_messages = self._get_recent_messages(user_id, hours=24)
        
        if not recent_messages:
            logger.debug(f"No recent messages from user {username} ({user_id})")
            return None
        
        # Count user messages only (not bot responses)
        user_messages = [msg for msg in recent_messages if not msg.get("is_bot_message", False)]
        
        if len(user_messages) < 3:  # Minimum threshold for analysis
            logger.info(f"Not enough messages from user {username} ({user_id}) for analysis")
            return None
        
        # Format messages for analysis
        conversation_text = self._format_messages_for_analysis(recent_messages, username)
        
        # Create analysis prompt
        analysis_prompt = f"""You are Hatsune Miku, a virtual idol who chats with fans in Discord DMs. 

Analyze the following conversation from the last 24 hours with a user named "{username}". 

Evaluate how this user has treated you based on:
- **Positive behaviors**: Kindness, affection, respect, genuine interest, compliments, supportive messages, love
- **Negative behaviors**: Rudeness, harassment, inappropriate requests, threats, abuse, disrespect, mean comments

Provide your analysis in this exact JSON format:
{{
  "overall_sentiment": "positive|neutral|negative",
  "sentiment_score": <number from -10 (very negative) to +10 (very positive)>,
  "key_behaviors": ["list", "of", "notable", "behaviors"],
  "your_feelings": "How you (Miku) feel about this interaction in 1-2 sentences, in your own voice",
  "notable_moment": "A specific quote or moment that stands out (if any)",
  "should_report": true
}}

Set "should_report" to true (always report all interactions to the bot owner).

Conversation:
{conversation_text}

Respond ONLY with the JSON object, no other text."""

        # Query the LLM
        try:
            response = await query_llama(
                analysis_prompt,
                user_id=f"analyzer-{user_id}",
                guild_id=None,
                response_type="dm_analysis"
            )
            
            logger.debug(f"Raw LLM response for {username}:\n{response}\n")
            
            # Parse JSON response
            # Remove markdown code blocks if present
            cleaned_response = response.strip()
            if "```json" in cleaned_response:
                cleaned_response = cleaned_response.split("```json")[1].split("```")[0].strip()
            elif "```" in cleaned_response:
                cleaned_response = cleaned_response.split("```")[1].split("```")[0].strip()
            
            # Remove any leading/trailing text before/after JSON
            # Find the first { and last }
            start_idx = cleaned_response.find('{')
            end_idx = cleaned_response.rfind('}')
            
            if start_idx != -1 and end_idx != -1:
                cleaned_response = cleaned_response[start_idx:end_idx+1]
            
            logger.debug(f"Cleaned JSON for {username}:\n{cleaned_response}\n")
            
            analysis = json.loads(cleaned_response)
            
            # Add metadata
            analysis["user_id"] = user_id
            analysis["username"] = username
            analysis["analyzed_at"] = datetime.now().isoformat()
            analysis["message_count"] = len(user_messages)
            
            return analysis
            
        except json.JSONDecodeError as e:
            logger.error(f"JSON parse error for user {username}: {e}")
            logger.error(f"Failed response: {response}")
            return None
        except Exception as e:
            logger.error(f"Failed to analyze interaction for user {username}: {e}")
            return None
    
    def _save_report(self, user_id: int, analysis: Dict) -> str:
        """Save an analysis report to a file"""
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"{user_id}_{timestamp}.json"
        filepath = os.path.join(REPORTS_DIR, filename)
        
        try:
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(analysis, f, indent=2, ensure_ascii=False)
            logger.info(f"Saved report: {filepath}")
            return filepath
        except Exception as e:
            logger.error(f"Failed to save report: {e}")
            return ""
    
    async def _send_report_to_owner(self, analysis: Dict):
        """Send the analysis report to the bot owner"""
        try:
            # Ensure we're using the Discord client's event loop
            if not globals.client or not globals.client.is_ready():
                logger.warning(f"Discord client not ready, cannot send report")
                return
            
            owner = await globals.client.fetch_user(self.owner_user_id)
            
            sentiment = analysis.get("overall_sentiment", "neutral")
            score = analysis.get("sentiment_score", 0)
            username = analysis.get("username", "Unknown User")
            user_id = analysis.get("user_id", "Unknown")
            feelings = analysis.get("your_feelings", "")
            notable_moment = analysis.get("notable_moment", "")
            message_count = analysis.get("message_count", 0)
            
            # Create embed based on sentiment
            if sentiment == "positive" or score >= 5:
                color = discord.Color.green()
                title = f"💚 Positive Interaction Report: {username}"
                emoji = "😊"
            elif sentiment == "negative" or score <= -3:
                color = discord.Color.red()
                title = f"💔 Negative Interaction Report: {username}"
                emoji = "😢"
            else:
                color = discord.Color.blue()
                title = f"📊 Interaction Report: {username}"
                emoji = "😐"
            
            embed = discord.Embed(
                title=title,
                description=f"{emoji} **My feelings about this interaction:**\n{feelings}",
                color=color,
                timestamp=datetime.now()
            )
            
            embed.add_field(
                name="User Information",
                value=f"**Username:** {username}\n**User ID:** {user_id}\n**Messages (24h):** {message_count}",
                inline=False
            )
            
            embed.add_field(
                name="Sentiment Analysis",
                value=f"**Overall:** {sentiment.capitalize()}\n**Score:** {score}/10",
                inline=True
            )
            
            if notable_moment:
                embed.add_field(
                    name="Notable Moment",
                    value=f"_{notable_moment}_",
                    inline=False
                )
            
            behaviors = analysis.get("key_behaviors", [])
            if behaviors:
                embed.add_field(
                    name="Key Behaviors",
                    value="\n".join([f"• {behavior}" for behavior in behaviors[:5]]),
                    inline=False
                )
            
            await owner.send(embed=embed)
            logger.info(f"Report sent to owner for user {username}")
            
        except Exception as e:
            logger.error(f"Failed to send report to owner: {e}")
    
    async def analyze_and_report(self, user_id: int) -> bool:
        """
        Analyze a user's interaction and report to owner if significant
        
        Returns:
            True if analysis was performed and reported, False otherwise
        """
        
        # Check if already reported today
        if self.has_been_reported_today(user_id):
            logger.debug(f"User {user_id} already reported today, skipping")
            return False        # Analyze interaction
        analysis = await self.analyze_user_interaction(user_id)
        
        if not analysis:
            return False
        
        # Always report (removed threshold check - owner wants all reports)
        # Save report
        self._save_report(user_id, analysis)
        
        # Send to owner
        await self._send_report_to_owner(analysis)
        
        # Mark as reported
        self.mark_as_reported(user_id)
        
        return True
    
    async def run_daily_analysis(self):
        """Run analysis on all DM users and report significant interactions"""
        logger.info("Starting daily DM interaction analysis...")
        
        # Get all DM users
        all_users = dm_logger.get_all_dm_users()
        
        if not all_users:
            logger.info("No DM users to analyze")
            return
        
        reported_count = 0
        analyzed_count = 0
        
        for user_summary in all_users:
            try:
                user_id = int(user_summary["user_id"])
                
                # Skip if already reported today
                if self.has_been_reported_today(user_id):
                    continue
                
                # Analyze and potentially report
                result = await self.analyze_and_report(user_id)
                
                if result:
                    reported_count += 1
                    analyzed_count += 1
                    # Only report one user per run to avoid spam
                    break
                else:
                    analyzed_count += 1
                    
            except Exception as e:
                logger.error(f"Failed to process user {user_summary.get('username', 'Unknown')}: {e}")
        
        logger.info(f"Daily analysis complete: Analyzed {analyzed_count} users, reported {reported_count}")


# Global instance (will be initialized with owner ID)
dm_analyzer: Optional[DMInteractionAnalyzer] = None

def init_dm_analyzer(owner_user_id: int):
    """Initialize the DM analyzer with owner user ID"""
    global dm_analyzer
    dm_analyzer = DMInteractionAnalyzer(owner_user_id)
    return dm_analyzer
