"""
User Simulator Route
AI đóng vai từng persona để test chatbot, đánh giá từ góc nhìn user thật.

Flow:
1. generate-message: Persona AI (Gemini) tạo câu hỏi như user thật
2. chat-with-bot: Gọi chatbot API remote → lấy trả lời
3. evaluate: Gemini đánh giá conversation từ góc persona
4. synthesize: Tổng hợp kết quả tất cả personas
"""

import json
import logging
from typing import Any

import httpx
from fastapi import APIRouter
from fastapi.responses import JSONResponse
from pydantic import BaseModel

from common.llm_factory import create_llm
from config import DEFAULT_MODEL

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/user-simulator", tags=["User Simulator"])

CHATBOT_API_URL = "http://172.16.2.207:5000/api/agent/chat-dev"
LLM_MODEL = DEFAULT_MODEL  # Gemini Flash-Lite


# ═══ Request Models ═══
class GenerateMessageRequest(BaseModel):
    persona_system: str  # System prompt for persona role-play
    persona_name: str
    turn: int = 0  # Current turn number
    history: list[dict[str, str]] = []  # [{role, content}]
    last_bot_reply: str = ""  # Chatbot's last reply (for follow-up)


class ChatWithBotRequest(BaseModel):
    message: str  # User message to send to chatbot


class EvaluateRequest(BaseModel):
    persona_name: str
    persona_age: int
    persona_archetype: str
    persona_trait: str
    conversation: list[dict[str, str]]  # [{role, content}]


class SynthesizeRequest(BaseModel):
    chatbot_prompt: str
    results: list[dict[str, Any]]  # [{persona_name, scores, key_wins, key_fails, prompt_fix}]


# ═══ 1. GENERATE MESSAGE — Persona AI tạo tin nhắn ═══
@router.post("/generate-message", summary="Persona AI generates a message")
async def generate_message(req: GenerateMessageRequest):
    """
    Persona AI (Gemini) đóng vai user, tạo tin nhắn tiếp theo.
    """
    try:
        llm = create_llm(LLM_MODEL, streaming=False)

        messages = [{"role": "system", "content": req.persona_system}]

        if req.turn == 0:
            messages.append({
                "role": "user",
                "content": f"Bạn sẽ bắt đầu chat với một chatbot thời trang Canifa. "
                           f"Hãy gửi tin nhắn đầu tiên như {req.persona_name}. "
                           f"Chỉ gửi 1 tin nhắn ngắn, tự nhiên, đúng tính cách. KHÔNG giải thích vai trò."
            })
        else:
            # Build conversation context
            for h in req.history:
                messages.append(h)
            messages.append({
                "role": "user",
                "content": f'Chatbot Canifa vừa trả lời: "{req.last_bot_reply[:500]}"\n\n'
                           f"Dựa vào response trên, hãy tiếp tục cuộc trò chuyện như {req.persona_name}. "
                           f"Chỉ gửi 1 tin nhắn ngắn. KHÔNG giải thích, KHÔNG nhắc lại prompt."
            })

        response = await llm.ainvoke(messages)

        raw = response.content
        if isinstance(raw, list):
            raw = "".join(str(c.get("text", c) if isinstance(c, dict) else c) for c in raw)

        return {"status": "success", "message": raw.strip()}

    except Exception as e:
        logger.error(f"Generate message error: {e}", exc_info=True)
        return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})


# ═══ 2. CHAT WITH BOT — Forward to chatbot API ═══
@router.post("/chat-with-bot", summary="Send message to chatbot API")
async def chat_with_bot(req: ChatWithBotRequest):
    """
    Gọi chatbot API remote (172.16.2.207:5000) lấy câu trả lời.
    """
    try:
        async with httpx.AsyncClient(timeout=60) as client:
            resp = await client.post(
                CHATBOT_API_URL,
                json={"user_query": req.message},
                headers={"Content-Type": "application/json"},
            )
            resp.raise_for_status()
            data = resp.json()

        if data.get("status") != "success":
            raise ValueError(data.get("message", "Chatbot API error"))

        return {
            "status": "success",
            "reply": data.get("ai_response", ""),
            "trace_id": data.get("trace_id", ""),
        }
    except httpx.HTTPStatusError as e:
        logger.error(f"Chatbot API error: {e}")
        return JSONResponse(status_code=502, content={"status": "error", "message": f"Chatbot: {e.response.status_code}"})
    except Exception as e:
        logger.error(f"Chat with bot error: {e}", exc_info=True)
        return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})


# ═══ 3. EVALUATE — Score conversation from persona's POV ═══
EVAL_SYSTEM = """You are a UX evaluator. You just observed a conversation between a simulated user persona and a chatbot.
Rate the chatbot's performance from the PERSONA'S perspective.

Score each metric 1.0–5.0 (one decimal):
- clarity: Was the chatbot easy to understand for this type of user?
- helpfulness: Did it actually solve the user's problem?
- naturalness: Did the conversation feel natural and human?
- task_completion: Did the user achieve what they came for?
- satisfaction: Overall, would this user be satisfied?

Also provide:
- key_wins: 1-2 things the chatbot did well (array of strings, in Vietnamese)
- key_fails: 1-2 specific failures for THIS persona type (array of strings, in Vietnamese)
- prompt_fix: One concrete prompt instruction to fix the biggest issue (string, in Vietnamese)

Respond ONLY valid JSON:
{
  "scores": {"clarity":0.0,"helpfulness":0.0,"naturalness":0.0,"task_completion":0.0,"satisfaction":0.0},
  "key_wins": ["..."],
  "key_fails": ["..."],
  "prompt_fix": "..."
}"""


@router.post("/evaluate", summary="Evaluate conversation from persona POV")
async def evaluate_conversation(req: EvaluateRequest):
    """
    Gemini đánh giá chatbot từ góc nhìn persona.
    """
    try:
        conv_text = "\n".join(
            f"{'Persona' if m['role'] == 'user' else 'Chatbot'}: {m['content']}"
            for m in req.conversation
        )

        eval_input = f"""Persona: {req.persona_name} ({req.persona_age} tuổi, {req.persona_archetype})
Persona traits: {req.persona_trait}

Conversation:
{conv_text}

Evaluate the chatbot's performance from {req.persona_name}'s perspective."""

        llm = create_llm(LLM_MODEL, streaming=False, json_mode=True)
        response = await llm.ainvoke([
            {"role": "system", "content": EVAL_SYSTEM},
            {"role": "user", "content": eval_input},
        ])

        raw = response.content
        if isinstance(raw, list):
            raw = "".join(str(c.get("text", c) if isinstance(c, dict) else c) for c in raw)

        result = json.loads(raw)
        return {"status": "success", **result}

    except Exception as e:
        logger.error(f"Evaluate error: {e}", exc_info=True)
        return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})


# ═══ 4. SYNTHESIZE — Cross-persona insights ═══
SYNTHESIS_SYSTEM = """You are a senior UX researcher. Analyze simulation results across multiple user personas and provide actionable insights.

Given scores and findings from all personas, identify:
1. Which persona groups are underserved (lowest scores)
2. What are the 2-3 systemic issues in the chatbot prompt
3. What are the 2-3 prompt improvements that would help the most personas

Respond ONLY valid JSON:
{
  "worst_personas": ["persona names with lowest scores"],
  "systemic_issues": ["issue 1 in Vietnamese", "issue 2", "issue 3"],
  "top_fixes": [
    {"title": "Fix title", "instruction": "Concrete prompt instruction in Vietnamese", "impacts": ["Persona1","Persona2"]},
    {"title": "Fix title", "instruction": "Concrete prompt instruction", "impacts": ["Persona1"]},
    {"title": "Fix title", "instruction": "Concrete prompt instruction", "impacts": ["Persona1","Persona2","Persona3"]}
  ],
  "overall_score": 0.0,
  "summary": "2-3 sentence executive summary in Vietnamese"
}"""


@router.post("/synthesize", summary="Cross-persona synthesis")
async def synthesize_results(req: SynthesizeRequest):
    """
    Tổng hợp kết quả từ tất cả personas → insights + prompt fixes.
    """
    try:
        summaries = []
        for r in req.results:
            scores = r.get("scores", {})
            ov = sum(scores.values()) / max(len(scores), 1)
            summaries.append(
                f"{r.get('persona_name', '?')} ({r.get('archetype', '?')}): overall {ov:.1f}/5\n"
                f"  Scores: {json.dumps(scores)}\n"
                f"  Wins: {'; '.join(r.get('key_wins', []))}\n"
                f"  Fails: {'; '.join(r.get('key_fails', []))}"
            )

        synth_input = f"""Chatbot prompt: "{req.chatbot_prompt[:1000]}"

Results across {len(req.results)} personas:
{chr(10).join(summaries)}

Provide synthesis and top fixes."""

        llm = create_llm(LLM_MODEL, streaming=False, json_mode=True)
        response = await llm.ainvoke([
            {"role": "system", "content": SYNTHESIS_SYSTEM},
            {"role": "user", "content": synth_input},
        ])

        raw = response.content
        if isinstance(raw, list):
            raw = "".join(str(c.get("text", c) if isinstance(c, dict) else c) for c in raw)

        result = json.loads(raw)
        return {"status": "success", **result}

    except Exception as e:
        logger.error(f"Synthesize error: {e}", exc_info=True)
        return JSONResponse(status_code=500, content={"status": "error", "message": str(e)})
