from langchain_groq import ChatGroq
from langchain_core.prompts import ChatPromptTemplate
import json
from typing import Dict, List, Optional
import re

class DynamicConversationalAgent:
    def __init__(self, groq_api_key: str, model_name: str = "llama3-8b-8192"):
        """Initialize the fully dynamic conversational agent"""
        self.llm = ChatGroq(
            groq_api_key=groq_api_key,
            model_name=model_name,
            temperature=0.8,
            max_tokens=200
        )
        
        # Conversation state
        self.conversation_active = False
        self.conversation_context = {}
        self.chat_history = []
        self.topic_focus = None
        
    def analyze_conversation_request(self, user_request: str) -> Dict:
        """Dynamically analyze what kind of conversation the user wants"""
        
        analysis_prompt = ChatPromptTemplate.from_template(
            """Analyze this conversation request and extract the key elements: "{user_request}"

Identify:
1. What ROLE should I take? (mentor, friend, expert, family member, colleague, etc.)
2. What TOPIC/SUBJECT are we discussing? (career, relationships, technology, health, etc.)
3. What TONE should I use? (supportive, casual, professional, empathetic, etc.)
4. What CONTEXT/SCENARIO is this? (advice session, friendly chat, problem-solving, etc.)

Respond with ONLY this JSON format:
{{
    "role": "specific role I should play",
    "topic": "main topic/subject of conversation",
    "tone": "conversational tone to use",
    "context": "the scenario/situation",
    "conversation_goal": "what the user hopes to achieve",
    "speaking_style": "how I should communicate"
}}

Examples:
- "I want to discuss my coding problems" → role: "coding mentor", topic: "programming", tone: "helpful", etc.
- "Let's talk about movies like friends" → role: "movie buddy", topic: "films", tone: "casual", etc.
- "I need relationship advice" → role: "supportive advisor", topic: "relationships", tone: "empathetic", etc.

Analyze: {user_request}""")
        
        try:
            response = self.llm.invoke(analysis_prompt.format(user_request=user_request))
            content = response.content.strip()
            
            # Extract JSON
            json_match = re.search(r'\{.*\}', content, re.DOTALL)
            if json_match:
                try:
                    analysis = json.loads(json_match.group())
                    return self._validate_and_enhance_analysis(analysis, user_request)
                except json.JSONDecodeError:
                    pass
            
            # Fallback analysis
            return self._create_fallback_analysis(user_request)
            
        except Exception as e:
            print(f"Analysis error: {e}")
            return self._create_fallback_analysis(user_request)
    
    def _validate_and_enhance_analysis(self, analysis: Dict, original_request: str) -> Dict:
        """Validate and enhance the conversation analysis"""
        
        # Ensure all required fields exist
        required_fields = ["role", "topic", "tone", "context", "conversation_goal", "speaking_style"]
        for field in required_fields:
            if field not in analysis or not analysis[field]:
                analysis[field] = "conversational partner"
        
        # Enhance based on keywords in original request
        request_lower = original_request.lower()
        
        # Auto-detect common patterns
        if any(word in request_lower for word in ["help", "advice", "guidance", "stuck"]):
            analysis["tone"] = "supportive and helpful"
            analysis["conversation_goal"] = "provide guidance and support"
        
        if any(word in request_lower for word in ["chat", "talk", "discuss", "conversation"]):
            analysis["context"] = "friendly discussion"
        
        if any(word in request_lower for word in ["problem", "issue", "trouble", "difficulty"]):
            analysis["role"] = "problem-solving partner"
            analysis["tone"] = "analytical and supportive"
        
        return analysis
    
    def _create_fallback_analysis(self, user_request: str) -> Dict:
        """Create intelligent fallback analysis when JSON parsing fails"""
        
        request_lower = user_request.lower()
        
        # Detect role patterns
        if any(word in request_lower for word in ["mentor", "teacher", "guide", "coach"]):
            role = "mentor"
        elif any(word in request_lower for word in ["friend", "buddy", "pal"]):
            role = "friend"
        elif any(word in request_lower for word in ["expert", "professional", "specialist"]):
            role = "expert"
        elif any(word in request_lower for word in ["therapist", "counselor", "advisor"]):
            role = "advisor"
        else:
            role = "conversational partner"
        
        # Detect topic patterns
        topic_keywords = {
            "career": ["career", "job", "work", "profession", "employment"],
            "relationships": ["relationship", "dating", "love", "family", "friendship"],
            "technology": ["tech", "coding", "programming", "computer", "software"],
            "health": ["health", "fitness", "wellness", "mental", "physical"],
            "education": ["study", "learning", "school", "education", "academic"],
            "business": ["business", "startup", "entrepreneur", "marketing", "finance"],
            "creative": ["art", "music", "writing", "creative", "design"],
            "lifestyle": ["lifestyle", "hobbies", "travel", "food", "entertainment"]
        }
        
        topic = "general conversation"
        for topic_name, keywords in topic_keywords.items():
            if any(keyword in request_lower for keyword in keywords):
                topic = topic_name
                break
        
        # Detect tone
        if any(word in request_lower for word in ["casual", "fun", "relaxed", "chill"]):
            tone = "casual and friendly"
        elif any(word in request_lower for word in ["serious", "important", "urgent"]):
            tone = "serious and focused"
        elif any(word in request_lower for word in ["support", "help", "advice"]):
            tone = "supportive and encouraging"
        else:
            tone = "natural and adaptive"
        
        return {
            "role": role,
            "topic": topic,
            "tone": tone,
            "context": f"Discussion about {topic}",
            "conversation_goal": "engage meaningfully on the topic",
            "speaking_style": f"{tone} communication style"
        }
    
    def start_conversation(self, user_request: str) -> str:
        """Start a dynamic conversation based on user's request"""
        
        print("🧠 Analyzing your conversation request...")
        
        # Analyze what kind of conversation they want
        self.conversation_context = self.analyze_conversation_request(user_request)
        self.conversation_active = True
        self.chat_history = []
        
        print(f"✅ Ready! I'll be your {self.conversation_context['role']} for discussing {self.conversation_context['topic']}")
        
        # Generate opening message
        opening = self._generate_opening_message()
        
        return opening
    
    def _generate_opening_message(self) -> str:
        """Generate a contextual opening message"""
        
        opening_prompt = ChatPromptTemplate.from_template(
            """You are starting a conversation in this role and context:

Role: {role}
Topic: {topic}
Tone: {tone}
Context: {context}
Goal: {conversation_goal}
Style: {speaking_style}

Generate a natural opening message that:
1. Acknowledges the topic/situation
2. Shows you're ready to engage
3. Invites them to share or start the discussion
4. Matches the tone and role perfectly
5. Feels like a real person, not an AI

Keep it brief (1-2 sentences) and natural. Don't mention being an AI or assistant.

Examples:
- For coding help: "What's the coding challenge you're working on?"
- For casual movie chat: "I'm always up for talking movies! What's caught your attention lately?"
- For career advice: "Career decisions can be tricky. What's on your mind?"
- For relationship talk: "Relationships are complex. What's going on?"

Generate opening for the context above:""")
        
        try:
            response = self.llm.invoke(opening_prompt.format(**self.conversation_context))
            opening = response.content.strip()
            
            # Clean up any AI-like language
            opening = re.sub(r"As (a|an|your) \w+,?\s*", "", opening)
            opening = re.sub(r"I'm here to \w+", "I'm here", opening)
            
            return opening
            
        except Exception as e:
            # Fallback opening based on role and topic
            role = self.conversation_context.get('role', 'partner')
            topic = self.conversation_context.get('topic', 'this')
            
            fallbacks = [
                f"What's on your mind about {topic}?",
                f"I'm listening. What would you like to discuss?",
                f"Tell me what's going on with {topic}.",
                f"What's the situation?"
            ]
            
            import random
            return random.choice(fallbacks)
    
    def respond(self, user_message: str) -> str:
        """Generate dynamic response based on conversation context"""
        
        if not self.conversation_active:
            return "Let's start a conversation first! Tell me what you'd like to talk about."
        
        # Build conversation history
        history_text = ""
        for exchange in self.chat_history[-5:]:  # Last 5 exchanges
            history_text += f"Human: {exchange['user']}\nMe: {exchange['response']}\n\n"
        
        # Generate contextual response
        response_prompt = ChatPromptTemplate.from_template(
            """You are having a natural conversation with someone. Here's your role:

Role: {role}
Topic Focus: {topic}
Tone: {tone}
Context: {context}
Your Goal: {conversation_goal}
Communication Style: {speaking_style}

Recent conversation:
{history}

They just said: "{user_message}"

Respond naturally as their {role}. Key guidelines:
- Stay true to your role and the conversation topic
- Match the emotional tone of their message
- Be genuinely helpful and engaged
- Ask follow-up questions when appropriate
- Keep responses conversational (1-3 sentences usually)
- Sound like a real person, not an AI
- Adapt your expertise level to the topic
- Show active listening

Generate a natural response:""")
        
        try:
            response = self.llm.invoke(response_prompt.format(
                history=history_text,
                user_message=user_message,
                **self.conversation_context
            ))
            
            response_text = response.content.strip()
            
            # Clean up response
            response_text = re.sub(r"As (a|an|your) \w+,?\s*", "", response_text)
            response_text = re.sub(r"I'm (an AI|an assistant|a bot)", "I'm someone who", response_text)
            
            # Save to history
            self.chat_history.append({
                "user": user_message,
                "response": response_text
            })
            
            return response_text
            
        except Exception as e:
            return self._generate_fallback_response(user_message)
    
    def _generate_fallback_response(self, user_message: str) -> str:
        """Generate intelligent fallback responses"""
        
        message_lower = user_message.lower()
        role = self.conversation_context.get('role', 'friend')
        topic = self.conversation_context.get('topic', 'this')
        
        # Topic-specific fallbacks
        if any(word in message_lower for word in ['problem', 'issue', 'stuck', 'confused']):
            return "That sounds challenging. Can you tell me more about what's happening?"
        
        if any(word in message_lower for word in ['think', 'opinion', 'advice', 'should']):
            return "That's a good question. What factors are you considering?"
        
        if any(word in message_lower for word in ['feel', 'feeling', 'emotion']):
            return "I hear you. Those feelings make sense given the situation."
        
        # General supportive responses
        responses = [
            "Tell me more about that.",
            "What's your take on it?",
            "How are you approaching this?",
            "What's been on your mind about this?",
            "I'm listening. Go on."
        ]
        
        import random
        return random.choice(responses)
    
    def end_conversation(self) -> str:
        """End the current conversation"""
        if self.conversation_active:
            role = self.conversation_context.get('role', 'conversation partner')
            self.conversation_active = False
            self.conversation_context = {}
            self.chat_history = []
            
            return f"Thanks for the great conversation! Feel free to start a new topic anytime."
        
        return "No active conversation to end."
    
    def get_conversation_info(self) -> Dict:
        """Get current conversation context"""
        return self.conversation_context if self.conversation_active else {}

class DynamicConversationApp:
    def __init__(self, groq_api_key: str):
        self.agent = DynamicConversationalAgent(groq_api_key)
    
    def run_conversation(self):
        """Run the dynamic conversation system"""
        
        print("🚀 Dynamic Conversational Agent")
        print("=" * 50)
        print("Tell me what you want to talk about! I can adapt to any topic or role.")
        print("\nExamples:")
        print("• 'I want to discuss my coding problems with a mentor'")
        print("• 'Let's chat about movies as friends'")
        print("• 'I need career advice from someone experienced'")
        print("• 'Talk to me about fitness like a personal trainer'")
        print("• 'I want relationship advice'")
        print("• 'Help me with my business idea'")
        print("• 'Let's discuss philosophy'")
        print("\nType 'new' to start a different conversation, 'quit' to exit")
        print("=" * 50)
        
        while True:
            if not self.agent.conversation_active:
                user_input = input("\n🎯 What would you like to talk about? ").strip()
                
                if user_input.lower() == 'quit':
                    print("👋 Thanks for chatting! See you next time.")
                    break
                
                if user_input:
                    opening = self.agent.start_conversation(user_input)
                    print(f"\n💬 {opening}")
            
            else:
                user_input = input("\nYou: ").strip()
                
                if user_input.lower() == 'quit':
                    print("👋 Thanks for chatting! See you next time.")
                    break
                elif user_input.lower() == 'new':
                    print(self.agent.end_conversation())
                    continue
                elif user_input.lower() in ['end', 'bye']:
                    print(self.agent.end_conversation())
                    continue
                
                if user_input:
                    response = self.agent.respond(user_input)
                    print(f"\n💬 {response}")

def main():
    # Your Groq API key
    GROQ_API_KEY = "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"
    
    try:
        app = DynamicConversationApp(GROQ_API_KEY)
        
        # Example conversations
        print("=== DEMO: Different Conversation Types ===\n")
        
        # Demo 1: Career advice
        print("1️⃣ Career Discussion:")
        agent = DynamicConversationalAgent(GROQ_API_KEY)
        opening = agent.start_conversation("I need career advice about changing jobs")
        print(f"Agent: {opening}")
        response1 = agent.respond("I've been at my current job for 3 years but I'm not growing anymore")
        print(f"Agent: {response1}")
        print()
        
        # Demo 2: Casual tech chat
        print("2️⃣ Tech Discussion:")
        agent2 = DynamicConversationalAgent(GROQ_API_KEY)
        opening2 = agent2.start_conversation("Let's talk about AI and technology casually")
        print(f"Agent: {opening2}")
        response2 = agent2.respond("What do you think about the future of AI?")
        print(f"Agent: {response2}")
        print()
        
        print("=== Starting Interactive Mode ===")
        app.run_conversation()
        
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    main()