from rest_framework.decorators import api_view, permission_classes
from django.views.decorators.csrf import csrf_exempt
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework import status
from rest_framework.authtoken.models import Token
from django.shortcuts import get_object_or_404
from django.core.paginator import Paginator
import logging
import traceback

from .models import Module, Permission, Role, RolePermission, User
from .serializers import (
    ModuleSerializer, PermissionSerializer, RoleSerializer, RoleDetailSerializer,
    RolePermissionSerializer, UserSerializer, UserCreateUpdateSerializer, UserDetailSerializer,
    LoginSerializer, LogoutSerializer, AuthUserSerializer
)

logger = logging.getLogger(__name__)


# ==================== HELPER FUNCTIONS ====================

def check_is_admin(user):
    """Check if user is admin (staff or superuser)"""
    return user.is_staff or user.is_superuser


def check_is_superuser(user):
    """Check if user is superuser"""
    return user.is_superuser


def paginate_results(queryset, page_number=1, page_size=20):
    """Helper function to paginate queryset"""
    paginator = Paginator(queryset, page_size)
    page_obj = paginator.get_page(page_number)
    return page_obj.object_list, {
        'total': paginator.count,
        'pages': paginator.num_pages,
        'current_page': page_number,
        'page_size': page_size
    }
    

@csrf_exempt
@api_view(['GET'])
@permission_classes([AllowAny])
def ping(request):
    return Response({'status': 'ok', 'message': 'Server is running'}, status=status.HTTP_200_OK)

# ==================== AUTH APIS ====================

from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken

# @api_view(['GET'])

# def login(request):
#     return "donee"
    
# # Updated login:
@csrf_exempt
@api_view(['POST'])
@permission_classes([AllowAny])
def login(request):
    try:
        serializer = LoginSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.validated_data['user']
            refresh = RefreshToken.for_user(user)
            return Response({
                'message': 'Login successful',
                'access': str(refresh.access_token),
                'refresh': str(refresh),
                'user': AuthUserSerializer(user).data
            }, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
   
    except Exception as e:
        return Response({
            "error": str(e),
            "trace": traceback.format_exc()
        }, status=500)


# Updated logout (blacklists the refresh token):
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def logout(request):
    try:
        refresh_token = request.data.get('refresh')
        if refresh_token:
            token = RefreshToken(refresh_token)
            token.blacklist()
        return Response({'message': 'Logout successful'}, status=status.HTTP_200_OK)
    except Exception as e:
        logger.error(f"Error during logout: {e}")
        return Response({'error': 'Logout failed'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_current_user(request):
    """Get current authenticated user information"""
    try:
        serializer = UserDetailSerializer(request.user)
        return Response(serializer.data, status=status.HTTP_200_OK)
    except Exception as e:
        logger.error(f"Error retrieving current user: {e}")
        return Response({'error': 'Failed to retrieve user'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def module_list_create(request):
    """
    GET: List all modules (paginated)
    POST: Create new module (admin only)
    """
    if request.method == 'GET':
        try:
            page = request.query_params.get('page', 1)
            modules = Module.objects.all().order_by('-created_at')
            modules_paginated, pagination_info = paginate_results(modules, page)
            
            serializer = ModuleSerializer(modules_paginated, many=True)
            return Response({
                'data': serializer.data,
                'pagination': pagination_info
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error listing modules: {e}")
            return Response({'error': 'Failed to retrieve modules'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'POST':
        # Check admin permission
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = ModuleSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error creating module: {e}")
            return Response({'error': 'Failed to create module'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def module_detail_update_delete(request, module_id):
    """
    GET: Retrieve single module
    PUT: Update module (admin only)
    DELETE: Delete module (admin only)
    """
    try:
        module = get_object_or_404(Module, id=module_id)
    except:
        return Response({'error': 'Module not found'}, status=status.HTTP_404_NOT_FOUND)
    
    if request.method == 'GET':
        try:
            serializer = ModuleSerializer(module)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error retrieving module: {e}")
            return Response({'error': 'Failed to retrieve module'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'PUT':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = ModuleSerializer(module, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error updating module: {e}")
            return Response({'error': 'Failed to update module'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'DELETE':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            module.delete()
            return Response({'message': 'Module deleted successfully'}, status=status.HTTP_204_NO_CONTENT)
        except Exception as e:
            logger.error(f"Error deleting module: {e}")
            return Response({'error': 'Failed to delete module'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# ==================== PERMISSION APIS ====================

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def permission_list_create(request):
    """
    GET: List all permissions (paginated)
    POST: Create new permission (admin only)
    """
    if request.method == 'GET':
        try:
            page = request.query_params.get('page', 1)
            permissions = Permission.objects.all().select_related('module').order_by('-id')
            permissions_paginated, pagination_info = paginate_results(permissions, page)
            
            serializer = PermissionSerializer(permissions_paginated, many=True)
            return Response({
                'data': serializer.data,
                'pagination': pagination_info
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error listing permissions: {e}")
            return Response({'error': 'Failed to retrieve permissions'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'POST':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = PermissionSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error creating permission: {e}")
            return Response({'error': 'Failed to create permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def permission_detail_update_delete(request, permission_id):
    """
    GET: Retrieve single permission
    PUT: Update permission (admin only)
    DELETE: Delete permission (admin only)
    """
    try:
        permission = get_object_or_404(Permission, id=permission_id)
    except:
        return Response({'error': 'Permission not found'}, status=status.HTTP_404_NOT_FOUND)
    
    if request.method == 'GET':
        try:
            serializer = PermissionSerializer(permission)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error retrieving permission: {e}")
            return Response({'error': 'Failed to retrieve permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'PUT':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = PermissionSerializer(permission, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error updating permission: {e}")
            return Response({'error': 'Failed to update permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'DELETE':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            permission.delete()
            return Response({'message': 'Permission deleted successfully'}, status=status.HTTP_204_NO_CONTENT)
        except Exception as e:
            logger.error(f"Error deleting permission: {e}")
            return Response({'error': 'Failed to delete permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# ==================== ROLE APIS ====================

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def role_list_create(request):
    """
    GET: List all roles (paginated)
    POST: Create new role (admin only)
    """
    if request.method == 'GET':
        try:
            page = request.query_params.get('page', 1)
            roles = Role.objects.all().prefetch_related('role_permissions').order_by('-created_at')
            roles_paginated, pagination_info = paginate_results(roles, page)
            
            serializer = RoleSerializer(roles_paginated, many=True)
            return Response({
                'data': serializer.data,
                'pagination': pagination_info
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error listing roles: {e}")
            return Response({'error': 'Failed to retrieve roles'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'POST':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = RoleSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error creating role: {e}")
            return Response({'error': 'Failed to create role'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def role_detail_update_delete(request, role_id):
    """
    GET: Retrieve single role with all permissions
    PUT: Update role (admin only)
    DELETE: Delete role (admin only)
    """
    try:
        role = get_object_or_404(Role, id=role_id)
    except:
        return Response({'error': 'Role not found'}, status=status.HTTP_404_NOT_FOUND)
    
    if request.method == 'GET':
        try:
            serializer = RoleDetailSerializer(role)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error retrieving role: {e}")
            return Response({'error': 'Failed to retrieve role'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'PUT':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = RoleSerializer(role, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error updating role: {e}")
            return Response({'error': 'Failed to update role'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'DELETE':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            role.delete()
            return Response({'message': 'Role deleted successfully'}, status=status.HTTP_204_NO_CONTENT)
        except Exception as e:
            logger.error(f"Error deleting role: {e}")
            return Response({'error': 'Failed to delete role'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# ==================== ROLE PERMISSION APIS ====================

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def role_permission_list_create(request):
    """
    GET: List all role-permission assignments (paginated)
    POST: Assign permission to role (admin only)
    """
    if request.method == 'GET':
        try:
            page = request.query_params.get('page', 1)
            role_perms = RolePermission.objects.all().select_related('role', 'permission', 'permission__module').order_by('-id')
            role_perms_paginated, pagination_info = paginate_results(role_perms, page)
            
            serializer = RolePermissionSerializer(role_perms_paginated, many=True)
            return Response({
                'data': serializer.data,
                'pagination': pagination_info
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error listing role permissions: {e}")
            return Response({'error': 'Failed to retrieve role permissions'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'POST':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            # Check if role and permission exist
            role_id = request.data.get('role')
            permission_id = request.data.get('permission')
            
            if not role_id or not permission_id:
                return Response({'error': 'Role ID and Permission ID are required'}, status=status.HTTP_400_BAD_REQUEST)
            
            role = get_object_or_404(Role, id=role_id)
            permission = get_object_or_404(Permission, id=permission_id)
            
            # Check if assignment already exists
            existing = RolePermission.objects.filter(role=role, permission=permission).first()
            if existing:
                return Response({'error': 'Permission already assigned to this role'}, status=status.HTTP_400_BAD_REQUEST)
            
            serializer = RolePermissionSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error assigning permission: {e}")
            return Response({'error': 'Failed to assign permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def role_permission_detail_update_delete(request, role_permission_id):
    """
    GET: Retrieve single role-permission assignment
    PUT: Update role-permission (admin only)
    DELETE: Remove permission from role (admin only)
    """
    try:
        role_permission = get_object_or_404(RolePermission, id=role_permission_id)
    except:
        return Response({'error': 'Role Permission not found'}, status=status.HTTP_404_NOT_FOUND)
    
    if request.method == 'GET':
        try:
            serializer = RolePermissionSerializer(role_permission)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error retrieving role permission: {e}")
            return Response({'error': 'Failed to retrieve role permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'PUT':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = RolePermissionSerializer(role_permission, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error updating role permission: {e}")
            return Response({'error': 'Failed to update role permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'DELETE':
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            role_permission.delete()
            return Response({'message': 'Permission removed from role'}, status=status.HTTP_204_NO_CONTENT)
        except Exception as e:
            logger.error(f"Error removing permission: {e}")
            return Response({'error': 'Failed to remove permission'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# ==================== USER APIS ====================

@api_view(['GET', 'POST'])
@permission_classes([IsAuthenticated])
def user_list_create(request):
    """
    GET: List all users (paginated, admin only)
    POST: Create new user (open to all)
    """
    if request.method == 'GET':
        # List users - admin only
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            page = request.query_params.get('page', 1)
            users = User.objects.all().select_related('role', 'manager').order_by('-created_at')
            users_paginated, pagination_info = paginate_results(users, page)
            
            serializer = UserSerializer(users_paginated, many=True)
            return Response({
                'data': serializer.data,
                'pagination': pagination_info
            }, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error listing users: {e}")
            return Response({'error': 'Failed to retrieve users'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'POST':
        # Create user - open to all (registration)
        try:
            serializer = UserCreateUpdateSerializer(data=request.data)
            if serializer.is_valid():
                user = serializer.save()
                response_serializer = UserSerializer(user)
                return Response(response_serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error creating user: {e}")
            return Response({'error': 'Failed to create user'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['GET', 'PUT', 'DELETE'])
@permission_classes([IsAuthenticated])
def user_detail_update_delete(request, user_id):
    """
    GET: Retrieve single user
    PUT: Update user (own user or admin)
    DELETE: Delete user (admin only)
    """
    try:
        user = get_object_or_404(User, id=user_id)
    except:
        return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND)
    
    if request.method == 'GET':
        try:
            # Check authorization - can view own profile or if admin
            if request.user.id != user.id and not check_is_admin(request.user):
                return Response({'error': 'Access denied'}, status=status.HTTP_403_FORBIDDEN)
            
            serializer = UserDetailSerializer(user)
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Exception as e:
            logger.error(f"Error retrieving user: {e}")
            return Response({'error': 'Failed to retrieve user'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'PUT':
        # Update user - own user or admin
        if request.user.id != user.id and not check_is_admin(request.user):
            return Response({'error': 'Access denied'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            serializer = UserCreateUpdateSerializer(user, data=request.data, partial=True)
            if serializer.is_valid():
                serializer.save()
                response_serializer = UserSerializer(user)
                return Response(response_serializer.data, status=status.HTTP_200_OK)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        except Exception as e:
            logger.error(f"Error updating user: {e}")
            return Response({'error': 'Failed to update user'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    elif request.method == 'DELETE':
        # Delete user - admin only
        if not check_is_admin(request.user):
            return Response({'error': 'Admin access required'}, status=status.HTTP_403_FORBIDDEN)
        
        try:
            # Prevent deleting own account
            if request.user.id == user.id:
                return Response({'error': 'Cannot delete your own account'}, status=status.HTTP_400_BAD_REQUEST)
            
            user.delete()
            return Response({'message': 'User deleted successfully'}, status=status.HTTP_204_NO_CONTENT)
        except Exception as e:
            logger.error(f"Error deleting user: {e}")
            return Response({'error': 'Failed to delete user'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def assign_role_to_user(request, user_id):
    """
    POST: Assign role to user (superuser only)
    """
    if not check_is_superuser(request.user):
        return Response({'error': 'Superuser access required'}, status=status.HTTP_403_FORBIDDEN)
    
    try:
        user = get_object_or_404(User, id=user_id)
        role_id = request.data.get('role_id')
        
        if not role_id:
            return Response({'error': 'role_id is required'}, status=status.HTTP_400_BAD_REQUEST)
        
        role = get_object_or_404(Role, id=role_id)
        user.role = role
        user.save()
        
        serializer = UserSerializer(user)
        return Response({
            'message': f'Role "{role.name}" assigned to user "{user.email}"',
            'data': serializer.data
        }, status=status.HTTP_200_OK)
    except Exception as e:
        logger.error(f"Error assigning role: {e}")
        return Response({'error': 'Failed to assign role'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
