"""
Reaction Agent — Community Reaction Simulator Engine
=====================================================
Lấy cảm hứng từ BettaFish ForumEngine + MiroFish simulate_agent.

Simulate phản ứng cộng đồng khi Canifa có chiến dịch mới.
Dùng LLM để generate realistic reactions từ các persona segments.

Model: gpt-5.4-nano (from DEFAULT_MODEL env)
"""

import json
import logging
from typing import Any

from common.llm_factory import create_llm
from config import DEFAULT_MODEL

logger = logging.getLogger(__name__)

# ═══ PERSONA SEGMENTS ═══
PERSONA_SEGMENTS = [
    {
        "id": "mom_shopper",
        "name": "Mom Shopper",
        "desc": "Phụ nữ 30-40t, mua cho gia đình, ưu tiên chất lượng và giá hợp lý",
        "traits": "thực tế, so sánh giá, quan tâm chất liệu và độ bền",
        "tone": "nhẹ nhàng, có emoji, chia sẻ kinh nghiệm",
        "weight": 0.20,
    },
    {
        "id": "young_professional",
        "name": "Young Professional",
        "desc": "Nam/Nữ 25-32t, đi làm văn phòng, thích basic smart casual",
        "traits": "theo dõi sale, thích đồ basic công sở, hay compare brand",
        "tone": "ngắn gọn, lịch sự, đôi khi hỏi thêm chi tiết",
        "weight": 0.20,
    },
    {
        "id": "fashion_enthusiast",
        "name": "Fashion Enthusiast",
        "desc": "Nữ 28-38t, sẵn sàng chi tiền cho item đẹp, follow KOL",
        "traits": "biết về trend, chú ý chất liệu, phong cách, so sánh với Muji/Uniqlo",
        "tone": "hào hứng, dùng từ fashion, nhiều detail",
        "weight": 0.15,
    },
    {
        "id": "budget_conscious",
        "name": "Budget Conscious",
        "desc": "Nam 35-45t, mua khi sale, so sánh giá nhiều brand, thực dụng",
        "traits": "nhạy giá, tính toán, compare kỹ, chờ sale",
        "tone": "phân tích, so sánh số liệu, đôi khi tiêu cực về giá",
        "weight": 0.15,
    },
    {
        "id": "gen_z",
        "name": "Gen Z Trendy",
        "desc": "Nam/Nữ 18-25t, thích local brand, aesthetic, chia sẻ TikTok",
        "traits": "FOMO, trend-driven, visual-first, share trên social",
        "tone": "slang, emoji nhiều, hype, viết tắt",
        "weight": 0.15,
    },
    {
        "id": "kol",
        "name": "KOL / Blogger",
        "desc": "Nữ 25-35t, review sản phẩm chuyên nghiệp, phân tích kỹ",
        "traits": "objective, so sánh chất liệu, phân tích chiến lược brand",
        "tone": "chuyên nghiệp, review dài, phân tích deep",
        "weight": 0.10,
    },
    {
        "id": "troll",
        "name": "Social Media Troll",
        "desc": "Comment nhanh, hay chê, so sánh Uniqlo/Zara, toxic nhẹ",
        "traits": "cynical, so sánh brand ngoại, hay dùng meme",
        "tone": "châm biếm, ngắn, sarcastic, emoji mockery",
        "weight": 0.05,
    },
]

CAMPAIGN_TYPES = {
    "product_launch": "Ra mắt sản phẩm mới",
    "promotion": "Chương trình khuyến mãi / Flash Sale",
    "collection": "Ra mắt Bộ sưu tập (BST)",
    "price_change": "Thay đổi / Tăng giá",
    "social_post": "Bài đăng Social Media",
    "collab": "Hợp tác thương hiệu (Collab)",
}


REACTION_PROMPT = """Bạn là một người Việt Nam thực sự trên mạng xã hội.
Persona: {persona_name} — {persona_desc}
Tính cách: {persona_traits}
Giọng văn: {persona_tone}

Canifa vừa đăng một {campaign_type_label}:
---
{campaign_content}
---

Hãy viết MỘT comment phản ứng tự nhiên như trên Facebook/TikTok.  
Trả về JSON (không markdown):
{{
  "comment": "nội dung comment",
  "sentiment": "positive" | "neutral" | "negative",
  "likes_estimate": <number 1-200>,
  "shares_estimate": <number 0-50>,
  "key_concern": "vấn đề chính quan tâm (nếu có, null nếu không)"
}}
"""


async def simulate_reaction_for_persona(
    persona: dict,
    campaign_type: str,
    campaign_content: str,
    model_name: str | None = None,
) -> dict[str, Any]:
    """Generate a single persona's reaction to a campaign."""
    model = model_name or DEFAULT_MODEL
    llm = create_llm(model, streaming=False)

    prompt = REACTION_PROMPT.format(
        persona_name=persona["name"],
        persona_desc=persona["desc"],
        persona_traits=persona["traits"],
        persona_tone=persona["tone"],
        campaign_type_label=CAMPAIGN_TYPES.get(campaign_type, campaign_type),
        campaign_content=campaign_content,
    )

    try:
        response = await llm.ainvoke([
            {"role": "system", "content": "You are a social media comment generator. Always respond in valid JSON."},
            {"role": "user",   "content": prompt},
        ])
        raw = response.content
        if isinstance(raw, list):
            raw = "".join(str(c.get("text", c) if isinstance(c, dict) else c) for c in raw)

        data = json.loads(raw.strip().removeprefix("```json").removesuffix("```").strip())
        return {
            "persona_id": persona["id"],
            "persona_name": persona["name"],
            "segment": persona["name"],
            **data,
        }
    except Exception as e:
        logger.error(f"❌ [{persona['name']}] Reaction gen failed: {e}")
        return {
            "persona_id": persona["id"],
            "persona_name": persona["name"],
            "segment": persona["name"],
            "comment": f"[Error generating reaction: {e}]",
            "sentiment": "neutral",
            "likes_estimate": 0,
            "shares_estimate": 0,
            "key_concern": None,
        }


async def run_reaction_simulation(
    campaign_type: str,
    campaign_content: str,
    persona_weights: dict[str, float] | None = None,
    model_name: str | None = None,
) -> dict[str, Any]:
    """
    Run full community reaction simulation.

    Args:
        campaign_type: Type of campaign (product_launch, promotion, etc.)
        campaign_content: The campaign text content
        persona_weights: Optional weight overrides for each persona segment
        model_name: LLM model override

    Returns:
        Full simulation results with reactions, sentiment, recommendations
    """
    reactions = []
    segments_used = PERSONA_SEGMENTS.copy()

    # Apply weight overrides
    if persona_weights:
        for seg in segments_used:
            if seg["id"] in persona_weights:
                seg["weight"] = persona_weights[seg["id"]]

    # Generate reactions
    for persona in segments_used:
        logger.info(f"🎭 Simulating: {persona['name']}...")
        result = await simulate_reaction_for_persona(
            persona, campaign_type, campaign_content, model_name
        )
        reactions.append(result)

    # Calculate sentiment
    pos = sum(1 for r in reactions if r.get("sentiment") == "positive")
    neu = sum(1 for r in reactions if r.get("sentiment") == "neutral")
    neg = sum(1 for r in reactions if r.get("sentiment") == "negative")
    total = len(reactions)

    sentiment = {
        "positive": round(pos / total * 100) if total else 0,
        "neutral": round(neu / total * 100) if total else 0,
        "negative": round(neg / total * 100) if total else 0,
        "total_reactions": total,
    }

    # Generate recommendations
    recommendations = _generate_recommendations(reactions, sentiment, campaign_type)

    return {
        "status": "success",
        "campaign_type": campaign_type,
        "reactions": reactions,
        "sentiment": sentiment,
        "recommendations": recommendations,
    }


def _generate_recommendations(
    reactions: list[dict], sentiment: dict, campaign_type: str
) -> list[dict]:
    """Generate actionable recommendations based on reactions."""
    recos = []
    neg_pct = sentiment.get("negative", 0)
    pos_pct = sentiment.get("positive", 0)

    if neg_pct >= 40:
        recos.append({
            "icon": "🚨", "severity": "high",
            "text": "Tỷ lệ tiêu cực CAO (>40%). Cân nhắc điều chỉnh nội dung hoặc delay launch.",
        })
    elif neg_pct >= 20:
        recos.append({
            "icon": "⚠️", "severity": "medium",
            "text": "Có phản ứng tiêu cực đáng kể. Chuẩn bị response template cho team CS.",
        })

    neg_concerns = [r.get("key_concern") for r in reactions
                    if r.get("sentiment") == "negative" and r.get("key_concern")]
    if neg_concerns:
        recos.append({
            "icon": "💡", "severity": "info",
            "text": f"Concerns chính: {', '.join(neg_concerns[:3])}",
        })

    if pos_pct >= 60:
        recos.append({
            "icon": "🚀", "severity": "positive",
            "text": "Tín hiệu tốt! Chiến dịch có tiềm năng viral. Chuẩn bị stock + hạ tầng đơn hàng.",
        })

    recos.append({
        "icon": "📊", "severity": "info",
        "text": "Ưu tiên kênh TikTok/Instagram nếu Gen Z phản ứng tích cực, Facebook nếu Mom Shopper positive.",
    })

    return recos
