"""
Module Registry Views - API views for module and feature management.
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.views import APIView
from django.db import connection
from django.utils import timezone

from .models import Module, TenantModule, Feature, TenantFeatureOverride, LicenseType
from .serializers import (
    ModuleSerializer,
    ModuleDetailSerializer,
    FeatureSerializer,
    TenantModuleSerializer,
    TenantModuleEnableSerializer,
    TenantFeatureOverrideSerializer,
    FeatureToggleSerializer,
    ModuleStatusSerializer,
)
from .services import ModuleService, TenantModuleService, FeatureService, ModuleRegistryService


class ModuleViewSet(viewsets.ReadOnlyModelViewSet):
    """
    API endpoint for viewing available modules.
    
    list: Get all available modules
    retrieve: Get a specific module with details
    
    Custom actions:
    - catalog: Get module catalog for marketplace
    - check_access: Check if current tenant has access to a module
    """
    
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        """Get modules based on status filter."""
        queryset = Module.objects.all()
        
        status_filter = self.request.query_params.get('status')
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        else:
            # By default, show only active and beta modules
            queryset = queryset.filter(status__in=['active', 'beta'])
        
        category = self.request.query_params.get('category')
        if category:
            queryset = queryset.filter(category=category)
        
        search = self.request.query_params.get('search')
        if search:
            queryset = queryset.filter(
                display_name__icontains=search
            ) | queryset.filter(
                description__icontains=search
            ) | queryset.filter(
                tags__contains=[search]
            )
        
        return queryset.order_by('category', 'display_name')
    
    def get_serializer_class(self):
        """Get appropriate serializer."""
        if self.action == 'retrieve':
            return ModuleDetailSerializer
        return ModuleSerializer
    
    @action(detail=False, methods=['get'])
    def catalog(self, request):
        """
        Get module catalog grouped by category.
        Includes installation status for current tenant.
        """
        modules = self.get_queryset()
        
        # Get tenant's installed modules
        tenant_id = getattr(connection, 'tenant', None)
        tenant_id = tenant_id.id if tenant_id else None
        
        installed_modules = {}
        if tenant_id:
            for tm in TenantModule.objects.filter(tenant_id=tenant_id):
                installed_modules[tm.module_id] = tm
        
        # Group by category
        catalog = {}
        for module in modules:
            category = module.category or 'Other'
            if category not in catalog:
                catalog[category] = []
            
            module_data = ModuleSerializer(module).data
            tm = installed_modules.get(module.id)
            module_data['is_installed'] = tm is not None
            module_data['is_active'] = tm.is_active() if tm else False
            module_data['license_type'] = tm.license_type if tm else None
            
            catalog[category].append(module_data)
        
        return Response(catalog)
    
    @action(detail=True, methods=['get'])
    def check_access(self, request, pk=None):
        """Check if current user has access to this module."""
        module = self.get_object()
        has_access = ModuleRegistryService.is_module_enabled_for_user(
            request.user,
            module.name
        )
        
        return Response({
            'module': module.name,
            'has_access': has_access,
        })
    
    @action(detail=True, methods=['get'])
    def features(self, request, pk=None):
        """Get features for a module."""
        module = self.get_object()
        features = module.features.all()
        
        # Add enabled status for current tenant
        enabled_features = []
        if request.user.is_authenticated:
            enabled_features = ModuleRegistryService.get_user_features(
                request.user,
                module.name
            )
        
        result = []
        for feature in features:
            data = FeatureSerializer(feature).data
            data['is_enabled_for_tenant'] = feature.name in enabled_features
            result.append(data)
        
        return Response(result)
    
    @action(detail=False, methods=['get'])
    def categories(self, request):
        """Get list of module categories."""
        categories = Module.objects.filter(
            status='active'
        ).values_list('category', flat=True).distinct()
        
        return Response(list(filter(None, categories)))


class TenantModuleViewSet(viewsets.ModelViewSet):
    """
    API endpoint for managing tenant modules.
    
    Only accessible by tenant admins.
    """
    
    serializer_class = TenantModuleSerializer
    permission_classes = [IsAuthenticated]  # Add custom permission later
    
    def get_queryset(self):
        """Get modules for current tenant."""
        tenant = getattr(connection, 'tenant', None)
        if not tenant:
            return TenantModule.objects.none()
        
        return TenantModule.objects.filter(
            tenant_id=tenant.id
        ).select_related('module').order_by('module__category', 'module__display_name')
    
    @action(detail=False, methods=['get'])
    def active(self, request):
        """Get only active modules for current tenant."""
        queryset = self.get_queryset().filter(is_enabled=True)
        
        # Filter expired
        active_modules = [tm for tm in queryset if tm.is_active()]
        serializer = TenantModuleSerializer(active_modules, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['post'])
    def enable(self, request):
        """Enable a module for current tenant."""
        serializer = TenantModuleEnableSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        tenant = getattr(connection, 'tenant', None)
        if not tenant:
            return Response(
                {'error': 'No tenant context'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        tenant_module = TenantModuleService.enable_module(
            tenant_id=tenant.id,
            module_name=serializer.validated_data['module_name'],
            license_type=serializer.validated_data['license_type'],
            expires_at=serializer.validated_data.get('expires_at'),
            enabled_features=serializer.validated_data.get('enabled_features'),
        )
        
        # Apply settings if provided
        if serializer.validated_data.get('settings'):
            tenant_module.settings = serializer.validated_data['settings']
            tenant_module.save()
        
        return Response(
            TenantModuleSerializer(tenant_module).data,
            status=status.HTTP_201_CREATED
        )
    
    @action(detail=True, methods=['post'])
    def disable(self, request, pk=None):
        """Disable a module for current tenant."""
        tenant_module = self.get_object()
        tenant_module.is_enabled = False
        tenant_module.save()
        
        return Response(TenantModuleSerializer(tenant_module).data)
    
    @action(detail=True, methods=['get', 'patch'])
    def settings(self, request, pk=None):
        """Get or update module settings."""
        tenant_module = self.get_object()
        
        if request.method == 'PATCH':
            # Merge new settings with existing
            tenant_module.settings.update(request.data)
            tenant_module.save()
        
        # Get effective settings
        effective = TenantModuleService.get_module_settings(
            tenant_module.tenant_id,
            tenant_module.module.name
        )
        
        return Response({
            'default': tenant_module.module.default_settings,
            'tenant_overrides': tenant_module.settings,
            'effective': effective,
        })
    
    @action(detail=True, methods=['get'])
    def features(self, request, pk=None):
        """Get feature status for a tenant module."""
        tenant_module = self.get_object()
        
        features = tenant_module.module.features.all()
        result = []
        
        for feature in features:
            is_enabled = FeatureService.is_feature_enabled(
                tenant_module.tenant_id,
                tenant_module.module.name,
                feature.name
            )
            
            # Check for override
            override = TenantFeatureOverride.objects.filter(
                tenant_id=tenant_module.tenant_id,
                feature=feature
            ).first()
            
            result.append({
                'feature': FeatureSerializer(feature).data,
                'is_enabled': is_enabled,
                'has_override': override is not None,
                'override': TenantFeatureOverrideSerializer(override).data if override else None,
            })
        
        return Response(result)
    
    @action(detail=True, methods=['post'])
    def toggle_feature(self, request, pk=None):
        """Toggle a feature for the tenant."""
        tenant_module = self.get_object()
        
        serializer = FeatureToggleSerializer(data={
            **request.data,
            'module_name': tenant_module.module.name,
        })
        serializer.is_valid(raise_exception=True)
        
        override = FeatureService.set_feature_override(
            tenant_id=tenant_module.tenant_id,
            module_name=tenant_module.module.name,
            feature_name=serializer.validated_data['feature_name'],
            is_enabled=serializer.validated_data['is_enabled'],
            reason=serializer.validated_data.get('reason', ''),
            expires_at=serializer.validated_data.get('expires_at'),
            created_by_id=request.user.id,
        )
        
        return Response(TenantFeatureOverrideSerializer(override).data)


class MyModulesView(APIView):
    """
    API endpoint for getting current user's accessible modules.
    """
    
    permission_classes = [IsAuthenticated]
    
    def get(self, request):
        """Get modules accessible to current user."""
        modules = ModuleRegistryService.get_user_modules(request.user)
        
        result = []
        for module_name in modules:
            module = ModuleService.get_module(module_name)
            if module:
                features = ModuleRegistryService.get_user_features(request.user, module_name)
                result.append({
                    'module': ModuleSerializer(module).data,
                    'enabled_features': features,
                })
        
        return Response(result)


class ModuleAccessCheckView(APIView):
    """
    API endpoint for checking module access.
    """
    
    permission_classes = [IsAuthenticated]
    
    def get(self, request, module_name):
        """Check access to a specific module."""
        has_access = ModuleRegistryService.is_module_enabled_for_user(
            request.user,
            module_name
        )
        
        return Response({
            'module': module_name,
            'has_access': has_access,
        })
    
    def post(self, request):
        """Check access to multiple modules at once."""
        module_names = request.data.get('modules', [])
        
        result = {}
        for name in module_names:
            result[name] = ModuleRegistryService.is_module_enabled_for_user(
                request.user,
                name
            )
        
        return Response(result)


class FeatureAccessCheckView(APIView):
    """
    API endpoint for checking feature access.
    """
    
    permission_classes = [IsAuthenticated]
    
    def get(self, request, module_name, feature_name):
        """Check access to a specific feature."""
        has_access = ModuleRegistryService.is_feature_enabled_for_user(
            request.user,
            module_name,
            feature_name
        )
        
        return Response({
            'module': module_name,
            'feature': feature_name,
            'has_access': has_access,
        })
