from __future__ import annotations

from django.apps import apps

from drf_spectacular.utils import OpenApiExample, OpenApiParameter, extend_schema
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView

from config.integration_contract import build_integration_meta
from config.openapi import (
    build_envelope_serializer,
    build_response,
    build_task_status_data_serializer,
)

from .growth_simulation import MAX_PAGE_SIZE, paginate_growth_stages
from .serializers import (
    CurrentFarmChartRequestSerializer,
    CurrentFarmChartResponseSerializer,
    GrowthSimulationQueuedSerializer,
    GrowthSimulationRequestSerializer,
    GrowthSimulationResultSerializer,
    HarvestPredictionRequestSerializer,
    HarvestPredictionResponseSerializer,
    YieldHarvestSummaryQuerySerializer,
    YieldHarvestSummaryResponseSerializer,
    YieldPredictionRequestSerializer,
    YieldPredictionResponseSerializer,
)
from .tasks import run_growth_simulation_task
from .yield_harvest_summary import YieldHarvestSummaryService


GrowthSimulationQueuedResponseSerializer = build_envelope_serializer(
    "GrowthSimulationQueuedResponseSerializer",
    GrowthSimulationQueuedSerializer,
)
GrowthSimulationStatusResponseSerializer = build_envelope_serializer(
    "GrowthSimulationStatusResponseSerializer",
    build_task_status_data_serializer(
        "GrowthSimulationTaskStatusDataSerializer",
        GrowthSimulationResultSerializer,
    ),
)
GrowthSimulationErrorSerializer = build_envelope_serializer(
    "GrowthSimulationErrorSerializer",
    data_required=False,
    allow_null=True,
)


def _get_async_result(task_id: str):
    from celery.result import AsyncResult

    return AsyncResult(task_id)


def _coerce_positive_int(value, default: int) -> int:
    try:
        parsed = int(value)
    except (TypeError, ValueError):
        return default
    return max(parsed, 1)


def _fa_task_status(status_name: str) -> str:
    return {
        "PENDING": "در انتظار",
        "PROGRESS": "در حال پردازش",
        "SUCCESS": "موفق",
        "FAILURE": "ناموفق",
    }.get(status_name, status_name)


class PlantGrowthSimulationView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="شروع شبیه سازی رشد گیاه",
        description=(
            "نوع گیاه و پارامترهای متغیر رشد را می گیرد، "
            "شبیه سازی را داخل Celery اجرا می کند و فقط task_id برمی گرداند."
        ),
        request=GrowthSimulationRequestSerializer,
        responses={
            202: build_response(
                GrowthSimulationQueuedResponseSerializer,
                "تسک شبیه سازی رشد گیاه در صف قرار گرفت.",
            ),
            400: build_response(
                GrowthSimulationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست با weather مستقیم",
                value={
                    "plant_name": "گوجه‌فرنگی",
                    "dynamic_parameters": ["DVS", "LAI", "TAGP", "TWSO", "SM"],
                    "weather": [
                        {
                            "DAY": "2026-04-01",
                            "LAT": 35.7,
                            "LON": 51.4,
                            "TMIN": 12,
                            "TMAX": 24,
                            "RAIN": 0.0,
                            "ET0": 0.32,
                        }
                    ],
                    "soil_parameters": {"SMFCF": 0.34, "SMW": 0.14, "RDMSOL": 120.0},
                    "site_parameters": {"WAV": 40.0},
                    "irrigation_recommendation": {"events": [{"date": "2026-04-02", "amount": 2.5}]},
                    "fertilization_recommendation": {
                        "events": [{"date": "2026-04-02", "N_amount": 45, "N_recovery": 0.7}]
                    },
                    "page_size": 2,
                },
                request_only=True,
            ),
            OpenApiExample(
                "نمونه درخواست با farm",
                value={
                    "plant_name": "گوجه‌فرنگی",
                    "dynamic_parameters": ["DVS", "LAI", "TAGP"],
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "irrigation_recommendation": {"events": [{"date": "2026-04-25", "amount": 2.5}]},
                    "fertilization_recommendation": {
                        "events": [{"date": "2026-04-20", "N_amount": 45, "N_recovery": 0.7}]
                    },
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = GrowthSimulationRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )

        task = run_growth_simulation_task.delay(serializer.validated_data)
        return Response(
            {
                "code": 202,
                "msg": "تسک شبیه سازی رشد در صف قرار گرفت.",
                "data": {
                    "task_id": task.id,
                    "status_url": f"/api/crop-simulation/growth/{task.id}/status/",
                    "plant_name": serializer.validated_data["plant_name"],
                },
                "meta": build_integration_meta(
                    flow_type="live_ai_inference",
                    source_type="provider",
                    source_service="ai_crop_simulation",
                    ownership="ai",
                    live=True,
                    cached=False,
                ),
            },
            status=status.HTTP_202_ACCEPTED,
        )


class PlantGrowthSimulationStatusView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="وضعیت شبیه سازی رشد گیاه",
        description="وضعیت تسک Celery را برمی گرداند و در صورت موفقیت مراحل رشد را به صورت صفحه بندی شده بازمی گرداند.",
        responses={
            200: build_response(
                GrowthSimulationStatusResponseSerializer,
                "وضعیت فعلی تسک شبیه سازی رشد گیاه.",
            )
        },
    )
    def get(self, request, task_id: str):
        result = _get_async_result(task_id)
        payload = {
            "task_id": task_id,
            "status": result.state,
            "status_fa": _fa_task_status(result.state),
        }

        if result.state == "PENDING":
            payload["message"] = "تسک در صف یا یافت نشد."
        elif result.state == "PROGRESS":
            payload["progress"] = result.info
        elif result.state == "SUCCESS":
            task_result = dict(result.result or {})
            page = _coerce_positive_int(request.query_params.get("page", 1), 1)
            page_size = min(
                _coerce_positive_int(
                    request.query_params.get("page_size", task_result.get("default_page_size", 10)),
                    10,
                ),
                MAX_PAGE_SIZE,
            )
            paginated = paginate_growth_stages(
                task_result.get("stage_timeline", []),
                page=page,
                page_size=page_size,
            )
            task_result["stages_page"] = paginated["items"]
            task_result["pagination"] = paginated["pagination"]
            payload["result"] = task_result
        elif result.state == "FAILURE":
            payload["error"] = str(result.result)

        return Response(
            {
                "code": 200,
                "msg": "موفق",
                "data": payload,
                "meta": build_integration_meta(
                    flow_type="live_ai_inference",
                    source_type="provider",
                    source_service="ai_crop_simulation",
                    ownership="ai",
                    live=result.state in {"PENDING", "PROGRESS", "SUCCESS"},
                    cached=False,
                ),
            },
            status=status.HTTP_200_OK,
        )



CurrentFarmChartEnvelopeSerializer = build_envelope_serializer(
    "CurrentFarmChartEnvelopeSerializer",
    CurrentFarmChartResponseSerializer,
)
HarvestPredictionEnvelopeSerializer = build_envelope_serializer(
    "HarvestPredictionEnvelopeSerializer",
    HarvestPredictionResponseSerializer,
)
YieldPredictionEnvelopeSerializer = build_envelope_serializer(
    "YieldPredictionEnvelopeSerializer",
    YieldPredictionResponseSerializer,
)
YieldHarvestSummaryEnvelopeSerializer = build_envelope_serializer(
    "YieldHarvestSummaryEnvelopeSerializer",
    YieldHarvestSummaryResponseSerializer,
)


class CurrentFarmSimulationChartView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="chart شبیه سازی وضعیت فعلی مزرعه",
        description=(
            "با دریافت farm_uuid، یک شبیه سازی از وضعیت فعلی مزرعه اجرا می کند و داده chart شامل برگ، وزن، بیوماس، رطوبت و خروجی روزانه را برمی گرداند."
        ),
        request=CurrentFarmChartRequestSerializer,
        responses={
            200: build_response(
                CurrentFarmChartEnvelopeSerializer,
                "خروجی chart شبیه سازی وضعیت فعلی مزرعه.",
            ),
            400: build_response(
                GrowthSimulationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            500: build_response(
                GrowthSimulationErrorSerializer,
                "خطا در اجرای chart شبیه سازی مزرعه.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست chart",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "plant_name": "گوجه‌فرنگی",
                    "irrigation_recommendation": {"events": [{"date": "2026-04-25", "amount": 2.5}]},
                    "fertilization_recommendation": {
                        "events": [{"date": "2026-04-20", "N_amount": 45, "N_recovery": 0.7}]
                    },
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = CurrentFarmChartRequestSerializer(data=request.data)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )

        simulator = apps.get_app_config("crop_simulation").get_current_farm_chart_simulator()
        try:
            result = simulator.simulate(**serializer.validated_data)
        except Exception as exc:
            return Response(
                {"code": 500, "msg": f"خطا در اجرای chart شبیه سازی مزرعه: {exc}", "data": None},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )

        return Response(
            {
                "code": 200,
                "msg": "موفق",
                "data": result,
                "meta": build_integration_meta(
                    flow_type="ai_owned_derived_output",
                    source_type="provider",
                    source_service="ai_crop_simulation_chart",
                    ownership="ai",
                    live=True,
                    cached=False,
                ),
            },
            status=status.HTTP_200_OK,
        )


class HarvestPredictionView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="پیش بینی زمان تقریبی برداشت",
        description=(
            "با دریافت farm_uuid، از شبیه ساز رشد برای برآورد زمان باقی مانده تا برداشت استفاده می کند "
            "و تاریخ تقریبی برداشت را برمی گرداند."
        ),
        request=HarvestPredictionRequestSerializer,
        responses={
            200: build_response(
                HarvestPredictionEnvelopeSerializer,
                "خروجی پیش بینی زمان برداشت مزرعه.",
            ),
            400: build_response(
                GrowthSimulationErrorSerializer,
                "داده ورودی نامعتبر است.",
            ),
            500: build_response(
                GrowthSimulationErrorSerializer,
                "خطا در پیش بینی زمان برداشت.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست harvest prediction",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "plant_name": "گوجه‌فرنگی",
                    "irrigation_recommendation": {"events": [{"date": "2026-04-25", "amount": 2.5}]},
                    "fertilization_recommendation": {
                        "events": [{"date": "2026-04-20", "N_amount": 45, "N_recovery": 0.7}]
                    },
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = HarvestPredictionRequestSerializer(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("crop_simulation").get_harvest_prediction_service()
        try:
            result = service.get_harvest_prediction(**serializer.validated_data)
        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,
                "meta": build_integration_meta(
                    flow_type="ai_owned_derived_output",
                    source_type="provider",
                    source_service="ai_crop_simulation_harvest_prediction",
                    ownership="ai",
                    live=True,
                    cached=False,
                ),
            },
            status=status.HTTP_200_OK,
        )


class YieldPredictionView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="پیش بینی عملکرد مزرعه",
        description="با دریافت farm_uuid، خروجی شبیه ساز رشد را به برآورد عملکرد قابل استفاده در KPI تبدیل می کند.",
        request=YieldPredictionRequestSerializer,
        responses={
            200: build_response(YieldPredictionEnvelopeSerializer, "خروجی پیش بینی عملکرد مزرعه."),
            400: build_response(GrowthSimulationErrorSerializer, "داده ورودی نامعتبر است."),
            500: build_response(GrowthSimulationErrorSerializer, "خطا در پیش بینی عملکرد."),
        },
        examples=[
            OpenApiExample(
                "نمونه درخواست yield prediction",
                value={
                    "farm_uuid": "11111111-1111-1111-1111-111111111111",
                    "plant_name": "گوجه‌فرنگی",
                    "irrigation_recommendation": {"events": [{"date": "2026-04-25", "amount": 2.5}]},
                    "fertilization_recommendation": {
                        "events": [{"date": "2026-04-20", "N_amount": 45, "N_recovery": 0.7}]
                    },
                },
                request_only=True,
            ),
        ],
    )
    def post(self, request):
        serializer = YieldPredictionRequestSerializer(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("crop_simulation").get_yield_prediction_service()
        try:
            result = service.get_yield_prediction(**serializer.validated_data)
        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,
                "meta": build_integration_meta(
                    flow_type="ai_owned_derived_output",
                    source_type="provider",
                    source_service="ai_crop_simulation_yield_prediction",
                    ownership="ai",
                    live=True,
                    cached=False,
                ),
            },
            status=status.HTTP_200_OK,
        )


class YieldHarvestSummaryView(APIView):
    @extend_schema(
        tags=["Crop Simulation"],
        summary="خلاصه عملکرد و برداشت",
        description=(
            "خروجی داشبورد Yield & Harvest Summary را با اتکا به داده های قطعی شبیه سازی برمی گرداند. "
            "این endpoint خروجی derived واقعی تولید می کند و پاسخ آن mock نیست."
        ),
        parameters=[
            OpenApiParameter(
                name="farm_uuid",
                type=str,
                location=OpenApiParameter.QUERY,
                required=True,
                description="شناسه یکتای مزرعه",
            ),
            OpenApiParameter(
                name="season_year",
                type=int,
                location=OpenApiParameter.QUERY,
                required=False,
                description="سال زراعی",
            ),
            OpenApiParameter(
                name="crop_name",
                type=str,
                location=OpenApiParameter.QUERY,
                required=False,
                description="نام محصول",
            ),
            OpenApiParameter(
                name="include_narrative",
                type=bool,
                location=OpenApiParameter.QUERY,
                required=False,
                description="در آینده روایت متنی را نیز اضافه می کند.",
            ),
            OpenApiParameter(
                name="irrigation_recommendation",
                type=str,
                location=OpenApiParameter.QUERY,
                required=False,
                description="JSON برنامه آبیاری برای تزریق به شبیه سازی PCSE.",
            ),
            OpenApiParameter(
                name="fertilization_recommendation",
                type=str,
                location=OpenApiParameter.QUERY,
                required=False,
                description="JSON برنامه کودهی برای تزریق به شبیه سازی PCSE.",
            ),
        ],
        responses={
            200: build_response(
                YieldHarvestSummaryEnvelopeSerializer,
                "خروجی خلاصه عملکرد و برداشت مزرعه.",
            ),
            400: build_response(
                GrowthSimulationErrorSerializer,
                "پارامترهای query نامعتبر است.",
            ),
        },
        examples=[
            OpenApiExample(
                "نمونه پاسخ yield harvest summary",
                value={
                    "code": 200,
                    "msg": "success",
                    "data": {
                        "farm_uuid": "11111111-1111-1111-1111-111111111111",
                        "season_highlights_card": {},
                        "yield_prediction": {},
                        "harvest_prediction_card": {},
                        "harvest_readiness_zones": {},
                        "yield_quality_bands": {},
                        "harvest_operations_card": {},
                        "yield_prediction_chart": {},
                    },
                },
                response_only=True,
            ),
        ],
    )
    def get(self, request):
        serializer = YieldHarvestSummaryQuerySerializer(data=request.query_params)
        if not serializer.is_valid():
            return Response(
                {"code": 400, "msg": "داده نامعتبر.", "data": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST,
            )

        validated = serializer.validated_data
        service = YieldHarvestSummaryService()
        payload = service.get_summary(
            farm_uuid=str(validated["farm_uuid"]),
            season_year=str(validated.get("season_year") or ""),
            crop_name=validated.get("crop_name") or "",
            include_narrative=validated.get("include_narrative", False),
            irrigation_recommendation=validated.get("irrigation_recommendation"),
            fertilization_recommendation=validated.get("fertilization_recommendation"),
        )
        return Response(
            {
                "code": 200,
                "msg": "موفق",
                "data": payload,
                "meta": build_integration_meta(
                    flow_type="ai_owned_derived_output",
                    source_type="provider",
                    source_service="ai_crop_simulation_yield_harvest_summary",
                    ownership="ai",
                    live=True,
                    cached=False,
                ),
            },
            status=status.HTTP_200_OK,
        )
        
