"""
Middleware для проверки подтверждения email пользователя.
Блокирует все запросы, кроме связанных с подтверждением email.
"""
from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError


class EmailVerificationMiddleware(MiddlewareMixin):
    """
    Middleware для проверки подтверждения email.
    
    Разрешает доступ к следующим endpoints без подтверждения email:
    - /api/users/auth/register/
    - /api/users/auth/login/
    - /api/users/auth/telegram/
    - /api/users/auth/telegram/bot-info/
    - /api/users/auth/token/refresh/
    - /api/users/auth/verify-email/
    - /api/users/auth/resend-verification/
    - /api/users/auth/password-reset/
    - /api/users/auth/password-reset-confirm/
    - /api/users/auth/logout/
    - /api/docs/ (Swagger документация)
    - /api/schema/ (API схема)
    """
    
    # Список путей, которые разрешены без подтверждения email
    ALLOWED_PATHS = [
        # Аутентификация и регистрация
        '/api/auth/register/',
        '/api/auth/login/',
        '/api/auth/telegram/',
        '/api/auth/telegram/bot-info/',
        '/api/auth/token/refresh/',
        '/api/auth/verify-email/',
        '/api/auth/resend-verification/',
        '/api/auth/change-password/',
        '/api/auth/password-reset/',
        '/api/auth/password-reset-confirm/',
        '/api/auth/logout/',
        # API документация
        '/api/swagger/',
        '/api/swagger.json',
        '/api/swagger.yaml',
        '/api/redoc/',
        '/api/schema/',
        # Статические файлы и медиа
        '/static/',
        '/media/',
        # Admin панель
        '/admin/',
        # Health check
        '/health/',
    ]
    
    def process_request(self, request):
        """
        Обработка запроса перед передачей в view.
        """
        # Проверяем, является ли путь разрешенным
        if self._is_allowed_path(request.path):
            return None  # Разрешаем запрос
        
        # Проверяем, есть ли токен авторизации
        if not self._has_auth_token(request):
            return None  # Если нет токена, пусть другие middleware обрабатывают
        
        # Получаем пользователя из токена
        user = self._get_user_from_token(request)
        
        if user is None:
            return None  # Если не удалось получить пользователя, пусть другие middleware обрабатывают
        
        # Проверяем подтверждение email
        if not user.email_verified:
            return JsonResponse(
                {
                    'success': False,
                    'error': 'email_not_verified',
                    'message': 'Необходимо подтвердить email адрес для доступа к платформе',
                    'email': user.email,
                },
                status=403
            )
        
        return None  # Разрешаем запрос
    
    def _is_allowed_path(self, path: str) -> bool:
        """
        Проверяет, является ли путь разрешенным.
        """
        # Проверяем точное совпадение
        if path in self.ALLOWED_PATHS:
            return True
        
        # Проверяем, начинается ли путь с разрешенного
        for allowed_path in self.ALLOWED_PATHS:
            if path.startswith(allowed_path):
                return True
        
        # Разрешаем доступ к статическим файлам и медиа
        if path.startswith('/static/') or path.startswith('/media/'):
            return True
        
        # Разрешаем доступ к admin панели
        if path.startswith('/admin/'):
            return True
        
        return False
    
    def _has_auth_token(self, request) -> bool:
        """
        Проверяет наличие токена авторизации в запросе.
        """
        # Проверяем заголовок Authorization
        auth_header = request.META.get('HTTP_AUTHORIZATION', '')
        if auth_header.startswith('Bearer '):
            return True
        
        # Проверяем токен в cookies (если используется)
        if 'access_token' in request.COOKIES:
            return True
        
        return False
    
    def _get_user_from_token(self, request):
        """
        Получает пользователя из JWT токена.
        """
        try:
            # Используем JWTAuthentication для получения пользователя
            jwt_auth = JWTAuthentication()
            header = jwt_auth.get_header(request)
            if header is None:
                return None
            
            raw_token = jwt_auth.get_raw_token(header)
            if raw_token is None:
                return None
            
            validated_token = jwt_auth.get_validated_token(raw_token)
            user = jwt_auth.get_user(validated_token)
            return user
        except (InvalidToken, TokenError, AttributeError, TypeError, ValueError):
            # Если токен невалиден или отсутствует, возвращаем None
            return None
        except Exception:
            # Для любых других ошибок также возвращаем None
            return None

