import asyncio
import json
import logging

from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from typing import List, Dict, Any
from nexus_agent.core.agent import orchestrator
from nexus_agent.core.memory_manager import memory_manager

logger = logging.getLogger(__name__)

router = APIRouter()

class ChatRequest(BaseModel):
    messages: List[Dict[str, Any]]


def _extract_text(content) -> str:
    """Extract plain text from message content (string or multimodal array)."""
    if isinstance(content, str):
        return content
    if isinstance(content, list):
        for part in content:
            if isinstance(part, dict) and part.get("type") == "text":
                return part.get("text", "")
    return ""


@router.post("/")
async def chat(request: ChatRequest):
    try:
        response = await orchestrator.run(request.messages)

        # Background memory extraction (fire-and-forget)
        try:
            assistant_content = response.get("choices", [{}])[0].get("message", {}).get("content", "")
            # Find last user message
            user_text = ""
            for msg in reversed(request.messages):
                if msg.get("role") == "user":
                    user_text = _extract_text(msg.get("content", ""))
                    break

            if user_text and assistant_content:
                asyncio.create_task(
                    memory_manager.extract_and_save(user_text, assistant_content)
                )
        except Exception as e:
            logger.debug(f"Memory extraction trigger failed: {e}")

        return response
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/stream")
async def chat_stream(request: ChatRequest):
    async def event_generator():
        full_response = None
        try:
            async for event in orchestrator.run_stream(request.messages):
                if event["type"] == "done":
                    full_response = event["full_response"]
                yield f"data: {json.dumps(event, ensure_ascii=False)}\n\n"
        except Exception as e:
            logger.error("Stream error: %s", e)
            yield f"data: {json.dumps({'type': 'error', 'content': str(e)}, ensure_ascii=False)}\n\n"

        # Background memory extraction (fire-and-forget)
        if full_response:
            try:
                assistant_content = full_response.get("choices", [{}])[0].get("message", {}).get("content", "")
                user_text = ""
                for msg in reversed(request.messages):
                    if msg.get("role") == "user":
                        user_text = _extract_text(msg.get("content", ""))
                        break

                if user_text and assistant_content:
                    asyncio.create_task(
                        memory_manager.extract_and_save(user_text, assistant_content)
                    )
            except Exception as e:
                logger.debug(f"Memory extraction trigger failed: {e}")

    return StreamingResponse(event_generator(), media_type="text/event-stream")
