from django.apps import apps

from drf_spectacular.utils import OpenApiExample, extend_schema
from rest_framework import status
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 .serializers import (
    FarmWeatherRequestSerializer,
    FarmWeatherResponseSerializer,
    WaterNeedPredictionRequestSerializer,
    WaterNeedPredictionResponseSerializer,
)


FarmWeatherEnvelopeSerializer = build_envelope_serializer(
    "FarmWeatherEnvelopeSerializer",
    FarmWeatherResponseSerializer,
)
WeatherErrorSerializer = build_envelope_serializer(
    "WeatherErrorSerializer",
    data_required=False,
    allow_null=True,
)
WaterNeedPredictionEnvelopeSerializer = build_envelope_serializer(
    "WaterNeedPredictionEnvelopeSerializer",
    WaterNeedPredictionResponseSerializer,
)


class FarmWeatherCardView(APIView):
    @extend_schema(
        tags=["Weather"],
        summary="دریافت کارت آب و هوای مزرعه",
        description="با دریافت farm_uuid، داده مستقل کارت آب و هوای مزرعه را از اپ weather برمی گرداند.",
        request=FarmWeatherRequestSerializer,
        responses={
            200: build_response(
                FarmWeatherEnvelopeSerializer,
                "داده کارت آب و هوای مزرعه با موفقیت بازگردانده شد.",
            ),
            400: build_response(
                WeatherErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            404: build_response(
                WeatherErrorSerializer,
                "مزرعه یافت نشد.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست weather",
                value={"farm_uuid": "11111111-1111-1111-1111-111111111111"},
                request_only=True,
            )
        ],
    )
    def post(self, request):
        serializer = FarmWeatherRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )

        service = apps.get_app_config("weather").get_farm_weather_service()
        try:
            data = service.get_farm_weather_card(
                farm_uuid=str(serializer.validated_data["farm_uuid"])
            )
        except ValueError as exc:
            return Response(
                {"code": 404, "msg": str(exc), "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )

        return Response(
            {"code": 200, "msg": "success", "data": data},
            status=status.HTTP_200_OK,
        )


class WaterNeedPredictionView(APIView):
    @extend_schema(
        tags=["Weather"],
        summary="دریافت پیش بینی نیاز آبی کوتاه مدت مزرعه",
        description="با دریافت farm_uuid، محاسبات نیاز آبی 7 روز آینده را از اپ weather برمی گرداند و با RAG تفسیر عملیاتی اضافه می کند.",
        request=WaterNeedPredictionRequestSerializer,
        responses={
            200: build_response(
                WaterNeedPredictionEnvelopeSerializer,
                "داده پیش بینی نیاز آبی مزرعه با موفقیت بازگردانده شد.",
            ),
            400: build_response(
                WeatherErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            404: build_response(
                WeatherErrorSerializer,
                "مزرعه یافت نشد.",
            ),
            500: build_response(
                WeatherErrorSerializer,
                "خطا در تحلیل نیاز آبی مزرعه.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست water need",
                value={"farm_uuid": "11111111-1111-1111-1111-111111111111"},
                request_only=True,
            )
        ],
    )
    def post(self, request):
        serializer = WaterNeedPredictionRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )

        service = apps.get_app_config("weather").get_water_need_service()
        try:
            data = service.get_water_need_prediction(
                farm_uuid=str(serializer.validated_data["farm_uuid"])
            )
        except ValueError as exc:
            return Response(
                {"code": 404, "msg": str(exc), "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )
        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": data},
            status=status.HTTP_200_OK,
        )
