from collections import defaultdict

from django.db import transaction
from django.db.models import Count
from django.utils import timezone

from apps.business.distributor.models import BrandAmbassadorEligibility, DistributorID


def refresh_brand_ambassadors(min_distributor_ids: int = 100, opportunity_bundle_id: str | None = None) -> dict:
    """Recompute Executive Director eligibility snapshots.

    Qualification rule: a user qualifies when ANY single distributor ID they own
    has at least `min_distributor_ids` direct referrals under it (IDs where
    sponsor_distributor points to that ID, regardless of who owns those IDs).

    For each (user, opportunity_bundle) pair the snapshot stores the MAX direct-referral count
    across all of that user's distributor IDs in the opportunity_bundle.
    """
    base_qs = (
        DistributorID.objects
        .filter(product__opportunity_bundle__isnull=False)
        .select_related('product')
        .annotate(referral_count=Count('direct_referrals'))
    )
    if opportunity_bundle_id:
        base_qs = base_qs.filter(product__opportunity_bundle_id=opportunity_bundle_id)

    # Group in Python: max referral_count per (user_id, opportunity_bundle_id)
    user_scheme_max: dict = defaultdict(lambda: {'distributor_count': 0, 'last_at': None})
    for dist in base_qs:
        key = (dist.user_id, dist.product.opportunity_bundle_id)
        entry = user_scheme_max[key]
        if dist.referral_count > entry['distributor_count']:
            entry['distributor_count'] = dist.referral_count
        if dist.created_at and (entry['last_at'] is None or dist.created_at > entry['last_at']):
            entry['last_at'] = dist.created_at

    grouped = [
        {
            'user_id': k[0],
            'opportunity_bundle_id': k[1],
            'distributor_count': v['distributor_count'],
            'last_distributor_created_at': v['last_at'],
        }
        for k, v in user_scheme_max.items()
        if v['distributor_count'] >= min_distributor_ids
    ]

    now = timezone.now()
    active_keys = {(row['user_id'], row['opportunity_bundle_id']) for row in grouped}

    with transaction.atomic():
        existing_qs = BrandAmbassadorEligibility.objects.all()
        if opportunity_bundle_id:
            existing_qs = existing_qs.filter(opportunity_bundle_id=opportunity_bundle_id)

        deactivated = 0
        for existing in existing_qs.select_for_update():
            key = (existing.user_id, existing.opportunity_bundle_id)
            if key not in active_keys and existing.is_active:
                existing.is_active = False
                existing.save(update_fields=['is_active', 'updated_at'])
                deactivated += 1

        created = 0
        updated = 0
        for row in grouped:
            defaults = {
                'distributor_count': row['distributor_count'],
                'last_distributor_created_at': row['last_distributor_created_at'],
                'is_active': True,
            }
            obj, is_created = BrandAmbassadorEligibility.objects.update_or_create(
                user_id=row['user_id'],
                opportunity_bundle_id=row['opportunity_bundle_id'],
                defaults=defaults,
            )
            if is_created:
                obj.qualified_at = now
                obj.save(update_fields=['qualified_at'])
                created += 1
            else:
                updated += 1

    return {
        'created': created,
        'updated': updated,
        'deactivated': deactivated,
        'qualified_count': len(grouped),
        'min_distributor_ids': min_distributor_ids,
        'opportunity_bundle_id': opportunity_bundle_id,
    }
