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, )