"""
Base ViewSet with account filtering support
"""
from rest_framework import viewsets
from rest_framework.response import Response
from django.core.exceptions import PermissionDenied


class AccountModelViewSet(viewsets.ModelViewSet):
    """
    Base ViewSet that automatically filters by account.
    All module ViewSets should inherit from this.
    """
    def get_queryset(self):
        queryset = super().get_queryset()
        # Filter by account if model has account field
        if hasattr(queryset.model, 'account'):
            user = getattr(self.request, 'user', None)
            
            # ADMIN/DEV/SYSTEM ACCOUNT OVERRIDE: Skip account filtering for:
            # - Admins and developers (by role)
            # - Users in system accounts (aws-admin, default-account)
            if user and hasattr(user, 'is_authenticated') and user.is_authenticated:
                try:
                    # Check if user has admin/developer privileges
                    is_admin_or_dev = (hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer()) if user else False
                    is_system_user = (hasattr(user, 'is_system_account_user') and user.is_system_account_user()) if user else False
                    
                    if is_admin_or_dev or is_system_user:
                        # Skip account filtering - allow all accounts
                        pass
                    else:
                        # Get account from request (set by middleware)
                        account = getattr(self.request, 'account', None)
                        if account:
                            queryset = queryset.filter(account=account)
                        elif hasattr(self.request, 'user') and self.request.user and hasattr(self.request.user, 'is_authenticated') and self.request.user.is_authenticated:
                            # Fallback to user's account
                            try:
                                user_account = getattr(self.request.user, 'account', None)
                                if user_account:
                                    queryset = queryset.filter(account=user_account)
                            except (AttributeError, Exception):
                                # If account access fails (e.g., column mismatch), skip account filtering
                                pass
                except (AttributeError, TypeError) as e:
                    # If there's an error accessing user attributes, return empty queryset
                    return queryset.none()
            else:
                # Require authentication - return empty queryset for unauthenticated users
                return queryset.none()
        return queryset

    def perform_create(self, serializer):
        # Set account from request (set by middleware)
        account = getattr(self.request, 'account', None)
        if not account and hasattr(self.request, 'user') and self.request.user and self.request.user.is_authenticated:
            try:
                account = getattr(self.request.user, 'account', None)
            except (AttributeError, Exception):
                # If account access fails (e.g., column mismatch), set to None
                account = None
        
        # If model has account field, set it
        if account and hasattr(serializer.Meta.model, 'account'):
            serializer.save(account=account)
        else:
            serializer.save()

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # Add account to context for serializers
        account = getattr(self.request, 'account', None)
        if account:
            context['account'] = account
        return context


class SiteSectorModelViewSet(AccountModelViewSet):
    """
    Base ViewSet for models that belong to Site and Sector (Keywords, Clusters, etc.).
    Automatically filters by:
    1. Account (via parent class)
    2. User's accessible sites (based on role and SiteUserAccess)
    3. Optional site/sector query parameters
    """
    def get_queryset(self):
        queryset = super().get_queryset()
        
        # Check if model has site and sector fields (SiteSectorBaseModel)
        if hasattr(queryset.model, 'site') and hasattr(queryset.model, 'sector'):
            user = getattr(self.request, 'user', None)
            
            # Check if user is authenticated and is a proper User instance (not AnonymousUser)
            if user and hasattr(user, 'is_authenticated') and user.is_authenticated and hasattr(user, 'get_accessible_sites'):
                try:
                    # ADMIN/DEV/SYSTEM ACCOUNT OVERRIDE: Developers, admins, and system account users 
                    # can see all data regardless of site/sector
                    if (hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer()) or \
                       (hasattr(user, 'is_system_account_user') and user.is_system_account_user()):
                        # Skip site/sector filtering for admins, developers, and system account users
                        # But still respect optional query params if provided
                        pass
                    else:
                        # Get user's accessible sites
                        accessible_sites = user.get_accessible_sites()
                        
                        # If no accessible sites, return empty queryset (unless admin/developer/system account)
                        if not accessible_sites.exists():
                            queryset = queryset.none()
                        else:
                            # Filter by accessible sites
                            queryset = queryset.filter(site__in=accessible_sites)
                except (AttributeError, TypeError) as e:
                    # If there's an error accessing user attributes, return empty queryset
                    queryset = queryset.none()
            else:
                # Require authentication - return empty queryset for unauthenticated users
                queryset = queryset.none()
            
            # Optional: Filter by specific site (from query params)
            # Safely access query_params (DRF wraps request with Request class)
            try:
                query_params = getattr(self.request, 'query_params', None)
                if query_params is None:
                    # Fallback for non-DRF requests
                    query_params = getattr(self.request, 'GET', {})
                    site_id = query_params.get('site_id')
                else:
                    site_id = query_params.get('site_id')
            except AttributeError:
                site_id = None
            
            if site_id:
                try:
                    # Convert site_id to int if it's a string
                    site_id_int = int(site_id) if site_id else None
                    if site_id_int:
                        # ADMIN/DEV/SYSTEM ACCOUNT OVERRIDE: Admins, developers, and system account users 
                        # can filter by any site, others must verify access
                        if user and hasattr(user, 'is_authenticated') and user.is_authenticated and hasattr(user, 'get_accessible_sites'):
                            try:
                                if (hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer()) or \
                                   (hasattr(user, 'is_system_account_user') and user.is_system_account_user()):
                                    # Admin/Developer/System Account User can filter by any site
                                    queryset = queryset.filter(site_id=site_id_int)
                                else:
                                    accessible_sites = user.get_accessible_sites()
                                    if accessible_sites.filter(id=site_id_int).exists():
                                        queryset = queryset.filter(site_id=site_id_int)
                                    else:
                                        queryset = queryset.none()  # Site not accessible
                            except (AttributeError, TypeError) as e:
                                # If there's an error accessing user attributes, return empty queryset
                                queryset = queryset.none()
                        else:
                            # Require authentication for site filtering
                            queryset = queryset.none()
                except (ValueError, TypeError):
                    # Invalid site_id, return empty queryset
                    queryset = queryset.none()
            
            # Optional: Filter by specific sector (from query params)
            # Safely access query_params (DRF wraps request with Request class)
            try:
                query_params = getattr(self.request, 'query_params', None)
                if query_params is None:
                    # Fallback for non-DRF requests
                    query_params = getattr(self.request, 'GET', {})
                    sector_id = query_params.get('sector_id')
                else:
                    sector_id = query_params.get('sector_id')
            except AttributeError:
                sector_id = None
            
            if sector_id:
                try:
                    # Convert sector_id to int if it's a string
                    sector_id_int = int(sector_id) if sector_id else None
                    if sector_id_int:
                        queryset = queryset.filter(sector_id=sector_id_int)
                        # If site_id also provided, ensure sector belongs to that site
                        if site_id:
                            try:
                                site_id_int = int(site_id) if site_id else None
                                if site_id_int:
                                    queryset = queryset.filter(site_id=site_id_int)
                            except (ValueError, TypeError):
                                pass
                except (ValueError, TypeError):
                    # Invalid sector_id, return empty queryset
                    queryset = queryset.none()
            
            # Always exclude records where site is null (orphaned records)
            # This prevents showing keywords/clusters/ideas/tasks that aren't associated with any site
            # Only skip this if explicitly requested (e.g., for admin cleanup operations)
            queryset = queryset.exclude(site__isnull=True)
        
        return queryset
    
    def perform_create(self, serializer):
        # First call parent to set account
        super().perform_create(serializer)
        
        # If model has site and sector fields, validate access
        if hasattr(serializer.Meta.model, 'site') and hasattr(serializer.Meta.model, 'sector'):
            user = getattr(self.request, 'user', None)
            site = serializer.validated_data.get('site')
            sector = serializer.validated_data.get('sector')
            
            if user and hasattr(user, 'is_authenticated') and user.is_authenticated and site:
                try:
                    # ADMIN/DEV/SYSTEM ACCOUNT OVERRIDE: Admins, developers, and system account users 
                    # can create in any site, others must verify access
                    if not ((hasattr(user, 'is_admin_or_developer') and user.is_admin_or_developer()) or 
                            (hasattr(user, 'is_system_account_user') and user.is_system_account_user())):
                        if hasattr(user, 'get_accessible_sites'):
                            accessible_sites = user.get_accessible_sites()
                            if not accessible_sites.filter(id=site.id).exists():
                                raise PermissionDenied("You do not have access to this site")
                    
                    # Verify sector belongs to site
                    if sector and hasattr(sector, 'site') and sector.site != site:
                        raise PermissionDenied("Sector must belong to the selected site")
                except (AttributeError, TypeError) as e:
                    # If there's an error accessing user attributes, raise permission denied
                    raise PermissionDenied("Unable to verify access permissions")
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        user = getattr(self.request, 'user', None)
        
        # Add accessible sites to context for serializer (e.g., for dropdown choices)
        if user and hasattr(user, 'is_authenticated') and user.is_authenticated and hasattr(user, 'get_accessible_sites'):
            try:
                context['accessible_sites'] = user.get_accessible_sites()
                # Get accessible sectors from accessible sites
                from igny8_core.auth.models import Sector
                context['accessible_sectors'] = Sector.objects.filter(
                    site__in=context['accessible_sites'],
                    is_active=True
                )
            except (AttributeError, TypeError):
                # If there's an error, set empty querysets
                from igny8_core.auth.models import Site, Sector
                context['accessible_sites'] = Site.objects.none()
                context['accessible_sectors'] = Sector.objects.none()
        else:
            # Set empty querysets for unauthenticated users
            from igny8_core.auth.models import Site, Sector
            context['accessible_sites'] = Site.objects.none()
            context['accessible_sectors'] = Sector.objects.none()
        
        return context


class StandardResponseMixin:
    """
    Mixin for standard API response format.
    """
    def get_response(self, data, message=None, status_code=200):
        return Response({
            'success': True,
            'message': message,
            'data': data
        }, status=status_code)

    def get_error_response(self, message, errors=None, status_code=400):
        return Response({
            'success': False,
            'message': message,
            'errors': errors
        }, status=status_code)

