from rest_framework import viewsets, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.response import Response
from django.contrib.auth.models import User, Group, Permission
from django.shortcuts import get_object_or_404
from rest_framework.serializers import ModelSerializer, SerializerMethodField


class PermissionSerializer(ModelSerializer):
    content_type = SerializerMethodField()

    class Meta:
        model = Permission
        fields = ['id', 'codename', 'content_type', 'name']

    def get_content_type(self, obj):
        return {
            'app_label': obj.content_type.app_label,
            'model': obj.content_type.model,
        }


class GroupSerializer(ModelSerializer):
    permissions = PermissionSerializer(many=True, read_only=True)
    user_count = SerializerMethodField()

    class Meta:
        model = Group
        fields = ['id', 'name', 'permissions', 'user_count']

    def get_user_count(self, obj):
        return obj.user_set.count()


class UserPermissionSerializer(ModelSerializer):
    user_permissions = PermissionSerializer(many=True, read_only=True)
    groups = GroupSerializer(many=True, read_only=True)

    class Meta:
        model = User
        fields = [
            'id',
            'username',
            'email',
            'first_name',
            'last_name',
            'is_staff',
            'is_superuser',
            'is_active',
            'date_joined',
            'user_permissions',
            'groups',
        ]


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_users_list(request):
    """
    Get all users with their permissions and groups.
    Only accessible to admins.
    """
    users = User.objects.prefetch_related('groups', 'user_permissions').all()
    serializer = UserPermissionSerializer(users, many=True)
    return Response(serializer.data)


@api_view(['GET', 'PUT'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_user_detail(request, user_id):
    """
    Get or update a user's groups and permissions.
    """
    user = get_object_or_404(User, id=user_id)

    if request.method == 'GET':
        serializer = UserPermissionSerializer(user)
        return Response(serializer.data)

    elif request.method == 'PUT':
        # Update groups
        group_ids = request.data.get('groups', [])
        groups = Group.objects.filter(id__in=group_ids)
        user.groups.set(groups)

        # Update direct permissions (optional)
        perm_ids = request.data.get('permissions', [])
        if perm_ids:
            permissions = Permission.objects.filter(id__in=perm_ids)
            user.user_permissions.set(permissions)

        serializer = UserPermissionSerializer(user)
        return Response(serializer.data)


@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_groups_list(request):
    """
    Get all groups with their permissions (GET) or create a new group (POST).
    """
    if request.method == 'GET':
        groups = Group.objects.prefetch_related('permissions').all()
        serializer = GroupSerializer(groups, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        name = request.data.get('name')

        if not name:
            return Response(
                {'error': 'Group name is required'},
                status=status.HTTP_400_BAD_REQUEST
            )

        # Check if group already exists
        if Group.objects.filter(name=name).exists():
            return Response(
                {'error': 'Group with this name already exists'},
                status=status.HTTP_400_BAD_REQUEST
            )

        group = Group.objects.create(name=name)

        # Add permissions
        perm_ids = request.data.get('permissions', [])
        if perm_ids:
            permissions = Permission.objects.filter(id__in=perm_ids)
            group.permissions.set(permissions)

        serializer = GroupSerializer(group)
        return Response(serializer.data, status=status.HTTP_201_CREATED)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_group_detail(request, group_id):
    """
    Get, update, or delete a group.
    """
    group = get_object_or_404(Group, id=group_id)

    if request.method == 'GET':
        serializer = GroupSerializer(group)
        return Response(serializer.data)

    elif request.method == 'PUT':
        # Update name
        group.name = request.data.get('name', group.name)
        group.save()

        # Update permissions
        perm_ids = request.data.get('permissions', [])
        permissions = Permission.objects.filter(id__in=perm_ids)
        group.permissions.set(permissions)

        serializer = GroupSerializer(group)
        return Response(serializer.data)

    elif request.method == 'DELETE':
        group.delete()
        return Response({'message': 'Group deleted successfully'})


@api_view(['GET'])
@permission_classes([IsAuthenticated, IsAdminUser])
def admin_permissions_list(request):
    """
    Get all available permissions grouped by app.
    Useful for permission assignment UI.
    """
    permissions = Permission.objects.select_related(
        'content_type'
    ).all().order_by('content_type__app_label', 'codename')

    serializer = PermissionSerializer(permissions, many=True)
    return Response(serializer.data)
