"""
Permission Views — API endpoints for role/permission management.
"""
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, permissions, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView

from .models import (
    Permission, Role, RolePermission, UserRole,
    UserPermission, ObjectRelation, RAICPolicy,
)
from .serializers import (
    PermissionSerializer,
    RoleListSerializer, RoleDetailSerializer, RoleCreateUpdateSerializer,
    RolePermissionAssignSerializer,
    UserRoleSerializer,
    UserPermissionSerializer,
    ObjectRelationSerializer,
    RAICPolicySerializer,
    MyPermissionsSerializer,
)
from .services import PermissionService


# ─── Permission ViewSet (Read-only) ─────────────────────────


class PermissionViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Permission list — read-only.
    
    Supports grouping by module.
    """
    queryset = Permission.objects.all()
    serializer_class = PermissionSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = None  # always return all permissions (for matrix/dropdown)
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['module', 'resource', 'action', 'is_sensitive']
    search_fields = ['codename', 'name', 'description']
    ordering_fields = ['module', 'resource', 'codename']
    ordering = ['module', 'resource', 'codename']
    
    @action(detail=False, methods=['get'], url_path='grouped')
    def grouped(self, request):
        """Permissions grouped by module → resource (with Persian labels)."""
        from apps.core.permission.management.commands.seed_permissions import (
            MODULE_LABELS, RESOURCE_LABELS, ACTION_LABELS,
        )

        perms = Permission.objects.all().order_by('module', 'resource', 'codename')
        
        grouped = {}
        for perm in perms:
            if perm.module not in grouped:
                grouped[perm.module] = {}
            if perm.resource not in grouped[perm.module]:
                grouped[perm.module][perm.resource] = []
            grouped[perm.module][perm.resource].append(
                PermissionSerializer(perm).data
            )
        
        result = []
        for module, resources in grouped.items():
            result.append({
                'module': module,
                'module_label': MODULE_LABELS.get(module, module),
                'resources': [
                    {
                        'resource': res,
                        'resource_label': RESOURCE_LABELS.get(res, res),
                        'permissions': perms_list,
                    }
                    for res, perms_list in resources.items()
                ]
            })
        
        return Response({'data': result})


# ─── Role ViewSet ────────────────────────────────────────────


class RoleViewSet(viewsets.ModelViewSet):
    """
    Role CRUD + permission assignment.
    """
    queryset = Role.objects.all().select_related('parent')
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['is_system', 'is_active', 'module']
    search_fields = ['name', 'slug', 'description']
    ordering_fields = ['name', 'created_at']
    ordering = ['name']
    
    def get_serializer_class(self):
        if self.action in ('list',):
            return RoleListSerializer
        if self.action in ('create', 'update', 'partial_update'):
            return RoleCreateUpdateSerializer
        return RoleDetailSerializer
    
    def get_queryset(self):
        qs = super().get_queryset()
        # Tenant filtering
        tenant = getattr(self.request, 'tenant', None)
        if tenant:
            qs = qs.filter(tenant=tenant)
        return qs
    
    def perform_create(self, serializer):
        tenant = getattr(self.request, 'tenant', None)
        serializer.save(tenant=tenant)
    
    def perform_destroy(self, instance):
        if instance.is_system:
            from rest_framework.exceptions import ValidationError
            raise ValidationError({"detail": "System roles cannot be deleted."})
        instance.delete()
    
    @action(detail=True, methods=['post'], url_path='assign-permissions')
    def assign_permissions(self, request, pk=None):
        """Assign permissions to a role."""
        role = self.get_object()
        serializer = RolePermissionAssignSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        permission_ids = serializer.validated_data['permission_ids']
        constraints = serializer.validated_data.get('constraints', {})
        
        created = []
        for perm_id in permission_ids:
            rp, was_created = RolePermission.objects.get_or_create(
                role=role,
                permission_id=perm_id,
                defaults={'constraints': constraints},
            )
            if was_created:
                created.append(perm_id)
        
        # Invalidate caches for all users with this role
        PermissionService.clear_all_caches()
        
        return Response({
            'data': {'assigned': len(created), 'total_requested': len(permission_ids)}
        })
    
    @action(detail=True, methods=['post'], url_path='remove-permissions')
    def remove_permissions(self, request, pk=None):
        """Remove permissions from a role."""
        role = self.get_object()
        serializer = RolePermissionAssignSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        permission_ids = serializer.validated_data['permission_ids']
        deleted, _ = RolePermission.objects.filter(
            role=role,
            permission_id__in=permission_ids,
        ).delete()
        
        PermissionService.clear_all_caches()
        
        return Response({
            'data': {'removed': deleted, 'total_requested': len(permission_ids)}
        })
    
    @action(detail=True, methods=['get'], url_path='users')
    def users(self, request, pk=None):
        """List users assigned to this role."""
        role = self.get_object()
        user_roles = UserRole.objects.filter(role=role).select_related(
            'user', 'organizational_unit'
        )
        serializer = UserRoleSerializer(user_roles, many=True)
        return Response({'data': serializer.data})


# ─── UserRole ViewSet ────────────────────────────────────────


class UserRoleViewSet(viewsets.ModelViewSet):
    """
    User role assignment CRUD.
    """
    queryset = UserRole.objects.all().select_related(
        'user', 'role', 'organizational_unit', 'assigned_by'
    )
    serializer_class = UserRoleSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['user', 'role', 'organizational_unit']
    search_fields = ['user__email', 'user__first_name', 'role__name']
    
    def perform_create(self, serializer):
        serializer.save(assigned_by=self.request.user)
        PermissionService.clear_all_caches()
    
    def perform_destroy(self, instance):
        instance.delete()
        PermissionService.clear_all_caches()


# ─── UserPermission ViewSet ──────────────────────────────────


class UserPermissionViewSet(viewsets.ModelViewSet):
    """
    User permission override CRUD (Explicit Allow/Deny).
    """
    queryset = UserPermission.objects.all().select_related(
        'user', 'permission', 'granted_by'
    )
    serializer_class = UserPermissionSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['user', 'permission', 'allow']
    search_fields = ['user__email', 'permission__codename', 'reason']
    
    def perform_create(self, serializer):
        serializer.save()
        PermissionService.clear_all_caches()
    
    def perform_destroy(self, instance):
        instance.delete()
        PermissionService.clear_all_caches()

    @action(detail=False, methods=['post'], url_path='bulk-create')
    def bulk_create(self, request):
        """
        Create multiple user-permission overrides at once.

        Payload: {
            "user": "<user-uuid>",
            "permission_ids": [1, 2, 3],
            "allow": true,
            "reason": "...",
            "starts_at": null,
            "expires_at": null
        }
        """
        user_id = request.data.get('user')
        permission_ids = request.data.get('permission_ids', [])
        allow = request.data.get('allow', True)
        reason = request.data.get('reason', '')
        starts_at = request.data.get('starts_at')
        expires_at = request.data.get('expires_at')

        if not user_id or not permission_ids:
            return Response(
                {'error': {'code': 'validation', 'message': 'user و permission_ids الزامی هستند'}},
                status=status.HTTP_400_BAD_REQUEST,
            )

        from apps.core.auth.models import User
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return Response(
                {'error': {'code': 'not_found', 'message': 'کاربر یافت نشد'}},
                status=status.HTTP_404_NOT_FOUND,
            )

        perms = Permission.objects.filter(id__in=permission_ids)
        created_count = 0
        for perm in perms:
            _, was_created = UserPermission.objects.update_or_create(
                user=user,
                permission=perm,
                defaults={
                    'allow': allow,
                    'reason': reason,
                    'granted_by': request.user,
                    'starts_at': starts_at,
                    'expires_at': expires_at,
                },
            )
            if was_created:
                created_count += 1

        PermissionService.clear_all_caches()
        return Response({
            'data': {
                'created': created_count,
                'updated': len(perms) - created_count,
                'total': len(perms),
            }
        }, status=status.HTTP_201_CREATED)


# ─── ObjectRelation ViewSet ──────────────────────────────────


class ObjectRelationViewSet(viewsets.ModelViewSet):
    """
    RAIC object relations CRUD.
    """
    queryset = ObjectRelation.objects.all().select_related('user')
    serializer_class = ObjectRelationSerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['object_type', 'object_id', 'user', 'relation_type', 'module']
    search_fields = ['user__email', 'object_type']


# ─── RAICPolicy ViewSet ──────────────────────────────────────


class RAICPolicyViewSet(viewsets.ModelViewSet):
    """
    RAIC policy CRUD — defines what relations grant what permissions.
    """
    queryset = RAICPolicy.objects.all().select_related('permission')
    serializer_class = RAICPolicySerializer
    permission_classes = [permissions.IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['module', 'object_type', 'relation_type', 'is_active']


# ─── My Permissions (current user) ──────────────────────────


class MyPermissionsView(APIView):
    """
    GET /api/v1/permissions/me/ — get current user's permissions and roles.
    
    Returns all permission codenames and role info.
    Used by frontend to build the permission store.
    """
    permission_classes = [permissions.IsAuthenticated]
    
    def get(self, request):
        user = request.user
        
        # Get all permissions
        perms = list(PermissionService.get_user_permissions(user))
        
        # Get roles
        roles = PermissionService.get_user_roles(user)
        roles_data = [
            {
                'id': role.id,
                'name': role.name,
                'slug': role.slug,
                'module': role.module,
                'is_system': role.is_system,
            }
            for role in roles
        ]
        
        return Response({
            'data': {
                'permissions': sorted(perms),
                'roles': roles_data,
                'is_superuser': user.is_superuser,
            }
        })
