# -*- coding: utf-8 -*-
"""
Core API Views Module

This module contains API views for the core app including ViewSets,
API endpoints, and data serialization for the REST API.
"""

from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.db.models import Count, Q
from django.core.cache import cache

from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend

from apps.accounts.models import User, Role
from apps.authentication.models import LoginAttempt, UserSession
from apps.core.models import (
    SystemConfiguration,
    ApplicationMetrics,
    AuditLog,
    NotificationTemplate,
    SystemHealth
)
from .serializers import (
    SystemConfigurationSerializer,
    ApplicationMetricsSerializer,
    AuditLogSerializer,
    NotificationTemplateSerializer,
    SystemHealthSerializer,
    SystemHealthSummarySerializer,
    DashboardStatsSerializer
)

import logging

# Set up logging
logger = logging.getLogger(__name__)

# AJAX Views
@csrf_exempt
def dashboard_stats_api(request):
    """
    API endpoint for dashboard statistics.
    
    Returns JSON data for dashboard widgets and charts.
    
    Args:
        request: HTTP request object
        
    Returns:
        JsonResponse: Dashboard statistics data
    """
    if not request.user.is_authenticated:
        return JsonResponse({"error": "Authentication required"}, status=401)
    
    try:
        # Get user statistics
        user_stats = {
            "total_logins": LoginAttempt.objects.filter(
                user=request.user,
                success=True
            ).count(),
            "active_sessions": UserSession.objects.filter(
                user=request.user,
                is_active=True
            ).count()
        }
        
        # Get system statistics for admin users
        system_stats = {}
        if request.user.is_staff:
            system_stats = {
                "total_users": User.objects.count(),
                "active_users": User.objects.filter(is_active=True).count(),
                "total_roles": Role.objects.count()
            }
        
        return JsonResponse({
            "user_stats": user_stats,
            "system_stats": system_stats,
            "timestamp": timezone.now().isoformat()
        })
    
    except Exception as e:
        logger.error(f"Error in dashboard_stats_api: {e}")
        return JsonResponse({"error": "Internal server error"}, status=500)


class SystemConfigurationViewSet(viewsets.ModelViewSet):
    """
    ViewSet for SystemConfiguration model.
    
    Provides CRUD operations for system configuration settings.
    Only accessible by admin users.
    """
    
    queryset = SystemConfiguration.objects.all()
    serializer_class = SystemConfigurationSerializer
    permission_classes = [IsAuthenticated, IsAdminUser]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['is_active']
    search_fields = ['key', 'description', 'value']
    ordering_fields = ['key', 'created_at', 'updated_at']
    ordering = ['key']
    
    def perform_create(self, serializer):
        """
        Set the created_by field when creating a configuration.
        
        Args:
            serializer: Configuration serializer instance
        """
        serializer.save(created_by=self.request.user)
    
    def perform_update(self, serializer):
        """
        Set the updated_by field when updating a configuration.
        
        Args:
            serializer: Configuration serializer instance
        """
        serializer.save(updated_by=self.request.user)
    
    @action(detail=False, methods=['get'])
    def active(self, request):
        """
        Get only active configurations.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Active configurations
        """
        active_configs = self.queryset.filter(is_active=True)
        serializer = self.get_serializer(active_configs, many=True)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def toggle_active(self, request, pk=None):
        """
        Toggle the active status of a configuration.
        
        Args:
            request: HTTP request object
            pk: Configuration primary key
            
        Returns:
            Response: Updated configuration
        """
        config = self.get_object()
        config.is_active = not config.is_active
        config.updated_by = request.user
        config.save()
        
        serializer = self.get_serializer(config)
        return Response(serializer.data)


class ApplicationMetricsViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for ApplicationMetrics model.
    
    Read-only access to application metrics data.
    """
    
    queryset = ApplicationMetrics.objects.all()
    serializer_class = ApplicationMetricsSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['metric_name', 'metric_type']
    search_fields = ['metric_name']
    ordering_fields = ['metric_name', 'timestamp', 'metric_value']
    ordering = ['-timestamp']
    
    def get_queryset(self):
        """
        Filter queryset based on user permissions.
        
        Returns:
            QuerySet: Filtered metrics queryset
        """
        queryset = super().get_queryset()
        
        # Non-admin users can only see basic metrics
        if not self.request.user.is_staff:
            queryset = queryset.filter(
                metric_name__in=['user_logins', 'page_views', 'api_calls']
            )
        
        return queryset
    
    @action(detail=False, methods=['get'])
    def summary(self, request):
        """
        Get metrics summary by type.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Metrics summary
        """
        summary = self.get_queryset().values('metric_type').annotate(
            count=Count('id'),
            latest_timestamp=timezone.now()
        ).order_by('metric_type')
        
        return Response(summary)


class AuditLogViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for AuditLog model.
    
    Read-only access to audit log entries.
    Only accessible by admin users.
    """
    
    queryset = AuditLog.objects.select_related('user')
    serializer_class = AuditLogSerializer
    permission_classes = [IsAuthenticated, IsAdminUser]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['action', 'resource_type', 'success', 'user']
    search_fields = ['action', 'resource_type', 'resource_id', 'user__email']
    ordering_fields = ['created_at', 'action', 'user']
    ordering = ['-created_at']
    
    @action(detail=False, methods=['get'])
    def recent(self, request):
        """
        Get recent audit log entries (last 24 hours).
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Recent audit logs
        """
        yesterday = timezone.now() - timezone.timedelta(days=1)
        recent_logs = self.queryset.filter(created_at__gte=yesterday)[:50]
        
        serializer = self.get_serializer(recent_logs, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def stats(self, request):
        """
        Get audit log statistics.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Audit log statistics
        """
        stats = {
            'total_entries': self.queryset.count(),
            'successful_actions': self.queryset.filter(success=True).count(),
            'failed_actions': self.queryset.filter(success=False).count(),
            'unique_users': self.queryset.values('user').distinct().count(),
            'actions_by_type': list(
                self.queryset.values('action').annotate(
                    count=Count('id')
                ).order_by('-count')[:10]
            )
        }
        
        return Response(stats)


class NotificationTemplateViewSet(viewsets.ModelViewSet):
    """
    ViewSet for NotificationTemplate model.
    
    Provides CRUD operations for notification templates.
    """
    
    queryset = NotificationTemplate.objects.all()
    serializer_class = NotificationTemplateSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['notification_type', 'is_active']
    search_fields = ['name', 'subject', 'body_text']
    ordering_fields = ['name', 'notification_type', 'created_at']
    ordering = ['name']
    
    def get_permissions(self):
        """
        Set permissions based on action.
        
        Returns:
            list: Permission classes
        """
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            permission_classes = [IsAuthenticated, IsAdminUser]
        else:
            permission_classes = [IsAuthenticated]
        
        return [permission() for permission in permission_classes]
    
    def perform_create(self, serializer):
        """
        Set the created_by field when creating a template.
        
        Args:
            serializer: Template serializer instance
        """
        serializer.save(created_by=self.request.user)
    
    def perform_update(self, serializer):
        """
        Set the updated_by field when updating a template.
        
        Args:
            serializer: Template serializer instance
        """
        serializer.save(updated_by=self.request.user)
    
    @action(detail=False, methods=['get'])
    def by_type(self, request):
        """
        Get templates grouped by notification type.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Templates grouped by type
        """
        templates_by_type = {}
        
        for template in self.queryset.filter(is_active=True):
            if template.notification_type not in templates_by_type:
                templates_by_type[template.notification_type] = []
            
            serializer = self.get_serializer(template)
            templates_by_type[template.notification_type].append(serializer.data)
        
        return Response(templates_by_type)


class SystemHealthViewSet(viewsets.ReadOnlyModelViewSet):
    """
    ViewSet for SystemHealth model.
    
    Read-only access to system health metrics.
    """
    
    queryset = SystemHealth.objects.all()
    serializer_class = SystemHealthSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['service_name', 'status']
    search_fields = ['service_name']
    ordering_fields = ['service_name', 'created_at', 'status']
    ordering = ['-created_at']
    
    def get_permissions(self):
        """
        Set permissions based on user role.
        
        Returns:
            list: Permission classes
        """
        if self.action in ['summary', 'critical']:
            permission_classes = [IsAuthenticated]
        else:
            permission_classes = [IsAuthenticated, IsAdminUser]
        
        return [permission() for permission in permission_classes]
    
    @action(detail=False, methods=['get'])
    def latest(self, request):
        """
        Get latest health status for each service.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Latest health status
        """
        # Get latest entry for each service
        latest_entries = []
        services = self.queryset.values_list('service_name', flat=True).distinct()
        
        for service in services:
            latest = self.queryset.filter(service_name=service).first()
            if latest:
                latest_entries.append(latest)
        
        serializer = self.get_serializer(latest_entries, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def summary(self, request):
        """
        Get system health summary.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Health summary
        """
        # Cache the summary for 5 minutes
        cache_key = 'system_health_summary'
        summary = cache.get(cache_key)
        
        if summary is None:
            # Get latest status for each service
            services = self.queryset.values_list('service_name', flat=True).distinct()
            status_counts = {'healthy': 0, 'warning': 0, 'critical': 0, 'unknown': 0}
            
            for service in services:
                latest = self.queryset.filter(service_name=service).first()
                if latest:
                    status_counts[latest.status] += 1
            
            # Determine overall status
            if status_counts['critical'] > 0:
                overall_status = 'critical'
            elif status_counts['warning'] > 0:
                overall_status = 'warning'
            elif status_counts['healthy'] > 0:
                overall_status = 'healthy'
            else:
                overall_status = 'unknown'
            
            summary = {
                'total_services': sum(status_counts.values()),
                'healthy_services': status_counts['healthy'],
                'warning_services': status_counts['warning'],
                'critical_services': status_counts['critical'],
                'unknown_services': status_counts['unknown'],
                'overall_status': overall_status,
                'last_updated': timezone.now()
            }
            
            cache.set(cache_key, summary, 300)  # Cache for 5 minutes
        
        serializer = SystemHealthSummarySerializer(summary)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def critical(self, request):
        """
        Get services with critical status.
        
        Args:
            request: HTTP request object
            
        Returns:
            Response: Critical services
        """
        critical_services = []
        services = self.queryset.values_list('service_name', flat=True).distinct()
        
        for service in services:
            latest = self.queryset.filter(
                service_name=service,
                status='critical'
            ).first()
            if latest:
                critical_services.append(latest)
        
        serializer = self.get_serializer(critical_services, many=True)
        return Response(serializer.data)


@api_view(['GET'])
@permission_classes([IsAuthenticated])
def enhanced_dashboard_stats(request):
    """
    Enhanced API endpoint for comprehensive dashboard statistics.
    
    Args:
        request: HTTP request object
        
    Returns:
        Response: Enhanced dashboard statistics
    """
    try:
        # Get user statistics
        user_stats = {
            "total_logins": LoginAttempt.objects.filter(
                user=request.user,
                success=True
            ).count(),
            "active_sessions": UserSession.objects.filter(
                user=request.user,
                is_active=True
            ).count(),
            "last_login": request.user.last_login.isoformat() if request.user.last_login else None
        }
        
        # Get system statistics for admin users
        system_stats = {}
        if request.user.is_staff:
            system_stats = {
                "total_users": User.objects.count(),
                "active_users": User.objects.filter(is_active=True).count(),
                "total_roles": Role.objects.count(),
                "recent_logins": LoginAttempt.objects.filter(
                    success=True,
                    created_at__gte=timezone.now() - timezone.timedelta(days=1)
                ).count()
            }
        
        # Get health summary
        health_summary = None
        if request.user.is_staff:
            cache_key = 'dashboard_health_summary'
            health_summary = cache.get(cache_key)
            
            if health_summary is None:
                services = SystemHealth.objects.values_list('service_name', flat=True).distinct()
                status_counts = {'healthy': 0, 'warning': 0, 'critical': 0, 'unknown': 0}
                
                for service in services:
                    latest = SystemHealth.objects.filter(service_name=service).first()
                    if latest:
                        status_counts[latest.status] += 1
                
                health_summary = {
                    'total_services': sum(status_counts.values()),
                    'healthy_services': status_counts['healthy'],
                    'warning_services': status_counts['warning'],
                    'critical_services': status_counts['critical'],
                    'unknown_services': status_counts['unknown']
                }
                
                cache.set(cache_key, health_summary, 300)
        
        # Get recent activities
        recent_activities = []
        if request.user.is_staff:
            recent_logs = AuditLog.objects.select_related('user')[:10]
            for log in recent_logs:
                recent_activities.append({
                    'action': log.action,
                    'resource_type': log.resource_type,
                    'user': log.user.email if log.user else 'System',
                    'timestamp': log.created_at.isoformat(),
                    'success': log.success
                })
        
        data = {
            "user_stats": user_stats,
            "system_stats": system_stats,
            "health_summary": health_summary,
            "recent_activities": recent_activities,
            "timestamp": timezone.now().isoformat()
        }
        
        serializer = DashboardStatsSerializer(data)
        return Response(serializer.data)
    
    except Exception as e:
        logger.error(f"Error in enhanced_dashboard_stats: {e}")
        return Response(
            {"error": "Internal server error"},
            status=status.HTTP_500_INTERNAL_SERVER_ERROR
        )
