"""
Middleware для проверки подписки и ограничений.
"""
from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
from django.urls import resolve
import logging

logger = logging.getLogger(__name__)


class SubscriptionMiddleware(MiddlewareMixin):
    """
    Middleware для проверки подписки и ограничений по ученикам.
    
    Проверяет:
    - Наличие активной подписки
    - Лимиты по количеству учеников (для типа "за ученика")
    - Лимиты по функционалу
    """
    
    # URL-пути, которые не требуют проверки подписки
    EXEMPT_PATHS = [
        '/api/auth/',
        '/api/subscriptions/',
        '/admin/',
        '/api/docs/',
    ]
    
    # URL-пути, которые требуют проверки лимита учеников
    STUDENT_LIMIT_PATHS = [
        '/api/clients/',
        '/api/users/clients/',
    ]
    
    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        Обработка запроса ПЕРЕД вызовом view.
        Используем process_view вместо process_request, чтобы быть уверенными,
        что AuthenticationMiddleware уже обработал запрос.
        """
        # Логируем ВСЕ POST/PUT/PATCH/DELETE запросы для отладки (уровень debug, не error)
        if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
            logger.debug(
                f"🔍 SubscriptionMiddleware.process_view: {request.method} {request.path}"
            )
        
        # Пропускаем exempt пути (это нормальное поведение, не ошибка)
        if any(request.path.startswith(path) for path in self.EXEMPT_PATHS):
            # EXEMPT пути - это нормальное поведение, логируем только на уровне debug
            logger.debug(f"SubscriptionMiddleware: EXEMPT path {request.path} (skipping subscription check)")
            return None
        
        # Проверяем наличие атрибута user
        if not hasattr(request, 'user'):
            # Это может быть нормальным для некоторых путей, логируем debug
            logger.debug(f"SubscriptionMiddleware: no user attribute for {request.path}")
            return None
        
        # Проверяем только для аутентифицированных пользователей
        if not request.user.is_authenticated:
            # Для неаутентифицированных пользователей пропускаем (DRF сам вернет 401)
            logger.debug(f"SubscriptionMiddleware: user not authenticated for {request.path}")
            return None
        
        # Проверяем только для менторов
        if not hasattr(request.user, 'role') or request.user.role != 'mentor':
            # Для не-менторов пропускаем (это нормальное поведение)
            logger.debug(f"SubscriptionMiddleware: user is not mentor (role={getattr(request.user, 'role', None)}) for {request.path}")
            return None
        
        # Логируем начало проверки для всех POST/PUT/PATCH/DELETE запросов (уровень debug)
        if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
            logger.debug(
                f"SubscriptionMiddleware: Checking subscription for {request.method} {request.path}, "
                f"user={request.user.id} ({request.user.email}), role={request.user.role}"
            )
        
        # Получаем активную подписку
        from .services import SubscriptionService
        from .models import Subscription
        from django.utils import timezone
        
        # Получаем все подписки пользователя (включая истекшие для диагностики)
        all_subscriptions = Subscription.objects.filter(
            user=request.user,
            status__in=['trial', 'active']
        ).order_by('-end_date')
        
        # Также проверяем истекшие подписки для диагностики
        expired_subscriptions = Subscription.objects.filter(
            user=request.user,
            status__in=['expired', 'past_due', 'cancelled']
        ).order_by('-end_date')
        
        # Проверяем, есть ли действительно активная подписка
        active_subscription = None
        for sub in all_subscriptions:
            if sub.is_active():
                active_subscription = sub
                break
        
        # Логируем информацию о всех подписках для диагностики
        if not active_subscription and (all_subscriptions.exists() or expired_subscriptions.exists()):
            logger.warning(
                f"SubscriptionMiddleware: user={request.user.id} has subscriptions but none are active. "
                f"Active status subscriptions: {all_subscriptions.count()}, "
                f"Expired status subscriptions: {expired_subscriptions.count()}"
            )
            if expired_subscriptions.exists():
                expired = expired_subscriptions.first()
                logger.warning(
                    f"Latest expired subscription: id={expired.id}, status={expired.status}, "
                    f"end_date={expired.end_date}, is_active={expired.is_active()}"
                )
        
        # Логируем для отладки
        logger.info(
            f"SubscriptionMiddleware: path={request.path}, method={request.method}, "
            f"user={request.user.id}, has_active_subscription={active_subscription is not None}, "
            f"total_subscriptions={all_subscriptions.count()}"
        )
        
        # Если нет активной подписки, блокируем все операции изменения данных
        if not active_subscription:
            # Разрешаем доступ к некоторым путям (подписки, авторизация, админка)
            if request.path.startswith('/api/subscriptions/'):
                return None
            
            # Блокируем все операции изменения данных (POST, PUT, PATCH, DELETE)
            if request.method in ['POST', 'PUT', 'PATCH', 'DELETE']:
                # Получаем информацию о подписке для сообщения об ошибке
                from apps.users.models import Client
                current_clients_count = Client.objects.filter(mentors=request.user).count()
                
                # Если подписка есть, но истекла (проверяем истекшие подписки)
                expired_subscription = expired_subscriptions.first() if expired_subscriptions.exists() else (all_subscriptions.first() if all_subscriptions.exists() else None)
                if expired_subscription:
                    logger.error(
                        f"❌ BLOCKING REQUEST: path={request.path}, method={request.method}, "
                        f"user={request.user.id} ({request.user.email}) - subscription expired (id={expired_subscription.id}, "
                        f"status={expired_subscription.status}, end_date={expired_subscription.end_date}, "
                        f"is_active={expired_subscription.is_active()})"
                    )
                    response_data = {
                        'error': 'Подписка истекла',
                        'detail': 'Ваша подписка истекла. Для продолжения работы необходимо продлить подписку.',
                        'subscription_id': expired_subscription.id,
                        'end_date': expired_subscription.end_date.strftime('%Y-%m-%d') if expired_subscription.end_date else None,
                        'current_students': current_clients_count,
                        'paid_students': expired_subscription.student_count if expired_subscription.plan.subscription_type == 'per_student' else None,
                        'requires_renewal': True
                    }
                    response = JsonResponse(response_data, status=403)
                    logger.error(f"✅ Returning 403 response for {request.path} with data: {response_data}")
                    return response
                else:
                    # Если подписки нет вообще
                    logger.error(
                        f"❌ BLOCKING REQUEST: path={request.path}, method={request.method}, "
                        f"user={request.user.id} - no active subscription"
                    )
                    response = JsonResponse(
                        {
                            'error': 'Требуется активная подписка',
                            'detail': 'Для использования платформы необходимо оформить подписку'
                        },
                        status=403
                    )
                    logger.error(f"✅ Returning 403 response for {request.path}")
                    return response
            
            # Для GET запросов разрешаем только чтение (можно показать данные, но не редактировать)
            return None
        
        # Проверяем лимит учеников для типа "за ученика"
        if active_subscription.plan.subscription_type == 'per_student':
            # Проверяем только для путей, связанных с клиентами
            if any(request.path.startswith(path) for path in self.STUDENT_LIMIT_PATHS):
                if request.method in ['POST']:  # При создании нового клиента
                    from apps.users.models import Client
                    current_clients_count = Client.objects.filter(
                        mentor=request.user
                    ).count()
                    
                    # Разрешаем добавление, но отслеживаем превышение
                    # Если превышен лимит оплаченных учеников, обновляем информацию о неоплаченных
                    if current_clients_count >= active_subscription.student_count:
                        # Рассчитываем количество неоплаченных учеников
                        unpaid_count = current_clients_count - active_subscription.student_count + 1  # +1 потому что добавляем нового
                        
                        # Обновляем подписку с информацией о неоплаченных учениках
                        active_subscription.unpaid_students_count = unpaid_count
                        
                        # Рассчитываем доплату
                        from .services import SubscriptionService
                        payment_data = SubscriptionService.calculate_extra_students_payment(
                            subscription=active_subscription,
                            new_student_count=current_clients_count + 1
                        )
                        active_subscription.pending_payment_amount = payment_data['payment_amount']
                        active_subscription.save(update_fields=['unpaid_students_count', 'pending_payment_amount'])
                        
                        # Разрешаем добавление, но возвращаем информацию о необходимости доплаты
                        # Это будет обработано на фронтенде для показа модального окна
                        # Не блокируем запрос, но добавляем заголовок с информацией
                        # Фактически, мы разрешаем создание, но фронтенд должен проверить ответ
                        # и показать модальное окно
                        pass  # Разрешаем создание, фронтенд обработает через API
        
        # Проверяем лимиты для ежемесячной подписки
        else:
            if any(request.path.startswith(path) for path in self.STUDENT_LIMIT_PATHS):
                if request.method in ['POST']:
                    if not active_subscription.check_limit('clients'):
                        max_clients = active_subscription.plan.max_clients
                        from apps.users.models import Client
                        current_clients_count = Client.objects.filter(
                            mentor=request.user
                        ).count()
                        
                        return JsonResponse(
                            {
                                'error': 'Достигнут лимит учеников',
                                'detail': f'Ваш тарифный план позволяет добавить максимум {max_clients} учеников.',
                                'current_count': current_clients_count,
                                'max_count': max_clients
                            },
                            status=403
                        )
        
        return None

