from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.contenttypes.models import ContentType
from django.http import JsonResponse, HttpResponseForbidden
from django.core.exceptions import PermissionDenied
from django.utils import timezone
import json
from .models import EditSubmission, PhotoSubmission

class EditSubmissionMixin:
    """
    Mixin for handling edit submissions with proper moderation.
    """
    def handle_edit_submission(self, request, changes, reason='', source='', submission_type='EDIT'):
        """
        Handle an edit submission based on user's role.
        
        Args:
            request: The HTTP request
            changes: Dict of field changes {field_name: new_value}
            reason: Why this edit is needed
            source: Source of information (optional)
            submission_type: 'EDIT' or 'CREATE'
            
        Returns:
            JsonResponse with status and message
        """
        if not request.user.is_authenticated:
            return JsonResponse({
                'status': 'error',
                'message': 'You must be logged in to make edits.'
            }, status=403)

        content_type = ContentType.objects.get_for_model(self.model)

        # Create the submission
        submission = EditSubmission(
            user=request.user,
            content_type=content_type,
            submission_type=submission_type,
            changes=changes,
            reason=reason,
            source=source
        )

        # For edits, set the object_id
        if submission_type == 'EDIT':
            obj = self.get_object()
            submission.object_id = obj.id

        # Auto-approve for moderators and above
        if request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
            obj = submission.auto_approve()
            return JsonResponse({
                'status': 'success',
                'message': 'Changes saved successfully.',
                'auto_approved': True,
                'redirect_url': obj.get_absolute_url() if hasattr(obj, 'get_absolute_url') else None
            })

        # Submit for approval for regular users
        submission.save()
        return JsonResponse({
            'status': 'success',
            'message': 'Your changes have been submitted for approval.',
            'auto_approved': False
        })

    def post(self, request, *args, **kwargs):
        """Handle POST requests for editing"""
        if not request.user.is_authenticated:
            return JsonResponse({
                'status': 'error',
                'message': 'You must be logged in to make edits.'
            }, status=403)

        try:
            data = json.loads(request.body)
            changes = data.get('changes', {})
            reason = data.get('reason', '')
            source = data.get('source', '')
            submission_type = data.get('submission_type', 'EDIT')

            if not changes:
                return JsonResponse({
                    'status': 'error',
                    'message': 'No changes provided.'
                }, status=400)

            if not reason and request.user.role == 'USER':
                return JsonResponse({
                    'status': 'error',
                    'message': 'Please provide a reason for your changes.'
                }, status=400)

            return self.handle_edit_submission(
                request, changes, reason, source, submission_type
            )

        except json.JSONDecodeError:
            return JsonResponse({
                'status': 'error',
                'message': 'Invalid JSON data.'
            }, status=400)
        except Exception as e:
            return JsonResponse({
                'status': 'error',
                'message': str(e)
            }, status=500)

class PhotoSubmissionMixin:
    """
    Mixin for handling photo submissions with proper moderation.
    """
    def handle_photo_submission(self, request):
        """Handle a photo submission based on user's role"""
        if not request.user.is_authenticated:
            return JsonResponse({
                'status': 'error',
                'message': 'You must be logged in to upload photos.'
            }, status=403)

        if not request.FILES.get('photo'):
            return JsonResponse({
                'status': 'error',
                'message': 'No photo provided.'
            }, status=400)

        obj = self.get_object()
        content_type = ContentType.objects.get_for_model(obj)

        submission = PhotoSubmission(
            user=request.user,
            content_type=content_type,
            object_id=obj.id,
            photo=request.FILES['photo'],
            caption=request.POST.get('caption', ''),
            date_taken=request.POST.get('date_taken')
        )

        # Auto-approve for moderators and above
        if request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
            submission.auto_approve()
            return JsonResponse({
                'status': 'success',
                'message': 'Photo uploaded successfully.',
                'auto_approved': True
            })

        # Submit for approval for regular users
        submission.save()
        return JsonResponse({
            'status': 'success',
            'message': 'Your photo has been submitted for approval.',
            'auto_approved': False
        })

class ModeratorRequiredMixin(UserPassesTestMixin):
    """Require moderator or higher role for access"""
    def test_func(self):
        return (
            self.request.user.is_authenticated and 
            self.request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']
        )

    def handle_no_permission(self):
        if not self.request.user.is_authenticated:
            return super().handle_no_permission()
        return HttpResponseForbidden("You must be a moderator to access this page.")

class AdminRequiredMixin(UserPassesTestMixin):
    """Require admin or superuser role for access"""
    def test_func(self):
        return (
            self.request.user.is_authenticated and 
            self.request.user.role in ['ADMIN', 'SUPERUSER']
        )

    def handle_no_permission(self):
        if not self.request.user.is_authenticated:
            return super().handle_no_permission()
        return HttpResponseForbidden("You must be an admin to access this page.")

class InlineEditMixin:
    """Add inline editing context to views"""
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.user.is_authenticated:
            context['can_edit'] = True
            context['can_auto_approve'] = self.request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']
            if hasattr(self, 'get_object'):
                obj = self.get_object()
                context['pending_edits'] = EditSubmission.objects.filter(
                    content_type=ContentType.objects.get_for_model(obj),
                    object_id=obj.id,
                    status='PENDING'
                ).select_related('user').order_by('-submitted_at')
        return context

class HistoryMixin:
    """Add edit history context to views"""
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        obj = self.get_object()
        
        # Get historical records
        context['history'] = obj.history.all().select_related('history_user')
        
        # Get related edit submissions
        content_type = ContentType.objects.get_for_model(obj)
        context['edit_submissions'] = EditSubmission.objects.filter(
            content_type=content_type,
            object_id=obj.id
        ).exclude(
            status='PENDING'
        ).select_related('user', 'reviewed_by').order_by('-submitted_at')
        
        return context
