"""
ویوهای RAG — چت با استریم
"""
import json
import logging

from django.http import StreamingHttpResponse
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import (
    OpenApiExample,
    OpenApiResponse,
    extend_schema,
    inline_serializer,
)
from rest_framework import status
from rest_framework import serializers as drf_serializers
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from config.openapi import (
    build_envelope_serializer,
    build_message_response_serializer,
    build_response,
)
from .chat import chat_rag_stream, encode_uploaded_image


logger = logging.getLogger(__name__)


RagChatErrorResponseSerializer = build_message_response_serializer(
    "RagChatErrorResponseSerializer"
)
RagValidationErrorResponseSerializer = build_envelope_serializer(
    "RagValidationErrorResponseSerializer",
    data_required=False,
    allow_null=True,
)


class ChatView(APIView):
    parser_classes = [JSONParser, MultiPartParser, FormParser]

    def _parse_history(self, raw_history):
        if raw_history in (None, "", []):
            return []
        if isinstance(raw_history, list):
            return raw_history
        if isinstance(raw_history, str):
            try:
                parsed = json.loads(raw_history)
            except (json.JSONDecodeError, ValueError):
                raise ValueError("history باید JSON معتبر باشد.")
            if not isinstance(parsed, list):
                raise ValueError("history باید آرایه باشد.")
            return parsed
        raise ValueError("history فرمت پشتیبانی شده ندارد.")

    def _collect_uploaded_images(self, request: Request):
        images = []
        for uploaded in request.FILES.getlist("images"):
            images.append(encode_uploaded_image(uploaded))
        single_image = request.FILES.get("image")
        if single_image is not None:
            images.append(encode_uploaded_image(single_image))
        image_urls = request.data.get("image_urls")
        if isinstance(image_urls, str) and image_urls.strip():
            try:
                parsed_urls = json.loads(image_urls)
            except (json.JSONDecodeError, ValueError):
                parsed_urls = [image_urls]
            image_urls = parsed_urls
        if isinstance(image_urls, list):
            for item in image_urls:
                if isinstance(item, str) and item.strip():
                    images.append({"url": item.strip(), "detail": "auto"})
                elif isinstance(item, dict) and isinstance(item.get("url"), str):
                    image_payload = {"url": item["url"].strip(), "detail": item.get("detail", "auto")}
                    images.append(image_payload)
        return images

    @extend_schema(
        tags=["RAG Chat"],
        summary="چت RAG با استریم",
        description="پیام کاربر را دریافت و پاسخ را به صورت استریم برمی‌گرداند.",
        request=inline_serializer(
            name="ChatRequest",
            fields={
                "query": drf_serializers.CharField(required=False, help_text="متن سوال کاربر"),
                "message": drf_serializers.CharField(required=False, help_text="نام قبلی فیلد query"),
                "farm_uuid": drf_serializers.CharField(help_text="شناسه مزرعه"),
                "history": drf_serializers.JSONField(required=False, help_text="آرایه پیام های قبلی با role=user/assistant"),
                "image_urls": drf_serializers.JSONField(required=False, help_text="آرایه URL تصاویر برای پیام فعلی"),
                "image": drf_serializers.FileField(required=False, help_text="یک تصویر برای پیام فعلی"),
                "images": drf_serializers.ListField(
                    child=drf_serializers.FileField(),
                    required=False,
                    help_text="چند تصویر برای پیام فعلی",
                ),
            },
        ),
        responses={
            200: OpenApiResponse(
                response=OpenApiTypes.STR,
                description="پاسخ استریم متنی (text/plain)",
            ),
            400: build_response(
                RagChatErrorResponseSerializer,
                "پارامترهای ورودی نامعتبر هستند.",
            ),
            404: build_response(
                RagChatErrorResponseSerializer,
                "مزرعه پیدا نشد.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "query": "وضعیت مزرعه من چطور است؟",
                    "history": [
                        {"role": "user", "content": "رطوبت خاک من پایین بود؟"},
                        {"role": "assistant", "content": "بله، رطوبت خاک کمتر از محدوده مطلوب بود."},
                    ],
                    "image_urls": ["https://example.com/farm-photo.jpg"],
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request: Request):
        from farm_data.services import build_ai_farm_snapshot
        from .config import load_rag_config

        data = request.data if request.method == "POST" else request.query_params
        message = data.get("query", data.get("message"))
        farm_uuid = data.get("farm_uuid")
        raw_history = data.get("history")
        try:
            images = self._collect_uploaded_images(request)
        except ValueError as exc:
            return Response(
                {"code": 400, "msg": str(exc)},
                status=status.HTTP_400_BAD_REQUEST,
            )
        if message is None and images:
            message = "لطفا تصویر ارسالی را در کنار اطلاعات مزرعه بررسی کن."
        if not message or not isinstance(message, str):
            return Response(
                {"code": 400, "msg": "پارامتر query الزامی است، مگر اینکه تصویر ارسال شده باشد."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        message = str(message).strip()
        if not message:
            return Response(
                {"code": 400, "msg": "پیام نباید خالی باشد."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        if not farm_uuid or not isinstance(farm_uuid, str):
            return Response(
                {"code": 400, "msg": "پارامتر farm_uuid الزامی است."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        farm_uuid = str(farm_uuid).strip()
        if not farm_uuid:
            return Response(
                {"code": 400, "msg": "farm_uuid نباید خالی باشد."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        try:
            history = self._parse_history(raw_history)
        except ValueError as exc:
            return Response(
                {"code": 400, "msg": str(exc)},
                status=status.HTTP_400_BAD_REQUEST,
            )
        cfg = load_rag_config()
        farm_details = build_ai_farm_snapshot(farm_uuid)
        if farm_details is None:
            return Response(
                {"code": 404, "msg": "farm پیدا نشد."},
                status=status.HTTP_404_NOT_FOUND,
            )

        def generate():
            try:
                for chunk in chat_rag_stream(
                    message,
                    farm_uuid=farm_uuid,
                    config=cfg,
                    farm_details=farm_details,
                    history=history,
                    images=images,
                ):
                    yield chunk
            except Exception as e:
                yield f"\n[خطا: {e}]"

        return StreamingHttpResponse(
            generate(),
            content_type="text/plain; charset=utf-8",
        )
