from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.db.models import Q
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response

from .authentication import issue_token
from .models import ContentItem, CourseAccess
from .serializers import ContentItemSerializer, UserSerializer


def auth_response(user):
    return {'user': UserSerializer(user).data, 'token': issue_token(user)}


def admin_required(request):
    return request.user.is_authenticated and request.user.is_staff


@api_view(['POST'])
@permission_classes([AllowAny])
def register(request):
    email = str(request.data.get('email', '')).strip().lower()
    password = request.data.get('password', '')
    if not email or not password:
        return Response({'error': 'Email and password are required.'}, status=status.HTTP_400_BAD_REQUEST)
    if User.objects.filter(username=email).exists():
        return Response({'error': 'User already exists.'}, status=status.HTTP_409_CONFLICT)
    user = User.objects.create_user(username=email, email=email, password=password)
    return Response(auth_response(user), status=status.HTTP_201_CREATED)


@api_view(['POST'])
@permission_classes([AllowAny])
def login(request):
    email = str(request.data.get('email', '')).strip().lower()
    user = authenticate(username=email, password=request.data.get('password', ''))
    if not user or not user.is_active:
        return Response({'error': 'Invalid email or password.'}, status=status.HTTP_401_UNAUTHORIZED)
    return Response(auth_response(user))


@api_view(['GET'])
@permission_classes([AllowAny])
def content_list(request):
    courses = ContentItem.objects.prefetch_related('questions').order_by('-created_at')
    return Response({'courses': ContentItemSerializer(courses, many=True, context={'request': request}).data, 'standaloneQuestions': []})


@api_view(['GET'])
@permission_classes([AllowAny])
def content_search(request):
    query = str(request.query_params.get('q', '')).strip()
    questions = ContentItem.objects.filter(Q(title__icontains=query) | Q(description__icontains=query))
    return Response(ContentItemSerializer(questions, many=True, context={'request': request}).data)


@api_view(['GET'])
@permission_classes([AllowAny])
def content_item(request, item_id):
    try:
        item = ContentItem.objects.prefetch_related('questions').get(id=item_id)
    except ContentItem.DoesNotExist:
        return Response({'error': 'Content not found.'}, status=status.HTTP_404_NOT_FOUND)
    return Response(ContentItemSerializer(item, context={'request': request}).data)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def unlock_course(request, item_id):
    try:
        item = ContentItem.objects.get(id=item_id)
    except ContentItem.DoesNotExist:
        return Response({'error': 'Content not found.'}, status=status.HTTP_404_NOT_FOUND)
    if item.passkey and request.data.get('passkey') != item.passkey:
        return Response({'error': 'Invalid passkey.'}, status=status.HTTP_403_FORBIDDEN)
    CourseAccess.objects.get_or_create(user=request.user, course=item, defaults={'granted_by_admin': False})
    return Response({'success': True, 'message': 'Content unlocked.'})


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_content(request):
    if not admin_required(request): return Response({'error': 'Admin access required.'}, status=403)
    item = ContentItem.objects.create(
        title=request.data.get('title', ''), description=request.data.get('description', ''),
        cover_image=request.data.get('coverImage') or None, price=float(request.data.get('price') or 0),
        passkey=request.data.get('passkey') or None, category=request.data.get('category'),
        instructor=request.data.get('instructor'), level=request.data.get('level'))
    for section in request.data.get('sections', []):
        for question in section.get('questions', []):
            Question.objects.create(content_item=item, question_text=question.get('questionText', ''), answer_text=question.get('answerText', ''), is_locked=question.get('isLocked', False), difficulty=question.get('difficulty'), points=question.get('points') or 1)
    return Response(ContentItemSerializer(item, context={'request': request}).data, status=201)


@api_view(['PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def update_content(request, item_id):
    if not admin_required(request): return Response({'error': 'Admin access required.'}, status=403)
    if request.method == 'DELETE':
        deleted, _ = ContentItem.objects.filter(id=item_id).delete()
        return Response({'success': bool(deleted)})
    try: item = ContentItem.objects.get(id=item_id)
    except ContentItem.DoesNotExist: return Response({'error': 'Course not found.'}, status=404)
    for field, key in [('title', 'title'), ('description', 'description'), ('category', 'category'), ('instructor', 'instructor'), ('level', 'level'), ('passkey', 'passkey')]:
        if key in request.data: setattr(item, field, request.data[key])
    if 'price' in request.data: item.price = float(request.data['price'] or 0)
    if 'coverImage' in request.data: item.cover_image = request.data['coverImage'] or None
    item.save()
    return Response(ContentItemSerializer(item, context={'request': request}).data)




@api_view(['POST'])
@permission_classes([IsAuthenticated])
def grant_course_access(request, item_id):
    if not request.user.is_staff:
        return Response({'error': 'Admin access required.'}, status=status.HTTP_403_FORBIDDEN)
    try:
        item = ContentItem.objects.get(id=item_id)
        student = User.objects.get(id=request.data.get('userId'), is_active=True)
    except (ContentItem.DoesNotExist, User.DoesNotExist):
        return Response({'error': 'Course or student not found.'}, status=status.HTTP_404_NOT_FOUND)
    CourseAccess.objects.update_or_create(user=student, course=item, defaults={'granted_by_admin': True})
    return Response({'success': True, 'message': f'Access granted to {student.email}.'})
