from django.contrib import admin
from django.contrib import messages
from django.utils import timezone
from django.utils.html import format_html
from django.contrib.admin import AdminSite
from django.urls import reverse

# Customize admin site
class BloggersEMSAdminSite(AdminSite):
    site_title = 'Bloggers of Zed EMS'
    site_header = 'Bloggers of Zed EMS - Admin'
    index_title = 'Admin Dashboard'
    
    def each_context(self, request):
        context = super().each_context(request)
        context['site_url'] = '/'
        return context
    
    def get_app_list(self, request, app_label=None):
        app_list = super().get_app_list(request)
        app_list += [
            {
                'name': 'Main Site',
                'app_label': 'main_site',
                'models': [{
                    'name': 'View Site',
                    'object_name': 'view_site',
                    'admin_url': '/',
                    'view_only': True
                }]
            }
        ]
        return app_list

    class Media:
        css = {
            'all': ('css/admin_custom.css',)
        }

# Create custom admin site instance
admin_site = BloggersEMSAdminSite(name='bloggers_ems_admin')
from .models import (
    Event, 
    Speaker, 
    Agenda, 
    CallForProposal, 
    Gallery, 
    Role, 
    UserProfile, 
    Registration,
    SessionType,
    Proposal,
    SectionImage,
    Publication,
    PublicationType,
    CarouselImage,
    Sponsor
)

class EventAdmin(admin.ModelAdmin):
    list_display = ('title', 'date_time', 'end_time', 'venue', 'get_status', 'registration_open', 'registration_count', 'has_live_stream')
    list_filter = ['date_time', 'status', 'registration_open']
    search_fields = ('title', 'description')
    fieldsets = (
        ('Event Details', {
            'fields': ('title', 'description', 'date_time', 'end_time', 'venue', 'banner_image')
        }),
        ('Registration', {
            'fields': ('registration_open',),
            'description': 'Control whether users can register for this event'
        }),
        ('Live Stream', {
            'fields': ('stream_url',),
            'description': 'Add a Facebook video URL to enable live streaming during the event. The URL should be in the format: https://www.facebook.com/username/videos/VIDEO_ID'
        })
    )
    
    def get_status(self, obj):
        """Display the event status with colored text"""
        status_colors = {
            'upcoming': 'primary',
            'ongoing': 'success',
            'archived': 'secondary'
        }
        color = status_colors.get(obj.status, 'secondary')
        return format_html(
            '<span class="badge bg-{}">{}</span>',
            color,
            obj.get_status_display()
        )
    get_status.short_description = 'Status'
    
    def registration_count(self, obj):
        """Display the number of registered users"""
        return obj.registrations.filter(status='registered').count()
    registration_count.short_description = 'Registered Users'
    
    def has_live_stream(self, obj):
        if not obj.has_stream:
            return format_html('<span class="badge bg-secondary">✗</span>')
        elif obj.is_ongoing:
            return format_html('<span class="badge bg-success">Live</span>')
        elif obj.is_archived and obj.stream_url:
            return format_html('<span class="badge bg-primary">Recorded</span>')
        else:
            return format_html('<span class="badge bg-info">Scheduled</span>')
    has_live_stream.short_description = 'Stream Status'

class SpeakerAdmin(admin.ModelAdmin):
    list_display = ('name', 'organization', 'website_link', 'created_at')
    list_filter = ('organization', 'created_at')
    search_fields = ('name', 'bio', 'organization')
    filter_horizontal = ('events',)

    def website_link(self, obj):
        if obj.website:
            return format_html('<a href="{}" target="_blank">{}</a>', obj.website, obj.website)
        return '-'
    website_link.short_description = 'Website'

class AgendaAdmin(admin.ModelAdmin):
    list_display = ('session_title', 'event', 'session_time', 'get_speakers')
    list_filter = ('event', 'session_time', 'speakers')
    search_fields = ('session_title', 'description')
    filter_horizontal = ('speakers',)  # Better interface for managing multiple speakers

    def get_speakers(self, obj):
        """Display comma-separated list of speakers"""
        return ", ".join([speaker.name for speaker in obj.speakers.all()]) or "-"
    get_speakers.short_description = 'Speakers'

from django.http import HttpResponse
import csv
from datetime import datetime

class RegistrationAdmin(admin.ModelAdmin):
    list_display = ('user', 'event', 'status', 'registration_date', 'attendance_date', 'user_email', 'user_phone')
    list_filter = ('status', 'event', 'registration_date')
    search_fields = ('user__username', 'user__email', 'event__title', 'notes')
    readonly_fields = ('registration_date',)
    actions = ['mark_as_attended', 'mark_as_cancelled', 'export_as_csv']
    change_list_template = 'admin/registration/registration_changelist.html'
    
    def user_email(self, obj):
        return obj.user.email
    user_email.short_description = 'Email'
    
    def user_phone(self, obj):
        profile = UserProfile.objects.filter(user=obj.user).first()
        return profile.phone_number if profile else '-'
    user_phone.short_description = 'Phone'
    
    def mark_as_attended(self, request, queryset):
        queryset.update(status='attended', attendance_date=timezone.now())
    mark_as_attended.short_description = 'Mark selected registrations as attended'
    
    def mark_as_cancelled(self, request, queryset):
        queryset.update(status='cancelled')
    mark_as_cancelled.short_description = 'Mark selected registrations as cancelled'
    
    def export_as_csv(self, request, queryset):
        meta = self.model._meta
        field_names = ['user', 'event', 'status', 'registration_date', 'attendance_date', 'notes']
        
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = f'attachment; filename=registrations-{datetime.now().strftime("%Y%m%d-%H%M%S")}.csv'
        writer = csv.writer(response)

        # Write headers with user email and phone
        writer.writerow(['Username', 'Email', 'Phone', 'Event', 'Status', 'Registration Date', 'Attendance Date', 'Notes'])
        
        # Write data rows
        for obj in queryset:
            profile = UserProfile.objects.filter(user=obj.user).first()
            phone = profile.phone_number if profile else '-'
            
            writer.writerow([
                obj.user.username,
                obj.user.email,
                phone,
                obj.event.title,
                obj.status,
                obj.registration_date.strftime('%Y-%m-%d %H:%M:%S'),
                obj.attendance_date.strftime('%Y-%m-%d %H:%M:%S') if obj.attendance_date else '-',
                obj.notes
            ])
        
        return response
    export_as_csv.short_description = 'Export selected registrations as CSV'

class UserProfileAdmin(admin.ModelAdmin):
    # list_display = ('username_link', 'email', 'role','organization', 'phone_number', 'created_at', 'user_actions')
    list_display = ('username_link', 'email','organization', 'phone_number', 'created_at')
    list_filter = ('role', 'organization', 'created_at', 'user__is_staff', 'user__is_superuser')
    search_fields = ('user__username', 'user__email', 'organization', 'bio', 'phone_number')
    readonly_fields = ('created_at', 'updated_at', 'user_details')
    change_list_template = 'admin/userprofile/userprofile_changelist.html'
    fieldsets = (
        ('User Information', {
            'fields': ('user', 'role', 'bio', 'organization', 'phone_number', 'profile_picture')
        }),
        ('Account Details', {
            'fields': ('user_details', 'created_at', 'updated_at'),
            'classes': ('collapse',)
        })
    )
    actions = ['make_staff', 'remove_staff', 'make_admin', 'remove_admin']
    
    def username_link(self, obj):
        url = reverse('events:view_profile', kwargs={'username': obj.user.username})
        return format_html(
            '<a href="{}" class="profile-link" title="View profile">{}</a> '
            '<a href="/admin/auth/user/{}/change/" class="edit-link" title="Edit user">'
            '<i class="fas fa-edit"></i></a>',
            url, obj.user.username, obj.user.id
        )
    username_link.short_description = 'Username'

    def email(self, obj):
        return obj.user.email
    email.short_description = 'Email'

    def user_details(self, obj):
        user = obj.user
        return format_html(
            '<div class="user-details">' 
            '<p><strong>Username:</strong> {}</p>' 
            '<p><strong>Email:</strong> {}</p>' 
            '<p><strong>Date Joined:</strong> {}</p>' 
            '<p><strong>Last Login:</strong> {}</p>' 
            '<p><strong>Status:</strong> {}</p>' 
            '</div>',
            user.username,
            user.email,
            user.date_joined.strftime('%Y-%m-%d %H:%M:%S'),
            user.last_login.strftime('%Y-%m-%d %H:%M:%S') if user.last_login else 'Never',
            self.get_user_status(user)
        )
    user_details.short_description = 'Account Information'

    def get_user_status(self, user):
        if user.is_superuser:
            return format_html('<span style="color: red;">Superuser</span>')
        elif user.is_staff:
            return format_html('<span style="color: blue;">Staff</span>')
        else:
            return format_html('<span style="color: green;">Regular User</span>')

    def user_actions(self, obj):
        actions = []
        if obj.user.is_staff and not obj.user.is_superuser:
            actions.append(
                format_html(
                    '<button onclick="makeAdmin({})" class="button">Make Admin</button>',
                    obj.user.id
                )
            )
        elif not obj.user.is_staff:
            actions.append(
                format_html(
                    '<button onclick="makeStaff({})" class="button">Make Staff</button>',
                    obj.user.id
                )
            )
        return format_html('&nbsp;'.join(actions))
    user_actions.short_description = 'Actions'
    
    def make_staff(self, request, queryset):
        for profile in queryset:
            if not profile.user.is_superuser:
                profile.user.is_staff = True
                profile.user.save()
        self.message_user(request, 'Selected users have been granted staff access.')
    make_staff.short_description = 'Grant staff access'
    
    def remove_staff(self, request, queryset):
        for profile in queryset:
            if not profile.user.is_superuser:
                profile.user.is_staff = False
                profile.user.save()
        self.message_user(request, 'Selected users have had staff access removed.')
    remove_staff.short_description = 'Remove staff access'
    
    def make_admin(self, request, queryset):
        for profile in queryset:
            profile.user.is_staff = True
            profile.user.is_superuser = True
            profile.user.save()
        self.message_user(request, 'Selected users have been granted admin access.')
    make_admin.short_description = 'Grant admin access'
    
    def remove_admin(self, request, queryset):
        for profile in queryset:
            profile.user.is_superuser = False
            profile.user.save()
        self.message_user(request, 'Selected users have had admin access removed.')
    remove_admin.short_description = 'Remove admin access'

    def delete_model(self, request, obj):
        """Override delete to properly remove both user and profile"""
        user = obj.user
        # Delete the user which will cascade to profile
        user.delete()

    def delete_queryset(self, request, queryset):
        """Override bulk delete to properly remove users and profiles"""
        # Get all associated users
        users = [profile.user for profile in queryset]
        # Delete the users which will cascade to profiles
        for user in users:
            user.delete()
    
    class Media:
        js = ('js/user_profile_admin.js',)

class CallForProposalAdmin(admin.ModelAdmin):
    list_display = ('title', 'event', 'status', 'submission_deadline', 'image_preview', 'created_by')
    list_filter = ('status', 'event', 'submission_deadline')
    search_fields = ('title', 'description')
    readonly_fields = ('created_at', 'updated_at', 'image_preview')
    
    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 50px; max-width: 100px" />', obj.image.url)
        return "No Image"
    
    image_preview.short_description = 'Preview'

class SessionTypeAdmin(admin.ModelAdmin):
    list_display = ('name', 'description')
    search_fields = ('name', 'description')
    ordering = ('name',)


class ProposalAdmin(admin.ModelAdmin):
    list_display = ('title', 'cfp', 'organisation', 'submitter', 'session_type', 'sponsorship', 'status', 'submitted_at')
    list_filter = ('status', 'session_type', 'sponsorship', 'submitted_at', 'cfp__event')
    search_fields = ('title', 'abstract', 'submitter__username', 'organisation', 'contact_number')
    readonly_fields = ('submitted_at', 'updated_at', 'reviewed_at')
    change_list_template = 'admin/proposal/proposal_changelist.html'


class PublicationTypeAdmin(admin.ModelAdmin):
    list_display = ('name', 'icon', 'allowed_extensions')
    search_fields = ('name',)
    ordering = ('name',)
    
    def has_delete_permission(self, request, obj=None):
        # Prevent deletion of built-in types
        if obj and obj.name in ['Presentation', 'Document', 'Research Paper']:
            return False
        return super().has_delete_permission(request, obj)

class PublicationAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'get_type', 'is_public', 'published_at', 'file_link', 'publication_status')
    list_filter = ('is_public', 'published_at')
    search_fields = ('title', 'abstract', 'author__username', 'author__email')
    readonly_fields = ('published_at',)
    actions = ['make_public', 'make_private']
    
    def get_type(self, obj):
        return obj.publication_type.name if obj.publication_type else '-'
    get_type.short_description = 'Type'
    
    def file_link(self, obj):
        if obj.file:
            icon_class = obj.publication_type.icon if obj.publication_type else 'bi-file-earmark'
            return format_html(
                '<a href="{}" target="_blank"><i class="{}"></i> View File</a>',
                obj.file.url,
                icon_class
            )
        return '-'
    file_link.short_description = 'File'

    def publication_status(self, obj):
        if not obj.is_public:
            return format_html('<span style="color: red;">Private</span>')
        
        return format_html('<span style="color: green;">Public</span>')
    publication_status.short_description = 'Status'
    
    def make_public(self, request, queryset):
        made_public = 0
        for pub in queryset:
            if pub.can_be_published():
                pub.is_public = True
                pub.save()
                made_public += 1
                
        if made_public:
            self.message_user(
                request,
                f'{made_public} publication(s) were made public.',
                messages.SUCCESS
            )
        else:
            self.message_user(
                request,
                'No publications were made public. Check publication requirements.',
                messages.WARNING
            )
    make_public.short_description = 'Make selected publications public'
    
    def make_private(self, request, queryset):
        updated = queryset.filter(is_public=True).update(is_public=False)
        if updated:
            self.message_user(
                request,
                f'{updated} publication(s) were made private.',
                messages.SUCCESS
            )
        else:
            self.message_user(
                request,
                'No publications were made private.',
                messages.WARNING
            )
    make_private.short_description = 'Make selected publications private'

    def save_model(self, request, obj, form, change):
        if not change:  # Only set author on creation
            obj.author = request.user
            obj.published_at = timezone.now()
        super().save_model(request, obj, form, change)

class GalleryAdmin(admin.ModelAdmin):
    list_display = ('caption', 'event', 'image_preview')
    list_filter = ('event',)
    search_fields = ('caption', 'event__title')
    change_list_template = 'admin/gallery/gallery_changelist.html'

    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 50px;"/>', obj.image.url)
        return '-'
    image_preview.short_description = 'Preview'
    
    def get_urls(self):
        from django.urls import path
        urls = super().get_urls()
        custom_urls = [
            path('bulk-upload/', self.bulk_upload_view, name='gallery_bulk_upload'),
        ]
        return custom_urls + urls
    
    def bulk_upload_view(self, request):
        from django.shortcuts import render, redirect
        from django.contrib import messages
        from django.utils import timezone
        from django.db.models import Case, When, Value, CharField
        from django.http import JsonResponse, HttpResponseBadRequest
        import json
        import logging
        
        # Set up logging
        logger = logging.getLogger(__name__)
        
        if request.method == 'POST':
            # Determine if this is an AJAX request
            is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'
            
            try:
                # Get event ID and validate
                event_id = request.POST.get('event')
                if not event_id:
                    error_msg = 'No event selected'
                    if is_ajax:
                        return JsonResponse({'status': 'error', 'message': error_msg}, status=400)
                    messages.error(request, error_msg)
                    return redirect('.')
                
                # Get images and validate
                images = request.FILES.getlist('images')
                if not images:
                    error_msg = 'No images selected'
                    if is_ajax:
                        return JsonResponse({'status': 'error', 'message': error_msg}, status=400)
                    messages.error(request, error_msg)
                    return redirect('.')
                
                # Get event
                try:
                    event = Event.objects.get(id=event_id)
                except Event.DoesNotExist:
                    error_msg = 'Selected event does not exist'
                    if is_ajax:
                        return JsonResponse({'status': 'error', 'message': error_msg}, status=400)
                    messages.error(request, error_msg)
                    return redirect('.')
                
                # Create gallery images
                created_count = 0
                skipped_count = 0
                
                # Get existing original filenames for this event to avoid duplicates
                existing_filenames = set(
                    Gallery.objects.filter(event=event)
                    .exclude(original_filename__isnull=True)
                    .values_list('original_filename', flat=True)
                )
                
                for image in images:
                    # Check if an image with this filename already exists
                    filename = image.name
                    if filename in existing_filenames:
                        skipped_count += 1
                        continue
                        
                    # Create new gallery image
                    Gallery.objects.create(
                        event=event,
                        image=image,
                        caption=f'Event photo - {event.title}',
                        original_filename=filename
                    )
                    created_count += 1
                    # Add to existing filenames to prevent duplicates within this batch
                    existing_filenames.add(filename)
                
                # Log success
                logger.info(f'Bulk upload: {created_count} images uploaded, {skipped_count} skipped for event {event.title} (ID: {event.id})')
                
                # Return appropriate response
                if skipped_count > 0:
                    success_msg = f'{created_count} images uploaded successfully! ({skipped_count} duplicate images were skipped)'
                else:
                    success_msg = f'{created_count} images uploaded successfully!'
                    
                if is_ajax:
                    return JsonResponse({
                        'status': 'success',
                        'message': success_msg
                    })
                messages.success(request, success_msg)
                return redirect('..')
                
            except Exception as e:
                # Log the error
                logger.error(f'Bulk upload error: {str(e)}')
                
                # Return appropriate error response
                error_msg = 'An error occurred during upload'
                if is_ajax:
                    return JsonResponse({'status': 'error', 'message': error_msg}, status=500)
                messages.error(request, error_msg)
                return redirect('.')
        
        now = timezone.now()
        two_hours_ago = now - timezone.timedelta(hours=2)
        
        # Update event statuses based on time rules
        Event.objects.filter(date_time__gt=now).update(status='upcoming')
        Event.objects.filter(date_time__gt=two_hours_ago, date_time__lte=now).update(status='ongoing')
        Event.objects.filter(date_time__lte=two_hours_ago).update(status='archived')
        
        events = Event.objects.order_by('-date_time')
        
        context = {
            'events': events,
            'title': 'Bulk Upload Images',
            'has_file_field': True
        }
        
        return render(request, 'admin/gallery/bulk_upload.html', context)

class CarouselImageAdmin(admin.ModelAdmin):
    list_display = ('title', 'image_preview', 'is_active', 'order', 'created_at')
    list_editable = ('is_active', 'order')
    list_filter = ('is_active', 'created_at')
    search_fields = ('title', 'caption')
    ordering = ['order', '-created_at']

    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 50px;"/>', obj.image.url)
        return '-'
    image_preview.short_description = 'Preview'

    class Media:
        css = {
            'all': ('css/admin_custom.css',)
        }

class RoleAdmin(admin.ModelAdmin):
    list_display = ('name', 'get_permissions')
    readonly_fields = ('permissions',)
    
    def get_permissions(self, obj):
        if obj.permissions:
            return ', '.join([k for k, v in obj.permissions.items() if v])
        return '-'
    get_permissions.short_description = 'Active Permissions'

@admin.register(Sponsor)
class SponsorAdmin(admin.ModelAdmin):
    list_display = ['name', 'website', 'is_active', 'order']
    list_editable = ['is_active', 'order']
    list_filter = ['is_active', 'events']
    search_fields = ['name', 'website']
    filter_horizontal = ['events']
    ordering = ['order', 'name']

class SectionImageAdmin(admin.ModelAdmin):
    list_display = ('title', 'section', 'image_preview', 'is_active', 'created_at')
    list_editable = ('is_active',)
    list_filter = ('section', 'is_active', 'created_at')
    search_fields = ('title', 'caption', 'section')
    ordering = ['section', '-created_at']
    
    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'section':
            kwargs['choices'] = [
                ('join_community', 'Join Community Section'),
                # ('about', 'About Section'),
                # ('hero', 'Hero Section'),
                # ('event', 'Event Section'),
            ]
        return super().formfield_for_dbfield(db_field, **kwargs)
    
    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 50px; max-width: 100px" />', obj.image.url)
        return "No Image"
    
    image_preview.short_description = 'Preview'
    
    class Media:
        css = {
            'all': ('css/admin_custom.css',)
        }

# Register the models with their custom admin classes
admin_site.register(Event, EventAdmin)
admin_site.register(Speaker, SpeakerAdmin)
admin_site.register(Agenda, AgendaAdmin)
admin_site.register(CallForProposal, CallForProposalAdmin)
admin_site.register(SessionType, SessionTypeAdmin)
admin_site.register(Proposal, ProposalAdmin)
admin_site.register(Gallery, GalleryAdmin)
admin_site.register(Registration, RegistrationAdmin)
admin_site.register(UserProfile, UserProfileAdmin)
admin_site.register(Role, RoleAdmin)
admin_site.register(PublicationType, PublicationTypeAdmin)
admin_site.register(Publication, PublicationAdmin)
admin_site.register(CarouselImage, CarouselImageAdmin)
admin_site.register(Sponsor, SponsorAdmin)
admin_site.register(SectionImage, SectionImageAdmin)