"""
ViewSets for Settings Models
Unified API Standard v1.0 compliant
"""
from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django.db import transaction
from drf_spectacular.utils import extend_schema, extend_schema_view
from igny8_core.api.base import AccountModelViewSet
from igny8_core.api.response import success_response, error_response
from igny8_core.api.authentication import JWTAuthentication, CSRFExemptSessionAuthentication
from igny8_core.api.pagination import CustomPageNumberPagination
from igny8_core.api.throttles import DebugScopedRateThrottle
from igny8_core.api.permissions import IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner
from .settings_models import SystemSettings, AccountSettings, UserSettings, ModuleSettings, ModuleEnableSettings, AISettings
from .settings_serializers import (
    SystemSettingsSerializer, AccountSettingsSerializer, UserSettingsSerializer,
    ModuleSettingsSerializer, ModuleEnableSettingsSerializer, AISettingsSerializer
)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    create=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
    destroy=extend_schema(tags=['System']),
)
class SystemSettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing system-wide settings (admin only for write operations)
    Unified API Standard v1.0 compliant
    """
    queryset = SystemSettings.objects.all()
    serializer_class = SystemSettingsSerializer
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    authentication_classes = [JWTAuthentication]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_permissions(self):
        """Admin only for write operations, read for authenticated users"""
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            return [IsAdminOrOwner()]
        return [IsAuthenticatedAndActive(), HasTenantAccess()]
    
    def get_queryset(self):
        """Get all system settings"""
        return SystemSettings.objects.all().order_by('key')
    
    def retrieve(self, request, pk=None):
        """Get setting by key (pk can be key string)"""
        try:
            # Try to get by ID first
            setting = self.get_object()
        except:
            # Try to get by key
            try:
                setting = SystemSettings.objects.get(key=pk)
            except SystemSettings.DoesNotExist:
                return error_response(
                    error='Setting not found',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
        
        serializer = self.get_serializer(setting)
        return success_response(data=serializer.data, request=request)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    create=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
    destroy=extend_schema(tags=['System']),
)
class AccountSettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing account-level settings
    Unified API Standard v1.0 compliant
    """
    queryset = AccountSettings.objects.all()
    serializer_class = AccountSettingsSerializer
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    authentication_classes = [JWTAuthentication]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_queryset(self):
        """Get settings for current account"""
        return super().get_queryset().order_by('key')
    
    def retrieve(self, request, pk=None):
        """Get setting by key (pk can be key string)"""
        queryset = self.get_queryset()
        try:
            # Try to get by ID first
            setting = queryset.get(pk=pk)
        except:
            # Try to get by key
            try:
                setting = queryset.get(key=pk)
            except AccountSettings.DoesNotExist:
                return error_response(
                    error='Setting not found',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
        
        serializer = self.get_serializer(setting)
        return success_response(data=serializer.data, request=request)
    
    def perform_create(self, serializer):
        """Set account automatically"""
        account = getattr(self.request, 'account', None)
        if not account:
            user = getattr(self.request, 'user', None)
            if user:
                account = getattr(user, 'account', None)
        
        if not account:
            from rest_framework.exceptions import ValidationError
            raise ValidationError("Account is required")
        
        serializer.save(account=account)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    create=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
    destroy=extend_schema(tags=['System']),
)
class UserSettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing user-level settings
    Unified API Standard v1.0 compliant
    """
    queryset = UserSettings.objects.all()
    serializer_class = UserSettingsSerializer
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    authentication_classes = [JWTAuthentication]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_queryset(self):
        """Get settings for current user and account"""
        user = self.request.user
        account = getattr(self.request, 'account', None)
        if not account:
            account = getattr(user, 'account', None)
        
        if account:
            return UserSettings.objects.filter(user=user, account=account).order_by('key')
        return UserSettings.objects.none()
    
    def retrieve(self, request, pk=None):
        """Get setting by key (pk can be key string)"""
        queryset = self.get_queryset()
        try:
            # Try to get by ID first
            setting = queryset.get(pk=pk)
        except:
            # Try to get by key
            try:
                setting = queryset.get(key=pk)
            except UserSettings.DoesNotExist:
                return error_response(
                    error='Setting not found',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
        
        serializer = self.get_serializer(setting)
        return success_response(data=serializer.data, request=request)
    
    def perform_create(self, serializer):
        """Set user and account automatically"""
        user = self.request.user
        account = getattr(self.request, 'account', None)
        if not account:
            account = getattr(user, 'account', None)
        
        if not account:
            from rest_framework.exceptions import ValidationError
            raise ValidationError("Account is required")
        
        serializer.save(user=user, account=account)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    create=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
    destroy=extend_schema(tags=['System']),
)
class ModuleSettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing module-specific settings
    Unified API Standard v1.0 compliant
    """
    queryset = ModuleSettings.objects.all()
    serializer_class = ModuleSettingsSerializer
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    authentication_classes = [JWTAuthentication]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_queryset(self):
        """Get settings for current account, optionally filtered by module"""
        queryset = super().get_queryset()
        module_name = self.request.query_params.get('module_name')
        if module_name:
            queryset = queryset.filter(module_name=module_name)
        return queryset.order_by('module_name', 'key')
    
    @action(detail=False, methods=['get'], url_path='module/(?P<module_name>[^/.]+)', url_name='by_module')
    def by_module(self, request, module_name=None):
        """Get all settings for a specific module"""
        queryset = self.get_queryset().filter(module_name=module_name)
        serializer = self.get_serializer(queryset, many=True)
        return success_response(data=serializer.data, request=request)
    
    def retrieve(self, request, pk=None):
        """Get setting by key (pk can be key string)"""
        # Special case: if pk is "enable", this is likely a routing conflict
        # The correct endpoint is /settings/modules/enable/ which should go to ModuleEnableSettingsViewSet
        if pk == 'enable':
            return error_response(
                error='Use /api/v1/system/settings/modules/enable/ endpoint for module enable settings',
                status_code=status.HTTP_404_NOT_FOUND,
                request=request
            )
        
        queryset = self.get_queryset()
        try:
            # Try to get by ID first
            setting = queryset.get(pk=pk)
        except:
            # Try to get by module_name and key
            module_name = request.query_params.get('module_name')
            if module_name:
                try:
                    setting = queryset.get(module_name=module_name, key=pk)
                except ModuleSettings.DoesNotExist:
                    return error_response(
                        error='Setting not found',
                        status_code=status.HTTP_404_NOT_FOUND,
                        request=request
                    )
            else:
                return error_response(
                    error='Setting not found',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
        
        serializer = self.get_serializer(setting)
        return success_response(data=serializer.data, request=request)
    
    def perform_create(self, serializer):
        """Set account automatically"""
        account = getattr(self.request, 'account', None)
        if not account:
            user = getattr(self.request, 'user', None)
            if user:
                account = getattr(user, 'account', None)
        
        if not account:
            from rest_framework.exceptions import ValidationError
            raise ValidationError("Account is required")
        
        serializer.save(account=account)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
)
class ModuleEnableSettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing module enable/disable settings
    Unified API Standard v1.0 compliant
    One record per account
    Read access: All authenticated users
    Write access: Admins/Owners only
    """
    queryset = ModuleEnableSettings.objects.all()
    serializer_class = ModuleEnableSettingsSerializer
    authentication_classes = [JWTAuthentication]
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_permissions(self):
        """
        Allow read access to all authenticated users,
        but restrict write access to admins/owners
        """
        if self.action in ['list', 'retrieve', 'get_current']:
            permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
        else:
            permission_classes = [IsAuthenticatedAndActive, HasTenantAccess, IsAdminOrOwner]
        return [permission() for permission in permission_classes]
    
    def get_queryset(self):
        """Get module enable settings for current account"""
        # Return queryset filtered by account - but list() will handle get_or_create
        queryset = super().get_queryset()
        # Filter by account if available
        account = getattr(self.request, 'account', None)
        if not account:
            user = getattr(self.request, 'user', None)
            if user:
                account = getattr(user, 'account', None)
        if account:
            queryset = queryset.filter(account=account)
        return queryset
    
    @action(detail=False, methods=['get', 'put'], url_path='current', url_name='current')
    def get_current(self, request):
        """Get or update current account's module enable settings"""
        if request.method == 'GET':
            return self.list(request)
        else:
            return self.update(request, pk=None)
    
    def list(self, request, *args, **kwargs):
        """Get or create module enable settings for current account"""
        try:
            account = getattr(request, 'account', None)
            if not account:
                user = getattr(request, 'user', None)
                if user and hasattr(user, 'account'):
                    account = user.account
            
            if not account:
                return error_response(
                    error='Account not found',
                    status_code=status.HTTP_400_BAD_REQUEST,
                    request=request
                )
            
            # Check if table exists (migration might not have been run)
            try:
                # Get or create settings for account (one per account)
                try:
                    settings = ModuleEnableSettings.objects.get(account=account)
                except ModuleEnableSettings.DoesNotExist:
                    # Create default settings for account
                    settings = ModuleEnableSettings.objects.create(account=account)
                
                serializer = self.get_serializer(settings)
                return success_response(data=serializer.data, request=request)
            except Exception as db_error:
                # Check if it's a "table does not exist" error
                error_str = str(db_error)
                if 'does not exist' in error_str.lower() or 'relation' in error_str.lower():
                    import logging
                    logger = logging.getLogger(__name__)
                    logger.error(f"ModuleEnableSettings table does not exist. Migration 0007_add_module_enable_settings needs to be run: {error_str}")
                    return error_response(
                        error='Module enable settings table not found. Please run migration: python manage.py migrate igny8_core_modules_system 0007',
                        status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                        request=request
                    )
                # Re-raise other database errors
                raise
        except Exception as e:
            import traceback
            error_trace = traceback.format_exc()
            return error_response(
                error=f'Failed to load module enable settings: {str(e)}',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )
    
    def retrieve(self, request, pk=None, *args, **kwargs):
        """Get module enable settings for current account"""
        try:
            account = getattr(request, 'account', None)
            if not account:
                user = getattr(request, 'user', None)
                if user:
                    account = getattr(user, 'account', None)
            
            if not account:
                return error_response(
                    error='Account not found',
                    status_code=status.HTTP_400_BAD_REQUEST,
                    request=request
                )
            
            # Get or create settings for account
            settings, created = ModuleEnableSettings.objects.get_or_create(account=account)
            serializer = self.get_serializer(settings)
            return success_response(data=serializer.data, request=request)
        except Exception as e:
            return error_response(
                error=f'Failed to load module enable settings: {str(e)}',
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                request=request
            )
    
    def update(self, request, pk=None):
        """Update module enable settings for current account"""
        account = getattr(request, 'account', None)
        if not account:
            user = getattr(request, 'user', None)
            if user:
                account = getattr(user, 'account', None)
        
        if not account:
            return error_response(
                error='Account not found',
                status_code=status.HTTP_400_BAD_REQUEST,
                request=request
            )
        
        # Get or create settings for account
        settings = ModuleEnableSettings.get_or_create_for_account(account)
        serializer = self.get_serializer(settings, data=request.data, partial=True)
        
        if serializer.is_valid():
            serializer.save()
            return success_response(data=serializer.data, request=request)
        
        return error_response(
            error='Validation failed',
            errors=serializer.errors,
            status_code=status.HTTP_400_BAD_REQUEST,
            request=request
        )
    
    def partial_update(self, request, pk=None):
        """Partial update module enable settings"""
        return self.update(request, pk)


@extend_schema_view(
    list=extend_schema(tags=['System']),
    create=extend_schema(tags=['System']),
    retrieve=extend_schema(tags=['System']),
    update=extend_schema(tags=['System']),
    partial_update=extend_schema(tags=['System']),
    destroy=extend_schema(tags=['System']),
)
class AISettingsViewSet(AccountModelViewSet):
    """
    ViewSet for managing AI-specific settings
    Unified API Standard v1.0 compliant
    """
    queryset = AISettings.objects.all()
    serializer_class = AISettingsSerializer
    permission_classes = [IsAuthenticatedAndActive, HasTenantAccess]
    authentication_classes = [JWTAuthentication]
    pagination_class = CustomPageNumberPagination
    throttle_scope = 'system'
    throttle_classes = [DebugScopedRateThrottle]
    
    def get_queryset(self):
        """Get AI settings for current account"""
        return super().get_queryset().order_by('integration_type')
    
    def retrieve(self, request, pk=None):
        """Get setting by integration_type (pk can be integration_type string)"""
        queryset = self.get_queryset()
        try:
            # Try to get by ID first
            setting = queryset.get(pk=pk)
        except:
            # Try to get by integration_type
            try:
                setting = queryset.get(integration_type=pk)
            except AISettings.DoesNotExist:
                return error_response(
                    error='AI Setting not found',
                    status_code=status.HTTP_404_NOT_FOUND,
                    request=request
                )
        
        serializer = self.get_serializer(setting)
        return success_response(data=serializer.data, request=request)
    
    def perform_create(self, serializer):
        """Set account automatically"""
        account = getattr(self.request, 'account', None)
        if not account:
            user = getattr(self.request, 'user', None)
            if user:
                account = getattr(user, 'account', None)
        
        if not account:
            from rest_framework.exceptions import ValidationError
            raise ValidationError("Account is required")
        
        serializer.save(account=account)

