from __future__ import annotations

import json

from django.apps import apps

from rest_framework import serializers


class QueryJSONField(serializers.JSONField):
    def to_internal_value(self, data):
        if isinstance(data, str):
            data = data.strip()
            if not data:
                return None
            try:
                data = json.loads(data)
            except json.JSONDecodeError as exc:
                raise serializers.ValidationError("فرمت JSON نامعتبر است.") from exc
        return super().to_internal_value(data)


class PlantNameAliasMixin:
    plant_name_field = "plant_name"
    plant_alias_fields = ("crop", "crop_name")

    def _get_raw_plant_name(self, attrs):
        value = attrs.get(self.plant_name_field)
        if value not in (None, ""):
            return value

        for alias in self.plant_alias_fields:
            alias_value = self.initial_data.get(alias) if hasattr(self, "initial_data") else None
            if alias_value not in (None, ""):
                return alias_value
        return value

    def _resolve_plant_name(self, attrs, *, required: bool) -> dict:
        raw_value = self._get_raw_plant_name(attrs)
        if raw_value in (None, ""):
            if required:
                raise serializers.ValidationError(
                    {self.plant_name_field: "یکی از plant_name، crop یا crop_name باید ارسال شود."}
                )
            attrs[self.plant_name_field] = ""
            return attrs

        resolved_value = apps.get_app_config("plant").resolve_plant_name(str(raw_value))
        attrs[self.plant_name_field] = resolved_value or str(raw_value).strip()
        return attrs


class GrowthSimulationRequestSerializer(PlantNameAliasMixin, serializers.Serializer):
    plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه")
    dynamic_parameters = serializers.ListField(
        child=serializers.CharField(),
        allow_empty=False,
        help_text="پارامترهای متغیر رشد که باید در خروجی گزارش شوند.",
    )
    farm_uuid = serializers.UUIDField(required=False, allow_null=True)
    weather = serializers.JSONField(required=False)
    soil_parameters = serializers.JSONField(required=False)
    site_parameters = serializers.JSONField(required=False)
    crop_parameters = serializers.JSONField(required=False)
    agromanagement = serializers.JSONField(required=False)
    irrigation_recommendation = serializers.JSONField(required=False)
    fertilization_recommendation = serializers.JSONField(required=False)
    page_size = serializers.IntegerField(required=False, min_value=1, max_value=50)

    def validate(self, attrs):
        attrs = self._resolve_plant_name(attrs, required=True)
        if not attrs.get("farm_uuid") and not attrs.get("weather"):
            raise serializers.ValidationError(
                "یکی از farm_uuid یا weather باید ارسال شود."
            )
        return attrs


class GrowthSimulationQueuedSerializer(serializers.Serializer):
    task_id = serializers.UUIDField()
    status_url = serializers.CharField()
    plant_name = serializers.CharField()


class GrowthStageMetricSerializer(serializers.Serializer):
    start = serializers.FloatField()
    end = serializers.FloatField()
    min = serializers.FloatField()
    max = serializers.FloatField()
    avg = serializers.FloatField()


class GrowthStageSerializer(serializers.Serializer):
    order = serializers.IntegerField()
    stage_code = serializers.CharField()
    stage_name = serializers.CharField()
    start_date = serializers.DateField()
    end_date = serializers.DateField()
    days_count = serializers.IntegerField()
    metrics = serializers.JSONField()


class GrowthPaginationSerializer(serializers.Serializer):
    page = serializers.IntegerField()
    page_size = serializers.IntegerField()
    total_items = serializers.IntegerField()
    total_pages = serializers.IntegerField()
    has_next = serializers.BooleanField()
    has_previous = serializers.BooleanField()


class GrowthSimulationResultSerializer(serializers.Serializer):
    plant_name = serializers.CharField()
    dynamic_parameters = serializers.ListField(child=serializers.CharField())
    engine = serializers.CharField(allow_null=True)
    model_name = serializers.CharField(allow_null=True)
    scenario_id = serializers.IntegerField(allow_null=True)
    simulation_warning = serializers.CharField(allow_null=True, allow_blank=True)
    summary_metrics = serializers.JSONField()
    stage_timeline = GrowthStageSerializer(many=True)
    stages_page = GrowthStageSerializer(many=True)
    pagination = GrowthPaginationSerializer()
    daily_records_count = serializers.IntegerField()
    default_page_size = serializers.IntegerField()



class CurrentFarmChartRequestSerializer(PlantNameAliasMixin, serializers.Serializer):
    farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه")
    plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه")
    irrigation_recommendation = serializers.JSONField(required=False)
    fertilization_recommendation = serializers.JSONField(required=False)

    def validate(self, attrs):
        return self._resolve_plant_name(attrs, required=False)


class CurrentFarmChartResponseSerializer(serializers.Serializer):
    farm_uuid = serializers.CharField(allow_null=True)
    plant_name = serializers.CharField()
    engine = serializers.CharField(allow_null=True)
    model_name = serializers.CharField(allow_null=True)
    scenario_id = serializers.IntegerField(allow_null=True)
    simulation_warning = serializers.CharField(allow_null=True, allow_blank=True)
    categories = serializers.ListField(child=serializers.CharField())
    series = serializers.JSONField()
    summary = serializers.JSONField()
    current_state = serializers.JSONField()
    metrics = serializers.JSONField()
    daily_output = serializers.JSONField()


class HarvestPredictionRequestSerializer(PlantNameAliasMixin, serializers.Serializer):
    farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه")
    plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه")
    irrigation_recommendation = serializers.JSONField(required=False)
    fertilization_recommendation = serializers.JSONField(required=False)

    def validate(self, attrs):
        return self._resolve_plant_name(attrs, required=False)


class HarvestPredictionResponseSerializer(serializers.Serializer):
    date = serializers.CharField()
    dateFormatted = serializers.CharField()
    daysUntil = serializers.IntegerField()
    description = serializers.CharField()
    optimalWindowStart = serializers.CharField()
    optimalWindowEnd = serializers.CharField()
    gddDetails = serializers.JSONField()


class YieldPredictionRequestSerializer(PlantNameAliasMixin, serializers.Serializer):
    farm_uuid = serializers.UUIDField(help_text="شناسه یکتای مزرعه")
    plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه")
    irrigation_recommendation = serializers.JSONField(required=False)
    fertilization_recommendation = serializers.JSONField(required=False)

    def validate(self, attrs):
        return self._resolve_plant_name(attrs, required=False)


class YieldPredictionResponseSerializer(serializers.Serializer):
    farm_uuid = serializers.CharField()
    plant_name = serializers.CharField(allow_null=True)
    predictedYieldTons = serializers.FloatField()
    predictedYieldRaw = serializers.FloatField()
    unit = serializers.CharField()
    sourceUnit = serializers.CharField()
    simulationEngine = serializers.CharField(allow_null=True)
    simulationModel = serializers.CharField(allow_null=True)
    scenarioId = serializers.IntegerField(allow_null=True)
    simulationWarning = serializers.CharField(allow_null=True, allow_blank=True)
    supportingMetrics = serializers.JSONField()


class YieldHarvestSummaryQuerySerializer(serializers.Serializer):
    farm_uuid = serializers.UUIDField(required=True, help_text="شناسه یکتای مزرعه")
    season_year = serializers.IntegerField(required=False, help_text="سال زراعی")
    crop_name = serializers.CharField(required=False, allow_blank=True, help_text="نام محصول")
    include_narrative = serializers.BooleanField(
        required=False,
        default=False,
        help_text="در صورت true بودن، بخش روایت نیز در آینده اضافه می شود.",
    )
    irrigation_recommendation = QueryJSONField(
        required=False,
        allow_null=True,
        help_text="برنامه آبیاری به صورت JSON برای تزریق به PCSE.",
    )
    fertilization_recommendation = QueryJSONField(
        required=False,
        allow_null=True,
        help_text="برنامه کودهی به صورت JSON برای تزریق به PCSE.",
    )

    def validate(self, attrs):
        raw_crop_name = attrs.get("crop_name")
        if raw_crop_name in (None, "") and hasattr(self, "initial_data"):
            raw_crop_name = self.initial_data.get("plant_name") or self.initial_data.get("crop")
        if raw_crop_name not in (None, ""):
            resolved_crop_name = apps.get_app_config("plant").resolve_plant_name(str(raw_crop_name))
            attrs["crop_name"] = resolved_crop_name or str(raw_crop_name).strip()
        return attrs


class YieldHarvestSummaryResponseSerializer(serializers.Serializer):
    farm_uuid = serializers.CharField()
    season_highlights_card = serializers.JSONField()
    yield_prediction = serializers.JSONField()
    harvest_prediction_card = serializers.JSONField()
    harvest_readiness_zones = serializers.JSONField()
    yield_quality_bands = serializers.JSONField()
    harvest_operations_card = serializers.JSONField()
    yield_prediction_chart = serializers.JSONField()
