"""
Celery задачи для подписок.
"""
from celery import shared_task
from django.utils import timezone
from datetime import timedelta
import logging

logger = logging.getLogger(__name__)


@shared_task
def check_expired_subscriptions():
    """
    Проверка истекших подписок.
    
    Запускается каждый день в 00:00.
    """
    from .models import Subscription
    
    subscriptions = Subscription.objects.filter(
        status__in=['trial', 'active']
    )
    
    # Оптимизация: используем list() для кеширования queryset
    subscriptions_list = list(subscriptions)
    expired_count = 0
    for subscription in subscriptions_list:
        subscription.check_expiration()
        if subscription.status in ['expired', 'past_due']:
            expired_count += 1
    
    logger.info(f"Checked {len(subscriptions_list)} subscriptions, {expired_count} expired")
    return f"Проверено {subscriptions.count()} подписок, истекло {expired_count}"


@shared_task
def send_expiration_warnings():
    """
    Отправка предупреждений об истечении подписок.
    
    Отправляет уведомления за 7, 3 и 1 день до истечения.
    Запускается каждый день в 10:00.
    """
    from .models import Subscription
    from apps.notifications.services import NotificationService
    
    now = timezone.now()
    warning_days = [7, 3, 1]
    
    sent_count = 0
    
    for days in warning_days:
        warning_date = now + timedelta(days=days)
        
        # Находим подписки, истекающие через N дней
        # Оптимизация: используем select_related для избежания N+1 запросов
        subscriptions = Subscription.objects.filter(
            status__in=['trial', 'active'],
            end_date__date=warning_date.date(),
            auto_renew=False
        ).select_related('user', 'plan')
        
        for subscription in subscriptions:
            # Отправляем уведомление
            NotificationService.create_notification_with_telegram(
                recipient=subscription.user,
                notification_type='subscription_expiring',
                title=f'Подписка истекает через {days} дн.',
                message=f'Ваша подписка "{subscription.plan.name}" истекает через {days} дней. Продлите подписку, чтобы не потерять доступ.',
                related_object=subscription
            )
            sent_count += 1
    
    logger.info(f"Sent {sent_count} expiration warnings")
    return f"Отправлено {sent_count} предупреждений"


@shared_task
def reset_monthly_usage():
    """
    Сброс месячного использования.
    
    Запускается 1-го числа каждого месяца в 00:00.
    """
    from .models import Subscription
    
    subscriptions = Subscription.objects.filter(
        status__in=['trial', 'active']
    )
    
    # Оптимизация: используем bulk_update вместо цикла с save()
    subscriptions_to_update = []
    for subscription in subscriptions:
        subscription.lessons_used = 0
        subscription.video_minutes_used = 0
        subscriptions_to_update.append(subscription)
    
    if subscriptions_to_update:
        Subscription.objects.bulk_update(
            subscriptions_to_update, 
            ['lessons_used', 'video_minutes_used'], 
            batch_size=100
        )
    
    logger.info(f"Reset usage for {len(subscriptions_to_update)} subscriptions")
    return f"Сброшено использование для {subscriptions.count()} подписок"


@shared_task
def auto_renew_subscriptions():
    """
    Автопродление подписок.
    
    Продлевает подписки с auto_renew=True, которые истекают сегодня.
    Запускается каждый день в 02:00.
    """
    from .models import Subscription, Payment
    
    today = timezone.now().date()
    
    # Находим подписки для продления
    # Оптимизация: используем select_related для избежания N+1 запросов
    subscriptions = Subscription.objects.filter(
        status='active',
        auto_renew=True,
        end_date__date=today
    ).select_related('user', 'plan')
    
    renewed_count = 0
    failed_count = 0
    
    for subscription in subscriptions:
        try:
            # Создаем платеж для продления
            payment = Payment.objects.create(
                user=subscription.user,
                subscription=subscription,
                amount=subscription.plan.price,
                currency=subscription.plan.currency,
                payment_method='card',  # Используем сохраненную карту
                description=f"Автопродление подписки {subscription.plan.name}"
            )
            
            # Здесь должна быть логика списания с сохраненной карты
            # Пока просто помечаем как успешный
            payment.mark_as_succeeded()
            
            # Продлеваем подписку
            subscription.renew()
            
            renewed_count += 1
            
        except Exception as e:
            logger.error(f"Failed to renew subscription {subscription.id}: {e}")
            subscription.status = 'past_due'
            subscription.save()
            failed_count += 1
    
    logger.info(f"Renewed {renewed_count} subscriptions, {failed_count} failed")
    return f"Продлено {renewed_count} подписок, ошибок {failed_count}"


@shared_task
def cleanup_old_payment_history():
    """
    Очистка старой истории платежей.
    
    Удаляет записи старше 1 года.
    Запускается 1-го числа каждого месяца в 03:00.
    """
    from .models import PaymentHistory
    
    cutoff_date = timezone.now() - timedelta(days=365)
    
    deleted = PaymentHistory.objects.filter(
        created_at__lt=cutoff_date
    ).delete()[0]
    
    logger.info(f"Deleted {deleted} old payment history records")
    return f"Удалено {deleted} старых записей"


@shared_task
def generate_subscription_reports():
    """
    Генерация отчетов по подпискам.
    
    Создает ежемесячные отчеты по подпискам.
    Запускается 1-го числа каждого месяца в 09:00.
    """
    from .models import Subscription, Payment
    from django.db.models import Count, Sum
    
    # Статистика за прошлый месяц
    now = timezone.now()
    start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
    start_of_prev_month = (start_of_month - timedelta(days=1)).replace(day=1)
    
    # Подписки
    new_subscriptions = Subscription.objects.filter(
        created_at__gte=start_of_prev_month,
        created_at__lt=start_of_month
    ).count()
    
    cancelled_subscriptions = Subscription.objects.filter(
        cancelled_at__gte=start_of_prev_month,
        cancelled_at__lt=start_of_month
    ).count()
    
    # Платежи
    payments_stats = Payment.objects.filter(
        created_at__gte=start_of_prev_month,
        created_at__lt=start_of_month,
        status='succeeded'
    ).aggregate(
        total_count=Count('id'),
        total_amount=Sum('amount')
    )
    
    report = {
        'period': f"{start_of_prev_month.strftime('%Y-%m')}",
        'new_subscriptions': new_subscriptions,
        'cancelled_subscriptions': cancelled_subscriptions,
        'total_payments': payments_stats['total_count'] or 0,
        'total_revenue': float(payments_stats['total_amount'] or 0)
    }
    
    logger.info(f"Generated subscription report: {report}")
    return f"Создан отчет за {report['period']}"
