"""
AI Trading Agents - Autonomous traders with distinct personalities

Each agent uses Gemini AI (or fallback logic) to make decisions based on:
1. Current market state
2. Recent news/events
3. Their unique trading personality

This creates a realistic market ecosystem with diverse trading styles.
"""

import os
import json
import uuid
import random
import math
from abc import ABC, abstractmethod
from datetime import datetime
from typing import Optional
import google.generativeai as genai

from .world_state import WorldState, NewsEvent, Trade, SocialMediaPost


# Configure Gemini
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")


class AIAgent(ABC):
    """Base class for all AI trading agents"""
    
    def __init__(self, agent_id: str, name: str, firm: str, style: str, avatar: str):
        self.agent_id = agent_id
        self.name = name
        self.firm = firm
        self.style = style
        self.avatar = avatar
        self.cash = 100_000.0
        self.positions = []
        self.trade_count = 0
        
        if GEMINI_API_KEY:
            genai.configure(api_key=GEMINI_API_KEY)
            self.model = genai.GenerativeModel('gemini-1.5-flash')
        else:
            self.model = None
    
    @abstractmethod
    def get_system_prompt(self) -> str:
        pass
    
    @abstractmethod
    async def decide(self, world: WorldState) -> Optional[Trade]:
        pass
    
    def _generate_trade_id(self) -> str:
        self.trade_count += 1
        return f"{self.agent_id}-{self.trade_count}-{uuid.uuid4().hex[:8]}"
    
    async def _call_gemini(self, prompt: str) -> str:
        if not self.model:
            return self._fallback_response(prompt)
        
        try:
            response = await self.model.generate_content_async(
                prompt,
                generation_config=genai.GenerationConfig(
                    temperature=0.8, 
                    max_output_tokens=500,
                    top_p=0.95
                )
            )
            if response and response.text:
                return response.text
            else:
                print("Gemini returned empty response")
                return self._fallback_response(prompt)
        except Exception as e:
            print(f"Gemini API error: {e}")
            return self._fallback_response(prompt)
    
    def _fallback_response(self, prompt: str) -> str:
        return json.dumps({"action": "HOLD", "reasoning": "Analyzing market conditions..."})


class NarratorAgent(AIAgent):
    """Generates market news and events"""
    
    def __init__(self):
        super().__init__("narrator", "Market Wire", "Reuters", "News", "📰")
        self.event_count = 0
    
    def get_system_prompt(self, news_type: str = "mixed") -> str:
        if news_type == "macro":
            return """You are a financial news generator for a multi-company market simulation.
Generate MACROECONOMIC news events that affect the entire market or multiple sectors. Use REAL-WORLD examples as inspiration.

MACRO events include:
- Federal Reserve interest rate decisions, policy changes, forward guidance
- Inflation data (CPI, PCE), employment reports (NFP), GDP growth
- Geopolitical events (trade wars, conflicts, sanctions)
- Currency movements, bond yield changes
- Global economic indicators (PMI, consumer confidence, retail sales)
- Government policy changes (fiscal stimulus, tax policy, regulations)
- Energy prices, commodity markets
- International trade data, balance of payments

Respond with ONLY JSON:
{
    "headline": "Headline (max 80 chars, real-world style)",
    "summary": "2-3 sentence detailed summary with specific numbers/data",
    "impact_score": <-1.0 to 1.0> (overall market impact),
    "volatility_impact": <0.0 to 1.0>,
    "affected_tickers": ["OMEGA", "NEXUS", "TITAN", "PULSE", "VORTX", "QUBIT"] or ["ALL"],
    "category": "macro",
    "duration_ticks": <3-10>
}"""
        elif news_type == "micro":
            return """You are a financial news generator for a multi-company market simulation.
Generate MICROECONOMIC/COMPANY-SPECIFIC news events that affect individual companies. Use REAL-WORLD examples as inspiration.

MICRO events include:
- Earnings beats/misses, guidance changes, revenue surprises
- Product launches, FDA approvals, patent news
- Management changes, strategic initiatives, M&A activity
- Analyst upgrades/downgrades, price target changes
- Supply chain issues, production delays, factory closures
- Competitive threats, market share changes
- Regulatory approvals/rejections, lawsuits, settlements
- Partnerships, joint ventures, licensing deals
- Insider trading, buybacks, dividend changes

Respond with ONLY JSON:
{
    "headline": "Headline (max 80 chars, real-world style)",
    "summary": "2-3 sentence detailed summary with specific numbers/data",
    "impact_score": <-1.0 to 1.0> (company-specific impact),
    "volatility_impact": <0.0 to 1.0>,
    "affected_tickers": ["OMEGA"] or ["NEXUS", "TITAN"] (1-3 specific companies),
    "category": "micro",
    "duration_ticks": <2-7>
}"""
        else:
            return """You are a financial news generator for a multi-company market simulation.
Generate realistic, impactful market news that affects stock prices. Use REAL-WORLD examples as inspiration.

Include both MACRO (market-wide) and MICRO (company-specific) events:
- MACRO: Fed decisions, inflation data, GDP, geopolitical events, policy changes
- MICRO: Earnings, product launches, analyst actions, regulatory news, competitive moves

Respond with ONLY JSON:
{
    "headline": "Headline (max 80 chars, real-world style)",
    "summary": "2-3 sentence detailed summary with specific numbers/data",
    "impact_score": <-1.0 to 1.0> (price impact),
    "volatility_impact": <0.0 to 1.0>,
    "affected_tickers": ["OMEGA", "NEXUS", etc.] or ["ALL"] for macro,
    "category": "macro" or "micro",
    "duration_ticks": <2-10>
}"""
    
    async def decide(self, world: WorldState) -> Optional[Trade]:
        return None
    
    async def generate_event(self, world: WorldState, news_type: str = "mixed") -> NewsEvent:
        self.event_count += 1
        market = world.get_market_summary()
        
        # Randomly choose macro or micro if mixed
        if news_type == "mixed":
            news_type = random.choice(["macro", "micro"])
        
        prompt = f"""{self.get_system_prompt(news_type)}

Current Market State:
- {market['ticker']}: ${market['price']:.2f}, {market['price_change_pct']:+.1f}%
- Overall Sentiment: {market['sentiment']}
- Market Volatility: {market['volatility']}%

Generate a {news_type.upper()} news event fitting current conditions. Use real-world examples as inspiration.
IMPORTANT: Generate BOTH positive AND negative news. If prices are high, generate bearish news. If prices are low, generate bullish news.
Make it specific with numbers/data. 
impact_score MUST be between -1.0 and 1.0. Use NEGATIVE values for bearish news (rate hikes, inflation, earnings misses, etc.).
JSON only:"""

        response = await self._call_gemini(prompt)
        
        try:
            clean = response.strip()
            # Remove markdown code blocks if present
            if "```json" in clean:
                clean = clean.split("```json")[1].split("```")[0].strip()
            elif "```" in clean:
                clean = clean.split("```")[1].split("```")[0].strip()
                if clean.startswith("json"):
                    clean = clean[4:].strip()
            
            # Try to parse JSON
            data = json.loads(clean)
            
            # Validate required fields
            headline = data.get("headline", "").strip()
            summary = data.get("summary", "").strip()
            
            if not headline or len(headline) < 10:
                print("Invalid headline from AI, using fallback")
                return self._generate_fallback_news(news_type)
            
            # Extract category and affected tickers - ENFORCE the requested type
            category = news_type  # Use the requested type, not what AI returned
            if category not in ["macro", "micro"]:
                category = "macro" if "macro" in category.lower() else "micro"
            
            affected_tickers = data.get("affected_tickers", [])
            if isinstance(affected_tickers, str):
                affected_tickers = [affected_tickers]
            
            # FORCE macro news to have "ALL", micro to have specific tickers
            if category == "macro":
                affected_tickers = ["ALL"]  # Macro always affects all
            elif not affected_tickers or "ALL" in affected_tickers:
                # If micro news has ALL or empty, assign to random tickers
                all_tickers = ["OMEGA", "NEXUS", "TITAN", "PULSE", "VORTX", "QUBIT"]
                affected_tickers = random.sample(all_tickers, random.randint(1, 2))
            
            return NewsEvent(
                id=f"news-{self.event_count}-{uuid.uuid4().hex[:6]}",
                timestamp=datetime.now(),
                headline=headline[:100],  # Limit length
                summary=summary[:500] if summary else "Market update.",
                impact_score=float(data.get("impact_score", 0)),
                volatility_impact=float(data.get("volatility_impact", 0.2)),
                source="Market Wire",
                category=category,
                affected_tickers=affected_tickers[:6],  # Limit to 6 tickers
                duration_ticks=int(data.get("duration_ticks", 5))
            )
        except json.JSONDecodeError as e:
            print(f"JSON parse error: {e}")
            print(f"Response was: {response[:200]}")
            return self._generate_fallback_news(news_type)
        except Exception as e:
            print(f"Error generating news: {e}")
            return self._generate_fallback_news(news_type)
    
    def _generate_fallback_news(self, news_type: str = "mixed") -> NewsEvent:
        # Expanded news events with macro and micro categories
        if news_type == "macro" or (news_type == "mixed" and random.random() > 0.5):
            # MACRO events
            macro_headlines = [
                ("Fed Cuts Rates 25bps, Signals More Easing Ahead", 0.4, 0.45, "Federal Reserve lowers target rate to 4.75%. Dot plot suggests 2 more cuts this year. Markets rally on dovish pivot.", ["ALL"], "macro", 8),
                ("CPI Rises 0.3% MoM, Core Inflation Sticky at 3.8%", -0.3, 0.4, "Consumer prices accelerate faster than expected. Services inflation remains elevated. Rate cut expectations pushed back.", ["ALL"], "macro", 6),
                ("Non-Farm Payrolls Surge 275K, Unemployment at 3.7%", 0.25, 0.3, "Job market remains robust despite Fed tightening. Wage growth moderates to 4.1% YoY. Mixed signals for policy.", ["ALL"], "macro", 5),
                ("GDP Growth Slows to 1.8% in Q4, Below 2.5% Forecast", -0.35, 0.4, "Economic expansion decelerates as consumer spending weakens. Recession fears resurface. Defensive sectors outperform.", ["ALL"], "macro", 7),
                ("Oil Prices Spike 8% on Middle East Tensions", -0.2, 0.5, "Geopolitical conflict disrupts supply routes. Energy costs surge, pressuring margins across industries. Inflation concerns mount.", ["ALL"], "macro", 6),
                ("Dollar Index Hits 20-Year High, Emerging Markets Suffer", -0.25, 0.35, "Strong dollar crushes export competitiveness. Foreign debt servicing costs surge. Capital flight accelerates.", ["ALL"], "macro", 5),
                ("China Trade Data Disappoints, Global Growth Concerns", -0.3, 0.4, "Exports fall 6.2% YoY, imports drop 4.8%. Manufacturing PMI contracts. Supply chain disruptions intensify.", ["ALL"], "macro", 6),
                ("ECB Holds Rates, Hints at June Cut", 0.2, 0.3, "European Central Bank maintains 4.5% rate but signals dovish shift. Euro weakens. European equities rally.", ["ALL"], "macro", 5),
                ("Government Announces $500B Infrastructure Package", 0.3, 0.35, "Massive spending bill targets green energy and tech. Industrial and construction stocks surge. Inflationary impact debated.", ["ALL"], "macro", 8),
                ("Bond Yields Invert Further, Recession Signal Strengthens", -0.4, 0.45, "10Y-2Y spread widens to -0.8%. Historical accuracy of inversion raises alarm. Defensive rotation accelerates.", ["ALL"], "macro", 7),
            ]
            headline, impact, vol, summary, affected, category, duration = random.choice(macro_headlines)
        else:
            # MICRO events
            all_tickers = ["OMEGA", "NEXUS", "TITAN", "PULSE", "VORTX", "QUBIT"]
            affected = random.sample(all_tickers, random.randint(1, 2))
            ticker_str = affected[0] if len(affected) == 1 else "Tech Sector"
            
            micro_headlines = [
                (f"{ticker_str} Beats Q4 Earnings, Revenue Up 18% YoY", 0.4, 0.35, f"EPS of $2.45 beats $2.20 estimate. Management raises full-year guidance. Strong demand across segments.", affected, "micro", 5),
                (f"{ticker_str} Misses Revenue by 5%, Cuts Guidance", -0.35, 0.4, f"Q4 revenue $850M vs $895M expected. Management cites supply chain and weak demand. Stock plunges 12%.", affected, "micro", 6),
                (f"{ticker_str} Announces $2B Stock Buyback Program", 0.25, 0.25, f"Board authorizes 10% share repurchase over 12 months. Signals confidence in undervaluation. EPS accretion expected.", affected, "micro", 4),
                (f"{ticker_str} FDA Approves Breakthrough Drug Application", 0.45, 0.4, f"Regulatory green light for blockbuster treatment. $500M peak sales potential. Stock jumps 18% pre-market.", affected, "micro", 6),
                (f"{ticker_str} CEO Resigns, Succession Plan Unclear", -0.3, 0.4, f"Leadership transition creates uncertainty. No immediate replacement named. Analysts downgrade on execution risk.", affected, "micro", 5),
                (f"{ticker_str} Launches AI Product, Pre-Orders Hit $100M", 0.35, 0.3, f"Revolutionary AI platform exceeds expectations. Enterprise demand strong. Competitive moat widens.", affected, "micro", 5),
                (f"{ticker_str} Faces Class-Action Lawsuit Over Data Breach", -0.25, 0.35, f"Security incident affects 2M users. Regulatory scrutiny intensifies. Potential $50M liability.", affected, "micro", 5),
                (f"{ticker_str} Goldman Upgrades to Buy, PT Raised to $150", 0.3, 0.3, f"Analyst cites strong fundamentals and market share gains. Valuation attractive vs peers. Momentum building.", affected, "micro", 4),
                (f"{ticker_str} Supply Chain Disruption Delays Product Launch", -0.28, 0.38, f"Component shortages push launch 6 months. Revenue guidance cut $200M. Margins compressed.", affected, "micro", 6),
                (f"{ticker_str} Strategic Acquisition of Competitor for $1.5B", 0.3, 0.35, f"Synergies of $150M expected. Market share increases 8%. Integration risks remain.", affected, "micro", 6),
            ]
            headline, impact, vol, summary, affected, category, duration = random.choice(micro_headlines)
        
        self.event_count += 1
        
        return NewsEvent(
            id=f"news-{self.event_count}-{uuid.uuid4().hex[:6]}",
            timestamp=datetime.now(),
            headline=headline,
            summary=summary,
            impact_score=impact + random.uniform(-0.1, 0.1),
            volatility_impact=vol,
            source="Market Wire",
            category=category,
            affected_tickers=affected,
            duration_ticks=duration
        )
    
    def _fallback_response(self, prompt: str) -> str:
        # This should not be used for news generation - use _generate_fallback_news() instead
        # But if called, return a random news item
        import random
        headlines = [
            ("Omegacorp Beats Q4 Earnings, Raises Guidance", 0.4, 0.3, "Revenue up 15% YoY, management raises full-year outlook."),
            ("Fed Holds Rates Steady, Signals Dovish Pivot", 0.35, 0.4, "Central bank keeps rates unchanged, hints at potential cuts."),
            ("Tech Sector Rally Continues on AI Optimism", 0.3, 0.35, "Major tech stocks surge as AI adoption accelerates."),
            ("Supply Chain Disruption Hits Manufacturing", -0.25, 0.4, "Port delays and component shortages impact production."),
            ("Goldman Upgrades Omegacorp to Buy", 0.25, 0.3, "Price target raised to $120. Analyst cites strong fundamentals."),
        ]
        headline, impact, vol, summary = random.choice(headlines)
        return json.dumps({
            "headline": headline,
            "summary": summary,
            "impact_score": impact + random.uniform(-0.1, 0.1),
            "volatility_impact": vol
        })


class TradingAgent(AIAgent):
    """Base class for trading agents"""
    
    def get_decision_prompt(self, world: WorldState) -> str:
        market = world.get_market_summary()
        
        return f"""{self.get_system_prompt()}

MARKET: {market['ticker']} @ ${market['price']:.2f} ({market['price_change_pct']:+.1f}%)
IV: {market['volatility']}%, Sentiment: {market['sentiment']}

Recent News: {json.dumps([n['headline'] for n in market['recent_news'][:2]])}

Your cash: ${self.cash:,.0f}

Respond with ONLY JSON:
{{"action": "BUY" or "SELL", "quantity": <100-1000 shares>, "reasoning": "<your reasoning in character>"}}
Or {{"action": "HOLD", "quantity": 0, "reasoning": "<why holding>"}}"""
    
    async def decide(self, world: WorldState) -> Optional[Trade]:
        prompt = self.get_decision_prompt(world)
        response = await self._call_gemini(prompt)
        
        try:
            clean = response.strip()
            if "```" in clean:
                clean = clean.split("```")[1].replace("json", "").strip()
            
            data = json.loads(clean)
            action = data.get("action", "HOLD").upper()
            
            if action == "HOLD":
                return None
            
            quantity = min(1000, max(100, int(data.get("quantity", 100))))
            reasoning = data.get("reasoning", "Market opportunity identified.")
            
            return Trade(
                id=self._generate_trade_id(),
                timestamp=datetime.now(),
                agent_id=self.agent_id,
                agent_name=self.name,
                agent_firm=self.firm,
                agent_avatar=self.avatar,
                action=action,
                quantity=quantity,
                price=world.price,
                reasoning=reasoning,
                ticker=world.ticker  # Include ticker in trade
            )
        except Exception as e:
            return None


# ============================================
# INDIVIDUAL TRADERS WITH PERSONALITIES
# ============================================

class MichaelChen(TradingAgent):
    """Momentum trader at Velocity Capital"""
    
    def __init__(self):
        super().__init__("michael_chen", "Michael Chen", "Velocity Capital", "Momentum", "📈")
    
    def get_system_prompt(self) -> str:
        return """You are Michael Chen, aggressive momentum trader at Velocity Capital.
You chase trends, buy strength, sell weakness. You're confident and use terms like "ripping", "pumping".
High conviction on breakouts. Risk tolerance: HIGH."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.6:
            return json.dumps({"action": "BUY", "quantity": random.randint(300, 800), "reasoning": "Momentum building, riding this wave higher!"})
        elif r > 0.3:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "Waiting for cleaner setup."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(200, 500), "reasoning": "Trend breaking down, cutting exposure."})


class VictoriaShaw(TradingAgent):
    """Value investor at Deepwater"""
    
    def __init__(self):
        super().__init__("victoria_shaw", "Victoria Shaw", "Deepwater Investments", "Value", "🎯")
    
    def get_system_prompt(self) -> str:
        return """You are Victoria Shaw, patient value investor at Deepwater Investments.
You buy quality at reasonable prices, sell overvalued names. Contrarian mindset.
You speak calmly about "intrinsic value" and "margin of safety". Risk tolerance: LOW."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.7:
            return json.dumps({"action": "BUY", "quantity": random.randint(200, 400), "reasoning": "Valuation compelling at current levels. Adding to core position."})
        elif r > 0.2:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "Patience. Waiting for margin of safety."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(100, 300), "reasoning": "Trimming as we approach fair value estimate."})


class QuinnRodriguez(TradingAgent):
    """Quant trader at Systematic Alpha"""
    
    def __init__(self):
        super().__init__("quinn_rodriguez", "Quinn Rodriguez", "Systematic Alpha", "Quantitative", "🤖")
    
    def get_system_prompt(self) -> str:
        return """You are Quinn Rodriguez, quantitative trader at Systematic Alpha.
You trade based on signals, mean reversion, and statistical arbitrage.
You speak in terms of "alpha", "z-scores", "signals". Emotionless, data-driven. Risk: MEDIUM."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.55:
            return json.dumps({"action": "BUY", "quantity": random.randint(400, 700), "reasoning": "Signal triggered. Z-score indicates mean reversion opportunity."})
        elif r > 0.25:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "No actionable signal. Staying flat."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(300, 600), "reasoning": "Overbought signal. Reducing position per model."})


class HannahPark(TradingAgent):
    """Risk manager at Citadel Partners"""
    
    def __init__(self):
        super().__init__("hannah_park", "Hannah Park", "Citadel Partners", "Risk Management", "🛡️")
    
    def get_system_prompt(self) -> str:
        return """You are Hannah Park, risk manager at Citadel Partners.
You focus on hedging, downside protection, and portfolio risk.
You worry about tail risks. Cautious language. Risk tolerance: VERY LOW."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.75:
            return json.dumps({"action": "BUY", "quantity": random.randint(100, 300), "reasoning": "Adding hedge. Tail risk elevated in current environment."})
        elif r > 0.3:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "Hedge ratio adequate. Monitoring conditions."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(100, 200), "reasoning": "Reducing exposure. Risk metrics uncomfortable."})


class SamuelWright(TradingAgent):
    """Swing trader at Apex Trading"""
    
    def __init__(self):
        super().__init__("samuel_wright", "Samuel Wright", "Apex Trading", "Swing Trading", "⚡")
    
    def get_system_prompt(self) -> str:
        return """You are Samuel Wright, swing trader at Apex Trading.
You catch 2-5 day moves, trade support/resistance. Technical analysis focused.
You talk about "levels", "breakouts", "retests". Risk tolerance: MEDIUM-HIGH."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.5:
            return json.dumps({"action": "BUY", "quantity": random.randint(300, 600), "reasoning": "Holding above key support. Initiating swing long."})
        elif r > 0.2:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "In no-man's land. Waiting for cleaner levels."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(200, 500), "reasoning": "Rejected at resistance. Taking profits."})


class AlexNakamura(TradingAgent):
    """Arbitrage trader"""
    
    def __init__(self):
        super().__init__("alex_nakamura", "Alex Nakamura", "Arbitrage Capital", "Arbitrage", "🔄")
    
    def get_system_prompt(self) -> str:
        return """You are Alex Nakamura, arbitrage trader at Arbitrage Capital.
You exploit pricing inefficiencies, pairs trades, and relative value.
Speak about "spreads", "convergence", "mispricing". Risk: LOW-MEDIUM."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.6:
            return json.dumps({"action": "BUY", "quantity": random.randint(200, 500), "reasoning": "Spread widened. Taking convergence position."})
        elif r > 0.3:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "No clear mispricing. Standing aside."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(200, 400), "reasoning": "Closing arb leg as spread normalizes."})


class EmmaThompson(TradingAgent):
    """Growth investor"""
    
    def __init__(self):
        super().__init__("emma_thompson", "Emma Thompson", "Horizon Growth Fund", "Growth", "🌱")
    
    def get_system_prompt(self) -> str:
        return """You are Emma Thompson, growth investor at Horizon Growth Fund.
You invest in high-growth companies, focus on revenue growth and TAM.
Long-term oriented, talk about "runway", "scalability". Risk: MEDIUM."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.55:
            return json.dumps({"action": "BUY", "quantity": random.randint(300, 600), "reasoning": "Growth trajectory intact. Adding to position."})
        elif r > 0.2:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "Long-term thesis unchanged. Staying invested."})
        else:
            return json.dumps({"action": "SELL", "quantity": random.randint(100, 300), "reasoning": "Rebalancing. Taking some profits on strength."})


class RajPatel(TradingAgent):
    """Options specialist"""
    
    def __init__(self):
        super().__init__("raj_patel", "Raj Patel", "Volatility Partners", "Options", "📊")
    
    def get_system_prompt(self) -> str:
        return """You are Raj Patel, options specialist at Volatility Partners.
You trade vol, sell premium when IV high, buy when low.
Speak about "Greeks", "IV rank", "theta decay". Risk: MEDIUM."""
    
    def _fallback_response(self, prompt: str) -> str:
        r = random.random()
        if r > 0.5:
            return json.dumps({"action": "SELL", "quantity": random.randint(200, 400), "reasoning": "IV elevated. Selling premium."})
        elif r > 0.2:
            return json.dumps({"action": "HOLD", "quantity": 0, "reasoning": "Vol fair valued. No edge."})
        else:
            return json.dumps({"action": "BUY", "quantity": random.randint(300, 500), "reasoning": "IV crushed. Buying cheap gamma."})


class SocialMediaAgent(AIAgent):
    """Generates social media posts from different economic perspectives"""
    
    def __init__(self):
        super().__init__("social_media", "Social Media", "Market Pulse", "Commentary", "💬")
        self.post_count = 0
        
        # Define personas with different economic perspectives
        self.personas = [
            # Traders
            {"name": "Michael Chen", "type": "trader", "affiliation": "Velocity Capital", "avatar": "📈", 
             "perspective": "momentum", "style": "Aggressive, uses terms like 'ripping', 'pumping'. High conviction."},
            {"name": "Victoria Shaw", "type": "trader", "affiliation": "Deepwater Investments", "avatar": "🎯", 
             "perspective": "value", "style": "Patient, talks about 'intrinsic value', 'margin of safety'. Contrarian."},
            {"name": "Dr. Sarah Kim", "type": "economist", "affiliation": "Federal Reserve", "avatar": "🏛️", 
             "perspective": "keynesian", "style": "Believes in fiscal stimulus, government intervention. Focuses on aggregate demand."},
            {"name": "Prof. James Rothbard", "type": "economist", "affiliation": "Austrian Economics Institute", "avatar": "📚", 
             "perspective": "austrian", "style": "Free market advocate, opposes central banking. Believes in business cycle theory."},
            {"name": "Sen. Maria Rodriguez", "type": "politician", "affiliation": "Democratic Party", "avatar": "🏛️", 
             "perspective": "progressive", "style": "Advocates for regulation, consumer protection, wealth redistribution."},
            {"name": "Rep. David Mitchell", "type": "politician", "affiliation": "Republican Party", "avatar": "🏛️", 
             "perspective": "conservative", "style": "Free market, deregulation, lower taxes. Pro-business."},
            {"name": "Dr. Alan Greenspan", "type": "economist", "affiliation": "Monetarist School", "avatar": "💰", 
             "perspective": "monetarist", "style": "Focuses on money supply, inflation control. Believes in monetary policy."},
            {"name": "Alexandra Minsky", "type": "economist", "affiliation": "Post-Keynesian Institute", "avatar": "📊", 
             "perspective": "minsky", "style": "Financial instability hypothesis. Warns about debt cycles and bubbles."},
        ]
    
    def get_system_prompt(self) -> str:
        return """You are a financial commentator on social media."""
    
    async def decide(self, world: WorldState) -> Optional[Trade]:
        return None
    
    async def generate_post(self, news_event: NewsEvent, world: WorldState) -> SocialMediaPost:
        """Generate a social media post reacting to news"""
        self.post_count += 1
        
        # Select a random persona
        persona = random.choice(self.personas)
        
        market = world.get_market_summary()
        
        prompt = f"""You are {persona['name']}, a {persona['type']} at {persona['affiliation']}.
Your economic perspective: {persona['perspective']}
Your style: {persona['style']}

Recent News: {news_event.headline}
Summary: {news_event.summary}
Market Impact: {news_event.impact_score:.2f}

Current Market: {market['ticker']} @ ${market['price']:.2f}, {market['price_change_pct']:+.1f}%

Write a social media post (2-3 sentences, max 280 chars) reacting to this news from your economic perspective.
Be substantive, academic, and reference your economic views. Use real-world examples.

Respond with ONLY JSON:
{{
    "content": "Your post content (max 280 chars)",
    "sentiment": <-1.0 to 1.0> (your reaction sentiment)
}}"""

        response = await self._call_gemini(prompt)
        
        try:
            clean = response.strip()
            if "```json" in clean:
                clean = clean.split("```json")[1].split("```")[0].strip()
            elif "```" in clean:
                clean = clean.split("```")[1].split("```")[0].strip()
                if clean.startswith("json"):
                    clean = clean[4:].strip()
            
            data = json.loads(clean)
            content = data.get("content", "").strip()
            sentiment = float(data.get("sentiment", 0))
            
            if not content or len(content) < 20:
                return self._generate_fallback_post(news_event, persona)
            
            return SocialMediaPost(
                id=f"post-{self.post_count}-{uuid.uuid4().hex[:6]}",
                timestamp=datetime.now(),
                author=persona["name"],
                author_type=persona["type"],
                author_affiliation=persona["affiliation"],
                author_avatar=persona["avatar"],
                economic_perspective=persona["perspective"],
                content=content[:280],
                related_news_id=news_event.id,
                sentiment=sentiment
            )
        except Exception as e:
            print(f"Error generating social media post: {e}")
            return self._generate_fallback_post(news_event, persona)
    
    def _generate_fallback_post(self, news_event: NewsEvent, persona: dict) -> SocialMediaPost:
        """Generate fallback post with more variety"""
        self.post_count += 1
        
        # Add randomness to make posts more varied
        import random
        rand_suffix = random.randint(1, 1000)
        
        # More varied perspectives with different angles
        perspective_templates = {
            "keynesian": [
                f"This {news_event.headline.lower()} reinforces the need for countercyclical fiscal policy. Government intervention can stabilize aggregate demand.",
                f"{news_event.headline} - Classic case for Keynesian stimulus. When private demand falters, public spending must fill the gap.",
                f"The {news_event.headline.lower()} shows why we need active fiscal policy. Markets don't self-correct quickly enough.",
            ],
            "austrian": [
                f"{news_event.headline} - Another example of market distortion from central planning. Free markets would self-correct without intervention.",
                f"This {news_event.headline.lower()} is a symptom of malinvestment from artificial credit expansion. The business cycle theory explains this perfectly.",
                f"{news_event.headline} - Central bank manipulation creates these distortions. Let markets clear naturally.",
            ],
            "monetarist": [
                f"The {news_event.headline.lower()} highlights the importance of stable money supply growth. Inflation expectations matter more than rates.",
                f"{news_event.headline} - This is why we need predictable monetary policy. Money supply rules, not discretion.",
                f"The {news_event.headline.lower()} reflects monetary policy transmission. Watch M2 growth, not just rates.",
            ],
            "minsky": [
                f"{news_event.headline} - This is classic financial instability. Debt cycles are building. Watch for the Ponzi phase.",
                f"The {news_event.headline.lower()} fits Minsky's instability hypothesis. Stability breeds instability. We're in the speculative phase.",
                f"{news_event.headline} - Financial fragility is increasing. The system is moving toward Ponzi finance. Dangerous.",
            ],
            "progressive": [
                f"{news_event.headline} shows why we need stronger regulation. Markets need guardrails to protect consumers and workers.",
                f"This {news_event.headline.lower()} demonstrates market failure. We need progressive policies to ensure fair outcomes.",
                f"{news_event.headline} - Another example of why we need wealth redistribution and stronger social safety nets.",
            ],
            "conservative": [
                f"{news_event.headline} - This is why we need less regulation, not more. Free markets allocate resources efficiently.",
                f"The {news_event.headline.lower()} shows government overreach. Deregulation and tax cuts would solve this.",
                f"{news_event.headline} - Classic case for supply-side economics. Lower taxes and less regulation boost growth.",
            ],
            "value": [
                f"{news_event.headline} - Market overreaction creates opportunities. Focus on intrinsic value, not short-term noise.",
                f"This {news_event.headline.lower()} is noise. True value investors ignore sentiment and focus on fundamentals.",
                f"{news_event.headline} - Price and value are diverging. Time to buy quality at a discount. Margin of safety expanding.",
            ],
            "momentum": [
                f"{news_event.headline} - This is HUGE! Momentum building. The trend is your friend. Riding this wave! 🚀",
                f"The {news_event.headline.lower()} is breaking out! Volume confirms. This is the move. All aboard! 📈",
                f"{news_event.headline} - Momentum traders are piling in. Don't fight the trend. This is just getting started! 💪",
            ]
        }
        
        templates = perspective_templates.get(persona["perspective"], [f"{news_event.headline} - Interesting development. Markets will price this in."])
        content = random.choice(templates)
        
        # Add unique identifier to prevent exact duplicates
        if rand_suffix % 3 == 0:
            content = content.replace(".", f". (Analysis #{rand_suffix % 100})", 1)
        
        return SocialMediaPost(
            id=f"post-{self.post_count}-{uuid.uuid4().hex[:6]}",
            timestamp=datetime.now(),
            author=persona["name"],
            author_type=persona["type"],
            author_affiliation=persona["affiliation"],
            author_avatar=persona["avatar"],
            economic_perspective=persona["perspective"],
            content=content[:280],
            related_news_id=news_event.id,
            sentiment=news_event.impact_score * (0.5 + random.uniform(-0.3, 0.3))  # Add randomness to sentiment
        )


def create_agent_swarm() -> dict[str, AIAgent]:
    """Create all agents for the simulation"""
    return {
        "narrator": NarratorAgent(),
        "social_media": SocialMediaAgent(),
        "michael_chen": MichaelChen(),
        "victoria_shaw": VictoriaShaw(),
        "quinn_rodriguez": QuinnRodriguez(),
        "hannah_park": HannahPark(),
        "samuel_wright": SamuelWright(),
        "alex_nakamura": AlexNakamura(),
        "emma_thompson": EmmaThompson(),
        "raj_patel": RajPatel(),
    }
