import json

from drf_spectacular.utils import OpenApiExample, extend_schema
from rest_framework import status
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
from rest_framework.response import Response
from rest_framework.views import APIView

from config.openapi import build_envelope_serializer, build_response
from rag.failure_contract import RAGServiceError
from rag.chat import encode_uploaded_image
from rag.services import get_pest_disease_detection, get_pest_disease_risk

from .serializers import (
    PestDiseaseDetectionRequestSerializer,
    PestDiseaseRiskRequestSerializer,
)


PestDiseaseValidationErrorSerializer = build_envelope_serializer(
    "PestDiseaseValidationErrorSerializer",
    data_required=False,
    allow_null=True,
)
PestDiseaseDetectionResponseSerializer = build_envelope_serializer(
    "PestDiseaseDetectionResponseSerializer",
    data_schema=None,
)
PestDiseaseRiskResponseSerializer = build_envelope_serializer(
    "PestDiseaseRiskResponseSerializer",
    data_schema=None,
)
class _ImageMixin:
    parser_classes = [JSONParser, MultiPartParser, FormParser]

    def _collect_uploaded_images(self, 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 = json.loads(image_urls)
            except (json.JSONDecodeError, ValueError):
                parsed = [image_urls]
            image_urls = parsed
        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):
                    images.append({"url": item["url"].strip(), "detail": item.get("detail", "auto")})
        return images


class PestDiseaseDetectionView(_ImageMixin, APIView):
    @extend_schema(
        tags=["Pest & Disease"],
        summary="تشخیص آفت یا بیماری از روی تصویر",
        description="با دریافت farm_uuid و حداقل یک تصویر، تصویر گیاه را با کمک RAG بررسی می کند و نتیجه تشخیص را برمی گرداند.",
        request=PestDiseaseDetectionRequestSerializer,
        responses={
            200: build_response(PestDiseaseDetectionResponseSerializer, "نتیجه تشخیص آفت/بیماری."),
            400: build_response(PestDiseaseValidationErrorSerializer, "پارامتر ورودی نامعتبر است."),
            500: build_response(PestDiseaseValidationErrorSerializer, "خطا در تحلیل تصویر گیاه."),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست تشخیص",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "plant_name": "گوجه فرنگی",
                    "query": "این برگ ها مشکوک به آفت هستند؟",
                    "image_urls": ["https://example.com/leaf.jpg"],
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = PestDiseaseDetectionRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )
        images = self._collect_uploaded_images(request)
        if not images:
            return Response(
                {"code": 400, "msg": "حداقل یک تصویر باید ارسال شود.", "data": None},
                status=status.HTTP_400_BAD_REQUEST,
            )
        validated = serializer.validated_data
        try:
            result = get_pest_disease_detection(
                farm_uuid=validated["farm_uuid"],
                plant_name=validated.get("plant_name"),
                query=validated.get("query"),
                images=images,
            )
        except RAGServiceError as exc:
            return Response(
                {"code": exc.http_status, "msg": exc.contract.message, "data": exc.to_dict()},
                status=exc.http_status,
            )
        except Exception as exc:
            return Response(
                {"code": 500, "msg": f"خطا در تحلیل تصویر گیاه: {exc}", "data": None},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        return Response({"code": 200, "msg": "success", "data": result}, status=status.HTTP_200_OK)


class PestDiseaseRiskView(APIView):
    @extend_schema(
        tags=["Pest & Disease"],
        summary="پیش بینی ریسک آفات و بیماری",
        description="با دریافت farm_uuid، داده های مزرعه و پایگاه دانش تخصصی را به RAG می دهد و ریسک آفات و بیماری را برمی گرداند.",
        request=PestDiseaseRiskRequestSerializer,
        responses={
            200: build_response(PestDiseaseRiskResponseSerializer, "خروجی پیش بینی ریسک آفات و بیماری."),
            400: build_response(PestDiseaseValidationErrorSerializer, "پارامتر ورودی نامعتبر است."),
            500: build_response(PestDiseaseValidationErrorSerializer, "خطا در پیش بینی ریسک آفات و بیماری."),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست ریسک",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "plant_name": "گوجه فرنگی",
                    "growth_stage": "گلدهی",
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = PestDiseaseRiskRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )
        validated = serializer.validated_data
        try:
            result = get_pest_disease_risk(
                farm_uuid=validated["farm_uuid"],
                plant_name=validated.get("plant_name"),
                growth_stage=validated.get("growth_stage"),
                query=validated.get("query"),
            )
        except RAGServiceError as exc:
            return Response(
                {"code": exc.http_status, "msg": exc.contract.message, "data": exc.to_dict()},
                status=exc.http_status,
            )
        except Exception as exc:
            return Response(
                {"code": 500, "msg": f"خطا در پیش بینی ریسک آفات و بیماری: {exc}", "data": None},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
        return Response({"code": 200, "msg": "success", "data": result}, status=status.HTTP_200_OK)
