from drf_spectacular.utils import (
    OpenApiExample,
    OpenApiResponse,
    extend_schema,
    inline_serializer,
)
from rest_framework import serializers as drf_serializers
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 .models import Plant
from .serializers import (
    PlantNameStageSerializer,
    PlantSerializer,
    normalize_growth_stage_values,
)
from .services import fetch_plant_info_from_api


PlantListResponseSerializer = build_envelope_serializer(
    "PlantListResponseSerializer",
    PlantSerializer,
    many=True,
)
PlantDetailResponseSerializer = build_envelope_serializer(
    "PlantDetailResponseSerializer",
    PlantSerializer,
)
PlantValidationErrorSerializer = build_envelope_serializer(
    "PlantValidationErrorSerializer",
    data_required=False,
    allow_null=True,
)
PlantFetchInfoResponseSerializer = build_envelope_serializer(
    "PlantFetchInfoResponseSerializer",
    PlantSerializer,
)
PlantNameStageListResponseSerializer = build_envelope_serializer(
    "PlantNameStageListResponseSerializer",
    PlantNameStageSerializer,
    many=True,
)


class PlantListCreateView(APIView):
    """لیست تمام گیاهان و ایجاد گیاه جدید."""

    @extend_schema(
        tags=["Plant"],
        summary="لیست گیاهان",
        description="لیست تمام گیاهان ذخیره‌شده را برمی‌گرداند.",
        responses={
            200: build_response(
                PlantListResponseSerializer,
                "لیست گیاهان ذخیره‌شده.",
            ),
        },
    )
    def get(self, request):
        plants = Plant.objects.all()
        serializer = PlantSerializer(plants, many=True)
        return Response(
            {"code": 200, "msg": "success", "data": serializer.data},
            status=status.HTTP_200_OK,
        )

    @extend_schema(
        tags=["Plant"],
        summary="ایجاد گیاه جدید",
        description="یک گیاه جدید با مشخصات داده‌شده ایجاد می‌کند.",
        request=PlantSerializer,
        responses={
            201: build_response(
                PlantDetailResponseSerializer,
                "گیاه جدید با موفقیت ایجاد شد.",
            ),
            400: build_response(
                PlantValidationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست",
                value={
                    "name": "گوجه‌فرنگی",
                    "light": "آفتاب کامل",
                    "watering": "منظم، هفته‌ای ۲-۳ بار",
                    "soil": "لومی، غنی از مواد آلی",
                    "temperature": "۲۰-۳۰ درجه سانتی‌گراد",
                    "growth_stage": "رشد رویشی",
                    "planting_season": "بهار",
                    "harvest_time": "۷۰-۹۰ روز پس از کاشت",
                    "spacing": "۴۵-۶۰ سانتی‌متر",
                    "fertilizer": "کود NPK متعادل",
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = PlantSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )
        serializer.save()
        return Response(
            {"code": 201, "msg": "success", "data": serializer.data},
            status=status.HTTP_201_CREATED,
        )


class PlantNameStageListView(APIView):
    """لیست سبک از نام گیاه، آیکون و مراحل رشد."""

    @extend_schema(
        tags=["Plant"],
        summary="لیست نام گیاهان با مراحل رشد",
        description=(
            "فقط نام گیاه، آیکون و مراحل رشد را برمی‌گرداند. "
            "اگر برای گیاهی مرحله رشد ثبت نشده باشد، مراحل پیش‌فرض به آن اضافه و ذخیره می‌شود."
        ),
        responses={
            200: build_response(
                PlantNameStageListResponseSerializer,
                "لیست نام گیاهان به همراه مراحل رشد و آیکون.",
            ),
        },
    )
    def get(self, request):
        payload = []
        for plant in Plant.objects.all():
            growth_stages = normalize_growth_stage_values(plant)
            serialized_stages = ", ".join(growth_stages)
            update_fields: list[str] = []

            if plant.growth_stage != serialized_stages:
                plant.growth_stage = serialized_stages
                update_fields.append("growth_stage")
            if not plant.icon:
                plant.icon = "leaf"
                update_fields.append("icon")
            if update_fields:
                update_fields.append("updated_at")
                plant.save(update_fields=update_fields)

            payload.append(
                {
                    "name": plant.name,
                    "icon": plant.icon,
                    "growth_stages": growth_stages,
                }
            )

        serializer = PlantNameStageSerializer(payload, many=True)
        return Response(
            {"code": 200, "msg": "success", "data": serializer.data},
            status=status.HTTP_200_OK,
        )


class PlantDetailView(APIView):
    """دریافت، ویرایش و حذف یک گیاه."""

    def _get_plant(self, pk):
        return Plant.objects.filter(pk=pk).first()

    @extend_schema(
        tags=["Plant"],
        summary="جزئیات گیاه",
        description="مشخصات یک گیاه را بر اساس شناسه برمی‌گرداند.",
        responses={
            200: build_response(
                PlantDetailResponseSerializer,
                "جزئیات گیاه.",
            ),
            404: build_response(
                PlantValidationErrorSerializer,
                "گیاه یافت نشد.",
            ),
        },
    )
    def get(self, request, pk):
        plant = self._get_plant(pk)
        if not plant:
            return Response(
                {"code": 404, "msg": "گیاه یافت نشد.", "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = PlantSerializer(plant)
        return Response(
            {"code": 200, "msg": "success", "data": serializer.data},
            status=status.HTTP_200_OK,
        )

    @extend_schema(
        tags=["Plant"],
        summary="ویرایش کامل گیاه",
        description="تمام فیلدهای یک گیاه را آپدیت می‌کند.",
        request=PlantSerializer,
        responses={
            200: build_response(
                PlantDetailResponseSerializer,
                "گیاه با موفقیت به‌روزرسانی شد.",
            ),
            400: build_response(
                PlantValidationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            404: build_response(
                PlantValidationErrorSerializer,
                "گیاه یافت نشد.",
            ),
        },
    )
    def put(self, request, pk):
        plant = self._get_plant(pk)
        if not plant:
            return Response(
                {"code": 404, "msg": "گیاه یافت نشد.", "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = PlantSerializer(plant, data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )
        serializer.save()
        return Response(
            {"code": 200, "msg": "success", "data": serializer.data},
            status=status.HTTP_200_OK,
        )

    @extend_schema(
        tags=["Plant"],
        summary="ویرایش جزئی گیاه",
        description="فقط فیلدهای ارسال‌شده آپدیت می‌شوند.",
        request=PlantSerializer,
        responses={
            200: build_response(
                PlantDetailResponseSerializer,
                "گیاه با موفقیت به‌روزرسانی شد.",
            ),
            400: build_response(
                PlantValidationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            404: build_response(
                PlantValidationErrorSerializer,
                "گیاه یافت نشد.",
            ),
        },
    )
    def patch(self, request, pk):
        plant = self._get_plant(pk)
        if not plant:
            return Response(
                {"code": 404, "msg": "گیاه یافت نشد.", "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )
        serializer = PlantSerializer(plant, data=request.data, partial=True)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )
        serializer.save()
        return Response(
            {"code": 200, "msg": "success", "data": serializer.data},
            status=status.HTTP_200_OK,
        )

    @extend_schema(
        tags=["Plant"],
        summary="حذف گیاه",
        description="یک گیاه را حذف می‌کند.",
        responses={
            200: build_response(
                PlantValidationErrorSerializer,
                "گیاه با موفقیت حذف شد.",
            ),
            404: build_response(
                PlantValidationErrorSerializer,
                "گیاه یافت نشد.",
            ),
        },
    )
    def delete(self, request, pk):
        plant = self._get_plant(pk)
        if not plant:
            return Response(
                {"code": 404, "msg": "گیاه یافت نشد.", "data": None},
                status=status.HTTP_404_NOT_FOUND,
            )
        plant.delete()
        return Response(
            {"code": 200, "msg": "گیاه با موفقیت حذف شد.", "data": None},
            status=status.HTTP_200_OK,
        )


class PlantFetchInfoView(APIView):
    """دریافت مشخصات گیاه از API خارجی بر اساس نام."""

    @extend_schema(
        tags=["Plant"],
        summary="دریافت مشخصات گیاه از API خارجی",
        description="بر اساس نام گیاه، مشخصات آن را از API خارجی دریافت می‌کند. (فعلاً خالی)",
        request=inline_serializer(
            name="PlantFetchInfoRequest",
            fields={
                "name": drf_serializers.CharField(help_text="نام گیاه"),
            },
        ),
        responses={
            200: build_response(
                PlantFetchInfoResponseSerializer,
                "اطلاعات گیاه از سرویس خارجی دریافت شد.",
            ),
            400: build_response(
                PlantValidationErrorSerializer,
                "نام گیاه ارسال نشده است.",
            ),
            503: build_response(
                PlantValidationErrorSerializer,
                "سرویس خارجی در دسترس نیست.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست",
                value={"name": "گوجه‌فرنگی"},
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        plant_name = request.data.get("name")
        if not plant_name:
            return Response(
                {"code": 400, "msg": "نام گیاه الزامی است.", "data": None},
                status=status.HTTP_400_BAD_REQUEST,
            )

        result = fetch_plant_info_from_api(plant_name)
        if result is None:
            return Response(
                {
                    "code": 503,
                    "msg": "سرویس API هنوز پیاده‌سازی نشده است.",
                    "data": None,
                },
                status=status.HTTP_503_SERVICE_UNAVAILABLE,
            )

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