"""
Сигналы для реферальной системы.
"""
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from decimal import Decimal

from .models import (
    UserReferralProfile,
    BonusAccount,
    ReferralLevel,
    ReferralSettings,
    ReferralEarning,
    generate_referral_code
)


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_referral_profile(sender, instance, created, **kwargs):
    """Создать реферальный профиль и бонусный счет при создании пользователя."""
    if created:
        # Генерируем уникальный код
        code = generate_referral_code()
        while UserReferralProfile.objects.filter(referral_code=code).exists():
            code = generate_referral_code()
        
        # Создаем профиль
        profile = UserReferralProfile.objects.create(
            user=instance,
            referral_code=code
        )
        
        # Устанавливаем начальный уровень
        level1 = ReferralLevel.objects.filter(level=1).first()
        if level1:
            profile.current_level = level1
            profile.save(update_fields=['current_level'])
        
        # Создаем бонусный счет
        BonusAccount.objects.create(user=instance)


@receiver(post_save, sender='subscriptions.Payment')
def process_referral_earnings(sender, instance, created, **kwargs):
    """Обработать начисление бонусов с рефералов после успешного платежа."""
    # Проверяем что платеж успешен
    if instance.status != 'succeeded':
        return
    
    # Проверяем что это не повторная обработка
    if ReferralEarning.objects.filter(payment=instance).exists():
        return
    
    # Получаем пользователя
    user = instance.user
    
    try:
        profile = user.referral_profile
    except UserReferralProfile.DoesNotExist:
        return
    
    # Если нет реферера - выходим
    if not profile.referred_by:
        return
    
    settings_obj = ReferralSettings.get_settings()
    payment_amount = instance.amount
    
    # Уровень 1: начисляем прямому рефереру
    try:
        referrer_profile = profile.referred_by.referral_profile
        referrer_bonus_account = profile.referred_by.bonus_account
        
        # Рассчитываем комиссию
        commission_amount = payment_amount * (settings_obj.level1_commission / 100)
        
        # Начисляем бонусы
        referrer_bonus_account.add_bonus(
            commission_amount,
            reason=f'Комиссия с реферала {user.email}'
        )
        
        # Создаем запись о заработке
        ReferralEarning.objects.create(
            referrer=profile.referred_by,
            referral=user,
            payment=instance,
            level=1,
            payment_amount=payment_amount,
            commission_percent=settings_obj.level1_commission,
            earned_amount=commission_amount
        )
        
        # Обновляем статистику
        referrer_profile.total_earned += commission_amount
        referrer_profile.save(update_fields=['total_earned'])
        
    except (UserReferralProfile.DoesNotExist, BonusAccount.DoesNotExist):
        pass
    
    # Уровень 2: начисляем рефереру реферера
    if profile.referred_by:
        try:
            level1_referrer_profile = profile.referred_by.referral_profile
            
            if level1_referrer_profile.referred_by:
                level2_referrer = level1_referrer_profile.referred_by
                level2_referrer_profile = level2_referrer.referral_profile
                level2_bonus_account = level2_referrer.bonus_account
                
                # Рассчитываем комиссию
                commission_amount = payment_amount * (settings_obj.level2_commission / 100)
                
                # Начисляем бонусы
                level2_bonus_account.add_bonus(
                    commission_amount,
                    reason=f'Комиссия с реферала 2 уровня {user.email}'
                )
                
                # Создаем запись о заработке
                ReferralEarning.objects.create(
                    referrer=level2_referrer,
                    referral=user,
                    payment=instance,
                    level=2,
                    payment_amount=payment_amount,
                    commission_percent=settings_obj.level2_commission,
                    earned_amount=commission_amount
                )
                
                # Обновляем статистику
                level2_referrer_profile.total_earned += commission_amount
                level2_referrer_profile.save(update_fields=['total_earned'])
                
        except (UserReferralProfile.DoesNotExist, BonusAccount.DoesNotExist):
            pass


@receiver(post_save, sender=UserReferralProfile)
def update_referrer_stats(sender, instance, created, **kwargs):
    """Обновить статистику реферера при добавлении нового реферала."""
    if created and instance.referred_by:
        try:
            referrer_profile = instance.referred_by.referral_profile
            settings_obj = ReferralSettings.get_settings()
            
            # Увеличиваем счетчик прямых рефералов
            referrer_profile.direct_referrals_count += 1
            referrer_profile.save(update_fields=['direct_referrals_count'])
            
            # Начисляем очки за прямого реферала
            referrer_profile.add_points(
                settings_obj.points_direct_referral,
                reason=f'Регистрация реферала {instance.user.email}'
            )
            
            # Если у реферера есть свой реферер - начисляем ему очки за непрямого реферала
            if referrer_profile.referred_by:
                try:
                    level2_referrer_profile = referrer_profile.referred_by.referral_profile
                    level2_referrer_profile.indirect_referrals_count += 1
                    level2_referrer_profile.save(update_fields=['indirect_referrals_count'])
                    
                    level2_referrer_profile.add_points(
                        settings_obj.points_indirect_referral,
                        reason=f'Регистрация непрямого реферала {instance.user.email}'
                    )
                except UserReferralProfile.DoesNotExist:
                    pass
                    
        except UserReferralProfile.DoesNotExist:
            pass

