# pxy_langchain/api/views.py
import json
import logging
from typing import Optional

from django.http import JsonResponse, HttpResponse
from django.views.decorators.csrf import csrf_exempt

from pxy_langchain.models import AIAssistant
from pxy_langchain.services import LangchainAIService

# We read the bot->assistant mapping from pxy_bots, so bots can decide which assistant to use.
from pxy_bots.models import TelegramBot

logger = logging.getLogger(__name__)


def _get_assistant_for_req(req: dict) -> Optional[AIAssistant]:
    """
    Resolve which AIAssistant to use:
      1) Try via TelegramBot (req['bot']['username'] matches TelegramBot.name or .username).
      2) Fallback: optional req['context']['assistant_name'].
    """
    bot_username = (((req.get("bot") or {}).get("username")) or "").strip()
    if bot_username:
        # Try Bot.name first (that’s how your req.v1 is built), then .username
        bot = (TelegramBot.objects.filter(name=bot_username).first() or
               TelegramBot.objects.filter(username=bot_username).first())
        if bot and bot.assistant_id:
            return bot.assistant

    # Fallback: explicit assistant name (optional)
    ctx = req.get("context") or {}
    assistant_name = (ctx.get("assistant_name") or "").strip()
    if assistant_name:
        return AIAssistant.objects.filter(name=assistant_name).first()

    return None


@csrf_exempt
def chat(request):
    """
    POST /api/langchain/chat
    Body: req.v1 (canonical envelope produced by pxy_bots)
    Returns: render.v1 (text message with the LLM answer)
    """
    if request.method != "POST":
        return HttpResponse(status=405)

    try:
        env = json.loads(request.body.decode("utf-8") or "{}")
    except Exception:
        return JsonResponse({"ok": False, "error": "invalid_json"}, status=400)

    assistant = _get_assistant_for_req(env)
    if not assistant:
        return JsonResponse({"ok": False, "error": "assistant_not_found"}, status=400)

    # Pull user text (or caption) from req.v1
    inp = env.get("input") or {}
    user_text = (inp.get("text") or inp.get("caption") or "").strip()

    # If nothing to say, keep it explicit
    if not user_text:
        return JsonResponse({
            "schema_version": "render.v1",
            "messages": [{"type": "text", "text": "No text received."}]
        })

    try:
        svc = LangchainAIService(assistant)
        answer = svc.generate_response(user_text)  # synchronous call
    except Exception as e:
        logger.exception("langchain.chat.error")
        return JsonResponse({"ok": False, "error": f"llm_error:{e.__class__.__name__}"}, status=500)

    # Minimal render.v1
    spec = {
        "schema_version": "render.v1",
        "messages": [
            {"type": "text", "text": str(answer)}
        ]
    }
    return JsonResponse(spec)
