# link_agregator/check_active/propagate.py
from django.utils import timezone

FIELDS_THAT_MEAN_HAVE_DATA = (
    "price", "title", "description", "images", "square_footage", "price_per_m2"
)
THRESHOLD_HAS_DATA = 0.70

def _value_present(val) -> bool:
    if val is None:
        return False
    if isinstance(val, str):
        return bool(val.strip())
    if isinstance(val, (list, dict, set, tuple)):
        return len(val) > 0
    return True

def _calc_has_data(instance) -> bool:
    fields = [f for f in FIELDS_THAT_MEAN_HAVE_DATA if hasattr(instance, f)]
    if not fields:
        return False
    filled = sum(1 for f in fields if _value_present(getattr(instance, f, None)))
    return (filled / len(fields)) >= THRESHOLD_HAS_DATA

def _safe_save(instance, update_fields):
    # Zapisz tylko istniejące, „concrete” pola – zabezpiecza przed różnicami środowiskowymi.
    concrete = {f.name for f in instance._meta.get_fields() if getattr(f, "concrete", False)}
    uf = [f for f in update_fields if f in concrete]
    instance.save(update_fields=uf if uf else None)

def propagate_from_page(page_obj, *, is_active: bool, reason: str | None = None):
    """
    Status-only propagate:
    - NIE tykamy check_active/check_active_date na NetworkMonitoredPage (bo ich tu nie ma).
    - Na stronie ustawiamy tylko is_active/inactive_date (+reason w meta).
    - Na Ads/AdsManual ustawiamy check_active_date, resetujemy flagi, liczymy has_data.
    """
    now_dt = timezone.now()
    today = now_dt.date()

    # --- NetworkMonitoredPage: tylko status + meta ---
    if is_active:
        page_obj.is_active = True
        page_obj.inactive_date = None
    else:
        page_obj.is_active = False
        page_obj.inactive_date = now_dt
        page_obj.meta = page_obj.meta or {}
        if reason:
            page_obj.meta["inactive_reason"] = reason

    _safe_save(page_obj, ["is_active", "inactive_date", "meta"])

    # --- Powiązane Ads/AdsManual ---
    related = []
    if getattr(page_obj, "network_ad_id", None):
        related.append(page_obj.network_ad)
    if getattr(page_obj, "network_ad_manual_id", None):
        related.append(page_obj.network_ad_manual)

    for ad in related:
        # UWAGA: po migracji 0011 nazwa pola to check_active_date
        if hasattr(ad, "check_active_date"):
            ad.check_active_date = today

        # processed_without_image jeżeli sprawdzane „z obrazka” i aktywne
        if is_active and getattr(ad, "check_active_from_image", False):
            ad.processed_without_image = True

        # status
        if is_active:
            ad.is_active = True
            ad.inactive_date = None
        else:
            ad.is_active = False
            ad.inactive_date = now_dt

        # 70% pól -> has_data (jeśli to pole istnieje)
        if hasattr(ad, "has_data"):
            ad.has_data = _calc_has_data(ad)

        # reset flag na Ads/AdsManual
        if hasattr(ad, "check_active"):
            ad.check_active = False
        if hasattr(ad, "check_active_from_image"):
            ad.check_active_from_image = False

        _safe_save(ad, [
            "is_active", "inactive_date", "check_active_date",
            "check_active", "check_active_from_image",
            "processed_without_image", "has_data",
        ])
