# -*- coding: utf-8 -*-
"""
Activities Admin Configuration

This module configures the Django admin interface for the activities app.
It provides optimized admin views with filters, search capabilities,
and grouped fields for better usability.

Admin Classes:
    - ActivityTypeAdmin: Admin for activity type management
    - ActivityAdmin: Admin for activity log viewing and management
    - AuditLogAdmin: Admin for audit log viewing
    - SecurityEventAdmin: Admin for security event management

Author: AdTlas Development Team
Version: 1.0.0
Last Updated: 2024
"""

from django.contrib import admin
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.db.models import Count, Q
from django.contrib.admin import SimpleListFilter
from django.utils import timezone
from datetime import timedelta

from .models import ActivityType, Activity, AuditLog, SecurityEvent


class DateRangeFilter(SimpleListFilter):
    """
    Custom filter for date ranges in admin.
    """
    title = _('Date Range')
    parameter_name = 'date_range'
    
    def lookups(self, request, model_admin):
        return (
            ('today', _('Today')),
            ('yesterday', _('Yesterday')),
            ('week', _('This Week')),
            ('month', _('This Month')),
            ('quarter', _('This Quarter')),
            ('year', _('This Year')),
        )
    
    def queryset(self, request, queryset):
        now = timezone.now()
        
        if self.value() == 'today':
            return queryset.filter(created_at__date=now.date())
        elif self.value() == 'yesterday':
            yesterday = now - timedelta(days=1)
            return queryset.filter(created_at__date=yesterday.date())
        elif self.value() == 'week':
            week_start = now - timedelta(days=now.weekday())
            return queryset.filter(created_at__gte=week_start.replace(hour=0, minute=0, second=0))
        elif self.value() == 'month':
            month_start = now.replace(day=1, hour=0, minute=0, second=0)
            return queryset.filter(created_at__gte=month_start)
        elif self.value() == 'quarter':
            quarter_start = now.replace(month=((now.month-1)//3)*3+1, day=1, hour=0, minute=0, second=0)
            return queryset.filter(created_at__gte=quarter_start)
        elif self.value() == 'year':
            year_start = now.replace(month=1, day=1, hour=0, minute=0, second=0)
            return queryset.filter(created_at__gte=year_start)
        
        return queryset


class SecurityRelatedFilter(SimpleListFilter):
    """
    Filter for security-related activities.
    """
    title = _('Security Related')
    parameter_name = 'security_related'
    
    def lookups(self, request, model_admin):
        return (
            ('yes', _('Security Related')),
            ('no', _('Not Security Related')),
        )
    
    def queryset(self, request, queryset):
        if self.value() == 'yes':
            return queryset.filter(activity_type__is_security_related=True)
        elif self.value() == 'no':
            return queryset.filter(activity_type__is_security_related=False)
        return queryset


@admin.register(ActivityType)
class ActivityTypeAdmin(admin.ModelAdmin):
    """
    Admin configuration for ActivityType model.
    
    Provides comprehensive management interface for activity types
    with search, filtering, and bulk operations.
    """
    
    list_display = [
        'name',
        'code',
        'is_security_related_badge',
        'retention_days',
        'activity_count',
        'is_active_badge',
        'created_at',
    ]
    
    list_filter = [
        'is_security_related',
        'is_active',
        'retention_days',
        'created_at',
    ]
    
    search_fields = [
        'name',
        'code',
        'description',
    ]
    
    list_editable = [
        'is_active',
        'retention_days',
    ]
    
    readonly_fields = [
        'created_at',
        'updated_at',
        'activity_count',
    ]
    
    fieldsets = (
        (_('Basic Information'), {
            'fields': ('name', 'code', 'description')
        }),
        (_('Configuration'), {
            'fields': ('is_security_related', 'retention_days', 'is_active')
        }),
        (_('Metadata'), {
            'fields': ('created_at', 'updated_at', 'activity_count'),
            'classes': ('collapse',)
        }),
    )
    
    actions = [
        'activate_activity_types',
        'deactivate_activity_types',
        'mark_as_security_related',
    ]
    
    def is_security_related_badge(self, obj):
        """
        Display security related status as a badge.
        
        Args:
            obj (ActivityType): The activity type instance
            
        Returns:
            str: HTML badge for security status
        """
        if obj.is_security_related:
            return format_html(
                '<span class="badge" style="background-color: #dc3545; color: white; padding: 2px 6px; border-radius: 3px;">🔒 Security</span>'
            )
        return format_html(
            '<span class="badge" style="background-color: #6c757d; color: white; padding: 2px 6px; border-radius: 3px;">📋 General</span>'
        )
    is_security_related_badge.short_description = _('Type')
    is_security_related_badge.admin_order_field = 'is_security_related'
    
    def is_active_badge(self, obj):
        """
        Display active status as a badge.
        
        Args:
            obj (ActivityType): The activity type instance
            
        Returns:
            str: HTML badge for active status
        """
        if obj.is_active:
            return format_html(
                '<span class="badge" style="background-color: #28a745; color: white; padding: 2px 6px; border-radius: 3px;">✓ Active</span>'
            )
        return format_html(
            '<span class="badge" style="background-color: #dc3545; color: white; padding: 2px 6px; border-radius: 3px;">✗ Inactive</span>'
        )
    is_active_badge.short_description = _('Status')
    is_active_badge.admin_order_field = 'is_active'
    
    def activity_count(self, obj):
        """
        Get the count of activities for this type.
        
        Args:
            obj (ActivityType): The activity type instance
            
        Returns:
            int: Number of activities
        """
        return obj.activities.count()
    activity_count.short_description = _('Activities Count')
    
    def activate_activity_types(self, request, queryset):
        """
        Bulk action to activate activity types.
        
        Args:
            request: The HTTP request
            queryset: Selected activity types
        """
        updated = queryset.update(is_active=True)
        self.message_user(request, f'{updated} activity types were activated.')
    activate_activity_types.short_description = _('Activate selected activity types')
    
    def deactivate_activity_types(self, request, queryset):
        """
        Bulk action to deactivate activity types.
        
        Args:
            request: The HTTP request
            queryset: Selected activity types
        """
        updated = queryset.update(is_active=False)
        self.message_user(request, f'{updated} activity types were deactivated.')
    deactivate_activity_types.short_description = _('Deactivate selected activity types')
    
    def mark_as_security_related(self, request, queryset):
        """
        Bulk action to mark activity types as security related.
        
        Args:
            request: The HTTP request
            queryset: Selected activity types
        """
        updated = queryset.update(is_security_related=True)
        self.message_user(request, f'{updated} activity types were marked as security related.')
    mark_as_security_related.short_description = _('Mark as security related')


@admin.register(Activity)
class ActivityAdmin(admin.ModelAdmin):
    """
    Admin configuration for Activity model.
    
    Provides comprehensive viewing and filtering of activity logs
    with advanced search and export capabilities.
    """
    
    list_display = [
        'user_display',
        'action_badge',
        'activity_type',
        'description_truncated',
        'success_badge',
        'ip_address',
        'created_at',
        'view_details_link',
    ]
    
    list_filter = [
        DateRangeFilter,
        SecurityRelatedFilter,
        'action',
        'success',
        'activity_type',
        'created_at',
    ]
    
    search_fields = [
        'user__email',
        'user__first_name',
        'user__last_name',
        'description',
        'ip_address',
        'user_agent',
    ]
    
    readonly_fields = [
        'user',
        'activity_type',
        'action',
        'description',
        'ip_address',
        'user_agent',
        'session_key',
        'extra_data_formatted',
        'content_type',
        'object_id',
        'content_object',
        'success',
        'error_message',
        'created_at',
        'updated_at',
    ]
    
    fieldsets = (
        (_('Activity Information'), {
            'fields': ('user', 'activity_type', 'action', 'description', 'success')
        }),
        (_('Request Information'), {
            'fields': ('ip_address', 'user_agent', 'session_key'),
            'classes': ('collapse',)
        }),
        (_('Related Object'), {
            'fields': ('content_type', 'object_id', 'content_object'),
            'classes': ('collapse',)
        }),
        (_('Additional Data'), {
            'fields': ('extra_data_formatted', 'error_message'),
            'classes': ('collapse',)
        }),
        (_('Metadata'), {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )
    
    date_hierarchy = 'created_at'
    
    list_per_page = 50
    
    actions = [
        'export_selected_activities',
    ]
    
    def has_add_permission(self, request):
        """
        Disable adding activities through admin.
        
        Args:
            request: The HTTP request
            
        Returns:
            bool: False to disable adding
        """
        return False
    
    def has_change_permission(self, request, obj=None):
        """
        Disable changing activities through admin.
        
        Args:
            request: The HTTP request
            obj: The activity object
            
        Returns:
            bool: False to disable changing
        """
        return False
    
    def user_display(self, obj):
        """
        Display user information with link to user admin.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: HTML link to user or 'System'
        """
        if obj.user:
            url = reverse('admin:accounts_user_change', args=[obj.user.pk])
            return format_html('<a href="{}">{}</a>', url, obj.user.email)
        return format_html('<em style="color: #666;">System</em>')
    user_display.short_description = _('User')
    user_display.admin_order_field = 'user__email'
    
    def action_badge(self, obj):
        """
        Display action as a colored badge.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: HTML badge for action
        """
        color_map = {
            'login': '#28a745',
            'logout': '#6c757d',
            'register': '#007bff',
            'create': '#28a745',
            'update': '#ffc107',
            'delete': '#dc3545',
            'security_event': '#dc3545',
            'admin_action': '#6f42c1',
        }
        color = color_map.get(obj.action, '#6c757d')
        return format_html(
            '<span class="badge" style="background-color: {}; color: white; padding: 2px 6px; border-radius: 3px;">{}</span>',
            color,
            obj.get_action_display()
        )
    action_badge.short_description = _('Action')
    action_badge.admin_order_field = 'action'
    
    def description_truncated(self, obj):
        """
        Display truncated description.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: Truncated description
        """
        if len(obj.description) > 50:
            return f"{obj.description[:50]}..."
        return obj.description
    description_truncated.short_description = _('Description')
    
    def success_badge(self, obj):
        """
        Display success status as a badge.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: HTML badge for success status
        """
        if obj.success:
            return format_html(
                '<span class="badge" style="background-color: #28a745; color: white; padding: 2px 6px; border-radius: 3px;">✓ Success</span>'
            )
        return format_html(
            '<span class="badge" style="background-color: #dc3545; color: white; padding: 2px 6px; border-radius: 3px;">✗ Failed</span>'
        )
    success_badge.short_description = _('Status')
    success_badge.admin_order_field = 'success'
    
    def view_details_link(self, obj):
        """
        Display link to view activity details.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: HTML link to activity details
        """
        url = reverse('admin:activities_activity_change', args=[obj.pk])
        return format_html('<a href="{}" class="button">View Details</a>', url)
    view_details_link.short_description = _('Details')
    
    def extra_data_formatted(self, obj):
        """
        Display formatted extra data.
        
        Args:
            obj (Activity): The activity instance
            
        Returns:
            str: Formatted JSON data
        """
        if obj.extra_data:
            import json
            return format_html(
                '<pre style="background: #f8f9fa; padding: 10px; border-radius: 4px; max-height: 200px; overflow-y: auto;">{}</pre>',
                json.dumps(obj.extra_data, indent=2)
            )
        return _('No extra data')
    extra_data_formatted.short_description = _('Extra Data')
    
    def export_selected_activities(self, request, queryset):
        """
        Export selected activities to CSV.
        
        Args:
            request: The HTTP request
            queryset: Selected activities
        """
        import csv
        from django.http import HttpResponse
        
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="activities.csv"'
        
        writer = csv.writer(response)
        writer.writerow([
            'User', 'Action', 'Description', 'IP Address', 
            'Success', 'Created At', 'Activity Type'
        ])
        
        for activity in queryset:
            writer.writerow([
                activity.user.email if activity.user else 'System',
                activity.get_action_display(),
                activity.description,
                activity.ip_address,
                'Yes' if activity.success else 'No',
                activity.created_at.strftime('%Y-%m-%d %H:%M:%S'),
                activity.activity_type.name
            ])
        
        return response
    export_selected_activities.short_description = _('Export selected activities to CSV')


@admin.register(AuditLog)
class AuditLogAdmin(admin.ModelAdmin):
    """
    Admin configuration for AuditLog model.
    
    Provides detailed audit trail viewing with change tracking.
    """
    
    list_display = [
        'user_display',
        'action_badge',
        'model_name',
        'object_repr_truncated',
        'changes_summary',
        'created_at',
    ]
    
    list_filter = [
        DateRangeFilter,
        'action',
        'model_name',
        'created_at',
    ]
    
    search_fields = [
        'user__email',
        'model_name',
        'object_repr',
        'object_id',
    ]
    
    readonly_fields = [
        'user',
        'action',
        'model_name',
        'object_id',
        'object_repr',
        'changes_formatted',
        'before_state_formatted',
        'after_state_formatted',
        'ip_address',
        'user_agent',
        'created_at',
        'updated_at',
    ]
    
    fieldsets = (
        (_('Audit Information'), {
            'fields': ('user', 'action', 'model_name', 'object_id', 'object_repr')
        }),
        (_('Changes'), {
            'fields': ('changes_formatted',)
        }),
        (_('States'), {
            'fields': ('before_state_formatted', 'after_state_formatted'),
            'classes': ('collapse',)
        }),
        (_('Request Information'), {
            'fields': ('ip_address', 'user_agent'),
            'classes': ('collapse',)
        }),
        (_('Metadata'), {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )
    
    date_hierarchy = 'created_at'
    
    def has_add_permission(self, request):
        """Disable adding audit logs through admin."""
        return False
    
    def has_change_permission(self, request, obj=None):
        """Disable changing audit logs through admin."""
        return False
    
    def user_display(self, obj):
        """Display user with link."""
        if obj.user:
            url = reverse('admin:accounts_user_change', args=[obj.user.pk])
            return format_html('<a href="{}">{}</a>', url, obj.user.email)
        return format_html('<em style="color: #666;">System</em>')
    user_display.short_description = _('User')
    
    def action_badge(self, obj):
        """Display action as badge."""
        color_map = {
            'create': '#28a745',
            'update': '#ffc107',
            'delete': '#dc3545',
        }
        color = color_map.get(obj.action, '#6c757d')
        return format_html(
            '<span class="badge" style="background-color: {}; color: white; padding: 2px 6px; border-radius: 3px;">{}</span>',
            color,
            obj.get_action_display()
        )
    action_badge.short_description = _('Action')
    
    def object_repr_truncated(self, obj):
        """Display truncated object representation."""
        if len(obj.object_repr) > 30:
            return f"{obj.object_repr[:30]}..."
        return obj.object_repr
    object_repr_truncated.short_description = _('Object')
    
    def changes_summary(self, obj):
        """Display summary of changes."""
        if obj.changes:
            count = len(obj.changes)
            fields = ', '.join(list(obj.changes.keys())[:3])
            if count > 3:
                fields += f' (+{count-3} more)'
            return f"{count} fields: {fields}"
        return _('No changes')
    changes_summary.short_description = _('Changes')
    
    def changes_formatted(self, obj):
        """Display formatted changes."""
        if obj.changes:
            import json
            return format_html(
                '<pre style="background: #f8f9fa; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto;">{}</pre>',
                json.dumps(obj.changes, indent=2)
            )
        return _('No changes')
    changes_formatted.short_description = _('Changes')
    
    def before_state_formatted(self, obj):
        """Display formatted before state."""
        if obj.before_state:
            import json
            return format_html(
                '<pre style="background: #f8f9fa; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto;">{}</pre>',
                json.dumps(obj.before_state, indent=2)
            )
        return _('No before state')
    before_state_formatted.short_description = _('Before State')
    
    def after_state_formatted(self, obj):
        """Display formatted after state."""
        if obj.after_state:
            import json
            return format_html(
                '<pre style="background: #f8f9fa; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto;">{}</pre>',
                json.dumps(obj.after_state, indent=2)
            )
        return _('No after state')
    after_state_formatted.short_description = _('After State')


@admin.register(SecurityEvent)
class SecurityEventAdmin(admin.ModelAdmin):
    """
    Admin configuration for SecurityEvent model.
    
    Provides security event management with resolution tracking.
    """
    
    list_display = [
        'event_type_badge',
        'severity_badge',
        'user_display',
        'description_truncated',
        'resolved_badge',
        'ip_address',
        'created_at',
    ]
    
    list_filter = [
        DateRangeFilter,
        'event_type',
        'severity',
        'resolved',
        'created_at',
    ]
    
    search_fields = [
        'user__email',
        'description',
        'ip_address',
        'resolution_notes',
    ]
    
    readonly_fields = [
        'event_type',
        'severity',
        'user',
        'ip_address',
        'user_agent',
        'description',
        'details_formatted',
        'created_at',
        'updated_at',
    ]
    
    fieldsets = (
        (_('Event Information'), {
            'fields': ('event_type', 'severity', 'user', 'description')
        }),
        (_('Request Information'), {
            'fields': ('ip_address', 'user_agent'),
            'classes': ('collapse',)
        }),
        (_('Event Details'), {
            'fields': ('details_formatted',),
            'classes': ('collapse',)
        }),
        (_('Resolution'), {
            'fields': ('resolved', 'resolved_by', 'resolved_at', 'resolution_notes')
        }),
        (_('Metadata'), {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )
    
    date_hierarchy = 'created_at'
    
    actions = [
        'mark_as_resolved',
    ]
    
    def event_type_badge(self, obj):
        """Display event type as badge."""
        color_map = {
            'failed_login': '#ffc107',
            'account_lockout': '#dc3545',
            'suspicious_activity': '#fd7e14',
            'unauthorized_access': '#dc3545',
            'data_breach': '#dc3545',
            'malware_detected': '#dc3545',
            'policy_violation': '#ffc107',
            'privilege_escalation': '#dc3545',
        }
        color = color_map.get(obj.event_type, '#6c757d')
        return format_html(
            '<span class="badge" style="background-color: {}; color: white; padding: 2px 6px; border-radius: 3px;">{}</span>',
            color,
            obj.get_event_type_display()
        )
    event_type_badge.short_description = _('Event Type')
    
    def severity_badge(self, obj):
        """Display severity as badge."""
        color_map = {
            'low': '#28a745',
            'medium': '#ffc107',
            'high': '#fd7e14',
            'critical': '#dc3545',
        }
        color = color_map.get(obj.severity, '#6c757d')
        return format_html(
            '<span class="badge" style="background-color: {}; color: white; padding: 2px 6px; border-radius: 3px;">{}</span>',
            color,
            obj.get_severity_display().upper()
        )
    severity_badge.short_description = _('Severity')
    
    def user_display(self, obj):
        """Display user with link."""
        if obj.user:
            url = reverse('admin:accounts_user_change', args=[obj.user.pk])
            return format_html('<a href="{}">{}</a>', url, obj.user.email)
        return format_html('<em style="color: #666;">Unknown</em>')
    user_display.short_description = _('User')
    
    def description_truncated(self, obj):
        """Display truncated description."""
        if len(obj.description) > 50:
            return f"{obj.description[:50]}..."
        return obj.description
    description_truncated.short_description = _('Description')
    
    def resolved_badge(self, obj):
        """Display resolved status as badge."""
        if obj.resolved:
            return format_html(
                '<span class="badge" style="background-color: #28a745; color: white; padding: 2px 6px; border-radius: 3px;">✓ Resolved</span>'
            )
        return format_html(
            '<span class="badge" style="background-color: #dc3545; color: white; padding: 2px 6px; border-radius: 3px;">⚠ Open</span>'
        )
    resolved_badge.short_description = _('Status')
    
    def details_formatted(self, obj):
        """Display formatted event details."""
        if obj.details:
            import json
            return format_html(
                '<pre style="background: #f8f9fa; padding: 10px; border-radius: 4px; max-height: 300px; overflow-y: auto;">{}</pre>',
                json.dumps(obj.details, indent=2)
            )
        return _('No details')
    details_formatted.short_description = _('Event Details')
    
    def mark_as_resolved(self, request, queryset):
        """Bulk action to mark security events as resolved."""
        updated = 0
        for event in queryset.filter(resolved=False):
            event.resolve(resolved_by=request.user, resolution_notes='Bulk resolved via admin')
            updated += 1
        
        self.message_user(request, f'{updated} security events were marked as resolved.')
    mark_as_resolved.short_description = _('Mark selected events as resolved')