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 .serializers import (
    FertilizationPlanParserRequestSerializer,
    FertilizationPlanParserResponseSerializer,
    FertilizationRecommendationResponseDataSerializer,
    FertilizationRecommendRequestSerializer,
)


FertilizationValidationErrorSerializer = build_envelope_serializer(
    "FertilizationValidationErrorSerializer",
    data_required=False,
    allow_null=True,
)
FertilizationResponseSerializer = build_envelope_serializer(
    "FertilizationResponseSerializer",
    data_schema=FertilizationRecommendationResponseDataSerializer,
)
FertilizationPlanParserEnvelopeSerializer = build_envelope_serializer(
    "FertilizationPlanParserEnvelopeSerializer",
    data_schema=FertilizationPlanParserResponseSerializer,
)


class FertilizationRecommendView(APIView):
    """
    توصیه کودهی ساختاریافته با ترکیب RAG و optimizer شبیه سازی.
    """

    @extend_schema(
        tags=["Fertilization Recommendation"],
        summary="درخواست توصیه کودهی ساختاریافته",
        description=(
            "داده های مزرعه، گیاه و مرحله رشد را دریافت می کند و "
            "خروجی نهایی بهینه شده با ترکیب RAG و optimizer مبتنی بر crop_simulation/PCSE را برمی گرداند."
        ),
        request=FertilizationRecommendRequestSerializer,
        responses={
            200: build_response(
                FertilizationResponseSerializer,
                "توصیه کودهی ساختاریافته با موفقیت تولید شد.",
            ),
            400: build_response(
                FertilizationValidationErrorSerializer,
                "پارامتر ورودی نامعتبر است.",
            ),
            500: build_response(
                FertilizationValidationErrorSerializer,
                "خطا در تولید توصیه کودهی.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "crop_id": "wheat",
                    "growth_stage": "flowering",
                },
                request_only=True,
            ),
            OpenApiExample(
                "نمونه پاسخ",
                value={
                    "code": 200,
                    "msg": "success",
                    "data": {
                        "primary_recommendation": {
                            "fertilizer_code": "15-10-30",
                            "fertilizer_name": "کود کامل 15-10-30",
                            "display_title": "کود کامل 15-10-30",
                            "fertilizer_type": "NPK",
                            "npk_ratio": {"n": 15, "p": 10, "k": 30, "label": "15-10-30"},
                            "application_method": {
                                "id": "foliar_fertigation",
                                "label": "کودآبیاری یا محلول پاشی سبک",
                            },
                            "application_interval": {"value": 14, "unit": "day", "label": "هر 14 روز"},
                            "dosage": {
                                "base_amount_per_hectare": 65,
                                "base_amount_per_square_meter": 0.0065,
                                "unit": "kg",
                                "label": "65 کیلوگرم در هکتار",
                                "calculation_basis": "crop_simulation_heuristic",
                            },
                            "reasoning": "این ترکیب برای مرحله گلدهی و توازن نیازهای تغذیه ای مناسب است.",
                            "summary": "برای پشتیبانی از گلدهی و کاهش تنش تغذیه ای پیشنهاد می شود.",
                        },
                        "nutrient_analysis": {
                            "macro": [
                                {
                                    "key": "n",
                                    "name": "نیتروژن (N)",
                                    "value": 15,
                                    "unit": "percent",
                                    "description": "نیتروژن برای حفظ رشد رویشی مهم است.",
                                }
                            ],
                            "micro": [],
                        },
                        "application_guide": {
                            "safety_warning": "در ساعات خنک مصرف شود و از اختلاط ناسازگار خودداری کنید.",
                            "steps": [
                                {"step_number": 1, "title": "آماده سازی", "description": "دوز را آماده کنید."},
                                {"step_number": 2, "title": "تزریق یا پخش", "description": "طبق روش مصرف اجرا کنید."},
                                {"step_number": 3, "title": "پایش", "description": "پاسخ مزرعه را بررسی کنید."},
                            ],
                        },
                        "alternative_recommendations": [],
                    },
                },
                response_only=True,
            ),
        ],
    )
    def post(self, request):
        from rag.services.fertilization import get_fertilization_recommendation

        serializer = FertilizationRecommendRequestSerializer(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_fertilization_recommendation(
                farm_uuid=validated["farm_uuid"],
                plant_name=validated.get("plant_name"),
                crop_id=validated.get("crop_id"),
                growth_stage=validated.get("growth_stage"),
                query=validated.get("query"),
            )
        except Exception as exc:
            return Response(
                {"code": 500, "msg": f"خطا در تولید توصیه کودهی: {exc}", "data": None},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

        final_result = result.get("data") if isinstance(result, dict) else None
        if not isinstance(final_result, dict):
            final_result = {"sections": result.get("sections", [])} if isinstance(result, dict) else {}

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


class FertilizationPlanParserView(APIView):
    @extend_schema(
        tags=["Fertilization Recommendation"],
        summary="استخراج برنامه کودهی از متن آزاد",
        description=(
            "توضیح متنی کاربر درباره برنامه کودهی را می گیرد و آن را به JSON ساختاریافته تبدیل می کند. "
            "اگر اطلاعات کافی نباشد، سوالات تکمیلی لازم را برمی گرداند تا در درخواست بعدی پاسخ داده شوند."
        ),
        request=FertilizationPlanParserRequestSerializer,
        responses={
            200: build_response(
                FertilizationPlanParserEnvelopeSerializer,
                "نتیجه استخراج یا سوالات تکمیلی برنامه کودهی.",
            ),
            400: build_response(
                FertilizationValidationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            500: build_response(
                FertilizationValidationErrorSerializer,
                "خطا در پردازش برنامه کودهی.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست کامل",
                value={
                    "message": "برای گندم در مرحله پنجه زنی هر 12 روز یک بار 20-20-20 به مقدار 35 کیلوگرم در هکتار از طریق کودآبیاری می دهم.",
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                },
                request_only=True,
            ),
            OpenApiExample(
                "نمونه درخواست تکمیلی",
                value={
                    "partial_plan": {
                        "crop_name": "گندم",
                        "applications": [{"fertilizer_name": "20-20-20"}],
                    },
                    "answers": {
                        "amount": "35 کیلوگرم در هکتار",
                        "timing": "هر 12 روز یک بار",
                    },
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = FertilizationPlanParserRequestSerializer(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
        service = apps.get_app_config("fertilization").get_free_text_plan_parser_service()
        try:
            result = service.parse_plan(
                message=validated.get("message", ""),
                answers=validated.get("answers"),
                partial_plan=validated.get("partial_plan"),
                farm_uuid=validated.get("farm_uuid"),
            )
        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": "موفق", "data": result},
            status=status.HTTP_200_OK,
        )
