"""
ساخت دیتای خاک و هواشناسی کاربر از farm_data، location_data و weather — Schema-agnostic
هر سنسور = یک کاربر. شناسایی با farm_uuid.

مدل‌های Django داخل توابع import می‌شوند تا از AppRegistryNotReady جلوگیری شود.
"""
from datetime import date

from django.db.models import Model


EXCLUDE_FIELD_NAMES = {"id", "created_at", "updated_at", "task_id", "recorded_at", "fetched_at"}


def _model_to_data_fields(instance: Model, exclude: set[str] | None = None) -> dict:
    """
    استخراج فیلدهای داده از یک instance با استفاده از introspection.
    تغییرات بعدی در مدل باعث شکستن نمی‌شود.
    """
    exclude = exclude or set()
    out: dict = {}
    for f in instance._meta.get_fields():
        if f.many_to_many or f.one_to_many or f.one_to_one and f.auto_created:
            continue
        if f.name in exclude or f.name in EXCLUDE_FIELD_NAMES:
            continue
        if hasattr(f, "related_model") and f.related_model:
            continue  # FK
        try:
            val = getattr(instance, f.name, None)
            if val is not None:
                out[f.name] = val
        except Exception:
            pass
    return out


def build_user_soil_text(sensor_uuid: str) -> str | None:
    """
    ساخت متن قابل embed برای یک سنسور (کاربر).
    از SensorData → SoilLocation → latest remote sensing snapshots خوانده می‌شود.

    Returns:
        متن متنی قابل چانک، یا None اگر سنسور یافت نشد.
    """
    from farm_data.models import SensorData
    from location_data.satellite_snapshot import (
        build_farmer_block_aggregated_snapshot,
        build_location_block_satellite_snapshots,
    )

    try:
        sensor = SensorData.objects.select_related("center_location").get(
            farm_uuid=sensor_uuid
        )
    except SensorData.DoesNotExist:
        return None

    parts: list[str] = []

    # شناسه سنسور
    parts.append(f"سنسور: {sensor.farm_uuid}")

    # موقعیت مزرعه
    loc = sensor.center_location
    parts.append(
        f"موقعیت مزرعه: عرض {loc.latitude}، طول {loc.longitude}"
    )

    # خوانش‌های سنسور (schema-agnostic)
    sensor_fields = _model_to_data_fields(
        sensor, exclude={"farm_uuid", "center_location_id", "center_location", "location"}
    )
    if sensor_fields:
        sensor_lines = [f"  {k}: {v}" for k, v in sorted(sensor_fields.items())]
        parts.append("خوانش‌های سنسور:\n" + "\n".join(sensor_lines))

    aggregated_snapshot = build_farmer_block_aggregated_snapshot(
        loc,
        sensor_payload=sensor.sensor_payload,
    )
    aggregated_metrics = aggregated_snapshot.get("resolved_metrics") or {}
    if aggregated_metrics:
        lines = [f"  {k}: {v}" for k, v in sorted(aggregated_metrics.items())]
        parts.append("خلاصه تجمیع‌شده بلوک‌های اصلی:\n" + "\n".join(lines))

    snapshots = build_location_block_satellite_snapshots(
        loc,
        sensor_payload=sensor.sensor_payload,
    )
    if snapshots:
        snapshot_lines = []
        for snapshot in snapshots:
            metrics = snapshot.get("resolved_metrics") or {}
            if not metrics:
                continue
            lines = [f"    {k}: {v}" for k, v in sorted(metrics.items())]
            snapshot_lines.append(
                f"  بلوک اصلی {snapshot.get('block_code') or 'farm'}:\n" + "\n".join(lines)
            )
        if snapshot_lines:
            parts.append("داده‌های تجمیع‌شده بلوک‌های اصلی:\n" + "\n".join(snapshot_lines))

    return "\n\n".join(parts) if len(parts) > 1 else None


def get_all_sensor_uuids() -> list[str]:
    """لیست همه farm_uuid های موجود."""
    from farm_data.models import SensorData

    return [
        str(u) for u in
        SensorData.objects.values_list("farm_uuid", flat=True).distinct()
    ]


def build_user_weather_text(sensor_uuid: str) -> str | None:
    """
    ساخت متن هواشناسی قابل embed برای یک سنسور (کاربر).
    پیش‌بینی ۷ روز آینده از WeatherForecast خوانده می‌شود.

    Returns:
        متن فارسی ساختاریافته، یا None اگر داده‌ای نباشد.
    """
    from farm_data.models import SensorData
    from weather.models import WeatherForecast

    try:
        sensor = SensorData.objects.select_related("center_location").get(
            farm_uuid=sensor_uuid
        )
    except SensorData.DoesNotExist:
        return None

    loc = sensor.center_location
    forecasts = (
        WeatherForecast.objects.filter(
            location=loc,
            forecast_date__gte=date.today(),
        )
        .order_by("forecast_date")[:7]
    )
    if not forecasts:
        return None

    parts: list[str] = []
    parts.append(f"پیش‌بینی هواشناسی سنسور {sensor_uuid} (موقعیت: {loc.latitude}, {loc.longitude})")

    for fc in forecasts:
        fc_data = _model_to_data_fields(
            fc, exclude={"location", "location_id", "forecast_date"}
        )
        lines = [f"    {k}: {v}" for k, v in sorted(fc_data.items())]
        day_text = f"  تاریخ {fc.forecast_date}:\n" + "\n".join(lines)
        parts.append(day_text)

    return "\n\n".join(parts) if len(parts) > 1 else None


def load_user_sources() -> list[tuple[str, str]]:
    """
    بارگذاری منابع دیتای کاربران از DB (خاک + هواشناسی).
    Returns: [(source_id, content), ...]
    source_id = user:{uuid} یا weather:{uuid}
    """
    uuids = get_all_sensor_uuids()
    sources: list[tuple[str, str]] = []
    for uid in uuids:
        text = build_user_soil_text(str(uid))
        if text and text.strip():
            sources.append((f"user:{uid}", text))
        weather_text = build_user_weather_text(str(uid))
        if weather_text and weather_text.strip():
            sources.append((f"weather:{uid}", weather_text))
    return sources


def build_plant_text(plant_name: str, growth_stage: str) -> str | None:
    """
    ساخت متن اطلاعات گیاه از snapshotهای `farm_data` برای استفاده در context LLM.
    """
    from farm_data.models import PlantCatalogSnapshot
    from farm_data.services import build_plant_text_from_snapshot

    plant = PlantCatalogSnapshot.objects.filter(name=plant_name).first()
    if not plant:
        return None

    return build_plant_text_from_snapshot(plant, growth_stage)


def build_irrigation_method_text(method_name: str) -> str | None:
    """
    ساخت متن مشخصات روش آبیاری از جدول IrrigationMethod برای استفاده در context LLM.
    """
    from irrigation.models import IrrigationMethod

    method = IrrigationMethod.objects.filter(name=method_name).first()
    if not method:
        return None

    lines = [f"روش آبیاری: {method.name}"]
    if method.category:
        lines.append(f"دسته‌بندی: {method.category}")
    if method.description:
        lines.append(f"توضیحات: {method.description}")
    if method.water_efficiency_percent is not None:
        lines.append(f"راندمان مصرف آب: {method.water_efficiency_percent}%")
    if method.water_pressure_required:
        lines.append(f"فشار مورد نیاز: {method.water_pressure_required}")
    if method.flow_rate:
        lines.append(f"دبی جریان: {method.flow_rate}")
    if method.coverage_area:
        lines.append(f"مساحت پوشش: {method.coverage_area}")
    if method.soil_type:
        lines.append(f"نوع خاک مناسب: {method.soil_type}")
    if method.climate_suitability:
        lines.append(f"اقلیم مناسب: {method.climate_suitability}")

    return "\n".join(lines)
