# accounts/views/profile.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from django.utils.decorators import method_decorator
from django.core.cache import cache
from rest_framework.decorators import action
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from .base import DummySerializer


class ProfileViewSet(viewsets.ViewSet):
    permission_classes = (IsAuthenticated,)
    serializer_class = DummySerializer

    def view_profile(self, request):
        """Display user profile page"""
        base_domain = request.build_absolute_uri('/')
        return render(request, 'profile.html', {
            'user': request.user,
            'active_tab': 'profile',
            'base_domain': base_domain
        })

    def edit_profile(self, request):
        """Handle profile updates (currently just displays profile)"""
        base_domain = request.build_absolute_uri('/')
        return render(request, 'profile.html', {
            'user': request.user,
            'active_tab': 'profile',
            'base_domain': base_domain
        })

    @action(detail=False, methods=['POST'], url_path='change-password')
    @method_decorator(csrf_protect)
    def change_password(self, request):
        """Handle password change functionality with enhanced security"""
        
        base_domain = request.build_absolute_uri('/')
        
        user = request.user
        
        # Simple rate limiting using cache (no external packages needed)
        cache_key = f'password_change_attempts_{user.id}'
        attempt_count = cache.get(cache_key, 0)
        
        # Allow 5 attempts per hour
        if attempt_count >= 5:
            messages.error(request, _("Too many password change attempts. Please try again after 1 hour."))
            return redirect(f'{base_domain}profile/')
        
        current_password = request.POST.get('current_password')
        new_password = request.POST.get('new_password')
        confirm_password = request.POST.get('confirm_password')
        
        # Prevent password reuse
        if current_password and new_password and user.check_password(new_password):
            messages.error(request, _("New password cannot be the same as your current password."))
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # Validate current password
        if not current_password:
            messages.error(request, _("Please enter your current password."))
            # Increment attempt counter on failure
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
            
        if not user.check_password(current_password):
            # Log failed attempt (for security monitoring)
            import logging
            logger = logging.getLogger(__name__)
            logger.warning(f"Failed password change attempt for user {user.username} from IP {request.META.get('REMOTE_ADDR')}")
            
            messages.error(request, _("Current password is incorrect."))
            # Increment attempt counter on failure
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # Validate new password and confirmation
        if not new_password or not confirm_password:
            messages.error(request, _("Please enter both new password and confirmation."))
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        if new_password != confirm_password:
            messages.error(request, _("New password and confirmation do not match."))
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # Check password length
        if len(new_password) < 8:
            messages.error(request, _("Password must be at least 8 characters long."))
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # Validate password strength
        try:
            validate_password(new_password, user=user)
        except ValidationError as e:
            for error in e.messages:
                messages.error(request, error)
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # Check if password contains personal info
        password_lower = new_password.lower()
        if (user.email and user.email.split('@')[0].lower() in password_lower) or \
           (user.username and user.username.lower() in password_lower):
            messages.error(request, _("Password cannot contain your email or username."))
            cache.set(cache_key, attempt_count + 1, 3600)
            return redirect(f'{base_domain}profile/')
        
        # All validations passed - reset attempt counter
        cache.delete(cache_key)
        
        # Set new password
        user.set_password(new_password)
        user.save()
        
        # Update session to prevent logout
        update_session_auth_hash(request, user)
        
        # Log successful password change
        import logging
        logger = logging.getLogger(__name__)
        logger.info(f"Password changed successfully for user {user.username}")
        
        messages.success(request, _("Your password has been successfully changed."))
        return redirect(f'{base_domain}profile/')