from django.contrib import admin
from django.utils.html import format_html
from django.urls import reverse, path
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib import messages
from .models import (
    User, Language, Category, CategoryTranslation, Exhibition, ExhibitionTranslation,
    Artwork, ArtworkTranslation, Media, AudioGuide, Visit, Favorite, Comment,
    Statistics, Artwork3DView, ArtworkDetailPoint, Artwork3DSession, RoomVisit, VirtualTourSession, ArtworkHotspot,
    RoomConnection, VirtualRoom
)
import io
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm


# ==================== INLINES ====================

class RoomConnectionInline(admin.TabularInline):
    model = RoomConnection
    fk_name = 'from_room'
    extra = 1
    fields = ['to_room', 'label', 'hotspot_x', 'hotspot_y', 'icon']
    verbose_name = "Connexion vers une autre salle"
    verbose_name_plural = "Connexions (Portes/Passages)"


class ArtworkHotspotInline(admin.TabularInline):
    model = ArtworkHotspot
    extra = 1
    fields = ['artwork', 'hotspot_x', 'hotspot_y', 'animation_type', 'is_active']
    autocomplete_fields = ['artwork']
    verbose_name = "Œuvre visible dans cette salle"
    verbose_name_plural = "Œuvres visibles"


# ==================== VIRTUAL ROOM ADMIN ====================

@admin.register(VirtualRoom)
class VirtualRoomAdmin(admin.ModelAdmin):
    list_display = ['name', 'floor', 'order', 'get_preview', 'artworks_count', 'connections_count', 'is_entrance',
                    'is_active']
    list_filter = ['floor', 'is_active', 'is_entrance']
    search_fields = ['name', 'slug']
    prepopulated_fields = {'slug': ('name',)}
    inlines = [RoomConnectionInline, ArtworkHotspotInline]

    fieldsets = (
        ('Informations de base', {
            'fields': ('name', 'slug', 'description', 'floor', 'order')
        }),
        ('Image 360°', {
            'fields': ('panorama_image', 'thumbnail'),
            'description': 'Image panoramique équirectangulaire (ratio 2:1, min 4096x2048px)'
        }),
        ('Audio', {
            'fields': ('ambient_audio',)
        }),
        ('Options', {
            'fields': ('is_entrance', 'is_active')
        }),
    )

    def get_preview(self, obj):
        if obj.panorama_image:
            return format_html(
                '<img src="{}" width="150" style="border-radius: 8px;" />',
                obj.panorama_image.url
            )
        return 'Pas d\'image'

    get_preview.short_description = 'Aperçu panorama'

    def artworks_count(self, obj):
        count = obj.artwork_hotspots.count()
        if count > 0:
            return format_html(
                '<span style="color: green; font-weight: bold;">🎨 {}</span>',
                count
            )
        return format_html('<span style="color: gray;">0</span>')

    artworks_count.short_description = 'Œuvres'

    def connections_count(self, obj):
        count = obj.exits.count()
        if count > 0:
            return format_html(
                '<span style="color: blue; font-weight: bold;">🚪 {}</span>',
                count
            )
        return format_html('<span style="color: gray;">0</span>')

    connections_count.short_description = 'Connexions'


# ==================== ROOM CONNECTION ADMIN ====================

@admin.register(RoomConnection)
class RoomConnectionAdmin(admin.ModelAdmin):
    list_display = ['from_room', 'arrow', 'to_room', 'label', 'icon', 'position']
    list_filter = ['icon', 'from_room__floor']
    search_fields = ['from_room__name', 'to_room__name', 'label']

    fieldsets = (
        ('Salles', {
            'fields': ('from_room', 'to_room', 'label')
        }),
        ('Position du hotspot', {
            'fields': ('hotspot_x', 'hotspot_y', 'icon'),
            'description': 'Position dans l\'image 360° (yaw: 0-360°, pitch: -90 à 90°)'
        }),
    )

    def arrow(self, obj):
        return format_html('<i class="fas fa-arrow-right" style="color: #FF5801;"></i>')

    arrow.short_description = ''

    def position(self, obj):
        return f"X: {obj.hotspot_x}°, Y: {obj.hotspot_y}°"

    position.short_description = 'Position'


# ==================== ARTWORK HOTSPOT ADMIN ====================

@admin.register(ArtworkHotspot)
class ArtworkHotspotAdmin(admin.ModelAdmin):
    list_display = ['artwork', 'room', 'position', 'animation_type', 'is_active']
    list_filter = ['room', 'animation_type', 'is_active']
    search_fields = ['artwork__reference_code', 'room__name']
    autocomplete_fields = ['artwork', 'room']

    fieldsets = (
        ('Œuvre et Salle', {
            'fields': ('room', 'artwork')
        }),
        ('Position', {
            'fields': ('hotspot_x', 'hotspot_y', 'animation_type'),
            'description': 'Position dans l\'image 360° (yaw: 0-360°, pitch: -90 à 90°)'
        }),
        ('Options', {
            'fields': ('is_active',)
        }),
    )

    def position(self, obj):
        return f"X: {obj.hotspot_x}°, Y: {obj.hotspot_y}°"

    position.short_description = 'Position'


# ==================== VIRTUAL TOUR SESSION ADMIN ====================

@admin.register(VirtualTourSession)
class VirtualTourSessionAdmin(admin.ModelAdmin):
    list_display = ['session_key_short', 'user', 'device_type', 'rooms_visited_count', 'duration_formatted',
                    'started_at']
    list_filter = ['device_type', 'started_at']
    search_fields = ['session_key', 'user__username']
    readonly_fields = ['started_at', 'ended_at', 'duration', 'session_key']

    fieldsets = (
        ('Session', {
            'fields': ('user', 'session_key', 'device_type')
        }),
        ('Durée', {
            'fields': ('started_at', 'ended_at', 'duration')
        }),
    )

    def session_key_short(self, obj):
        return f"{obj.session_key[:8]}..."

    session_key_short.short_description = 'Session'

    def rooms_visited_count(self, obj):
        return obj.rooms_visited.count()

    rooms_visited_count.short_description = 'Salles visitées'

    def duration_formatted(self, obj):
        if obj.duration:
            minutes = obj.duration // 60
            seconds = obj.duration % 60
            return f"{minutes}m {seconds}s"
        return '-'

    duration_formatted.short_description = 'Durée'


# ==================== ROOM VISIT ADMIN ====================

@admin.register(RoomVisit)
class RoomVisitAdmin(admin.ModelAdmin):
    list_display = ['session', 'room', 'entered_at', 'duration_formatted']
    list_filter = ['room', 'entered_at']
    search_fields = ['session__session_key', 'room__name']
    readonly_fields = ['entered_at']

    def duration_formatted(self, obj):
        if obj.duration:
            minutes = obj.duration // 60
            seconds = obj.duration % 60
            return f"{minutes}m {seconds}s"
        return '-'

    duration_formatted.short_description = 'Durée'
# ==================== INLINE ADMINS ====================

class AudioGuideInline(admin.TabularInline):
    model = AudioGuide
    extra = 1
    fields = ['audio_file', 'duration', 'narrator']
    verbose_name = "Audioguide"
    verbose_name_plural = "Audioguides"


class ArtworkTranslationInline(admin.StackedInline):
    model = ArtworkTranslation
    extra = 0
    fields = ['language', 'title', 'artist', 'description', 'historical_context', 'cultural_significance']
    classes = ['collapse']

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "language":
            kwargs["queryset"] = Language.objects.filter(is_active=True).order_by('order')
        return super().formfield_for_foreignkey(db_field, request, **kwargs)


class MediaInline(admin.TabularInline):
    model = Media
    extra = 1
    fields = ['media_type', 'file', 'caption', 'order']

    def formfield_for_dbfield(self, db_field, **kwargs):
        if db_field.name == 'is_featured':
            kwargs['help_text'] = '⭐ Cocher pour définir comme image à la une'
        return super().formfield_for_dbfield(db_field, **kwargs)


class Artwork3DViewInline(admin.StackedInline):
    model = Artwork3DView
    extra = 0
    fields = ['panorama_image', 'initial_yaw', 'initial_pitch', 'initial_fov',
              'auto_rotate', 'auto_rotate_speed', 'ambient_audio', 'is_active']
    classes = ['collapse']


class ArtworkDetailPointInline(admin.TabularInline):
    model = ArtworkDetailPoint
    extra = 1
    fields = ['title', 'pitch', 'yaw', 'point_type', 'detail_image', 'order', 'is_active']


# ==================== ARTWORK TRANSLATION ADMIN ====================

@admin.register(ArtworkTranslation)
class ArtworkTranslationAdmin(admin.ModelAdmin):
    list_display = ['artwork', 'language', 'title', 'artist', 'has_audio', 'is_complete']
    list_filter = ['language']
    search_fields = ['artwork__reference_code', 'title', 'artist']
    inlines = [AudioGuideInline]

    fieldsets = (
        ('Œuvre', {
            'fields': ('artwork',)
        }),
        ('Langue', {
            'fields': ('language',)
        }),
        ('Informations principales', {
            'fields': ('title', 'artist')
        }),
        ('Description', {
            'fields': ('description',)
        }),
        ('Contexte (optionnel)', {
            'fields': ('historical_context', 'cultural_significance'),
            'classes': ('collapse',)
        }),
    )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "language":
            kwargs["queryset"] = Language.objects.filter(is_active=True).order_by('order')
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

    def has_audio(self, obj):
        if obj.audio_guides.exists():
            audio = obj.audio_guides.first()
            return format_html(
                '<span style="color: green;">✓</span> <a href="{}" target="_blank">Écouter</a>',
                audio.audio_file.url
            )
        return format_html('<span style="color: red;">✗</span>')

    has_audio.short_description = 'Audio'

    def is_complete(self, obj):
        return obj.is_complete()

    is_complete.boolean = True
    is_complete.short_description = 'Complet'


# ==================== ARTWORK ADMIN (Principal) ====================

@admin.register(Artwork)
class ArtworkAdmin(admin.ModelAdmin):
    list_display = [
        'reference_code', 'get_title', 'category', 'status', 'is_published',
        'view_count', 'favorites_count', 'translations_count', 'has_3d_indicator', 'action_buttons'
    ]
    list_filter = ['status', 'is_published', 'is_featured', 'category', 'created_at']
    search_fields = ['reference_code', 'translations__title', 'translations__artist']
    readonly_fields = ['qr_code_preview', 'view_count', 'favorites_count', 'created_at', 'updated_at']
    inlines = [ArtworkTranslationInline, MediaInline, Artwork3DViewInline]

    fieldsets = (
        ('Informations de base', {
            'fields': ('reference_code', 'category', 'status', 'is_published', 'is_featured')
        }),
        ('Détails', {
            'fields': ('origin', 'period', 'acquisition_date')
        }),
        ('QR Code', {
            'fields': ('qr_code', 'qr_code_preview'),
            'description': 'Le QR code sera généré automatiquement lors de la sauvegarde'
        }),
        ('Statistiques', {
            'fields': ('view_count', 'favorites_count', 'created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )

    actions = [
        'publish_artworks',
        'unpublish_artworks',
        'regenerate_qr_codes',
        'generate_qr_labels',
    ]

    def get_title(self, obj):
        translation = obj.translations.first()
        return translation.title if translation else obj.reference_code

    get_title.short_description = 'Titre'

    def translations_count(self, obj):
        count = obj.translations.count()
        audio_count = sum(1 for t in obj.translations.all() if t.audio_guides.exists())
        return format_html(
            '<span title="Traductions avec audio">{}/{} <i class="fas fa-headphones"></i></span>',
            audio_count, count
        )

    translations_count.short_description = 'Traductions'

    def has_3d_indicator(self, obj):
        if hasattr(obj, 'view_3d') and obj.view_3d.is_active:
            return format_html('<span style="color: green; font-weight: bold;">✓ 3D</span>')
        return format_html('<span style="color: gray;">-</span>')

    has_3d_indicator.short_description = 'Vue 3D'

    def qr_code_preview(self, obj):
        if obj.qr_code:
            return format_html(
                '<img src="{}" width="100" height="100" /><br>'
                '<a href="{}" class="button" target="_blank">Télécharger</a>',
                obj.qr_code.url,
                obj.qr_code.url
            )
        return "Pas de QR code"

    qr_code_preview.short_description = 'QR Code'

    def action_buttons(self, obj):
        buttons = f'<a class="button" href="{reverse("artwork_detail", args=[obj.id])}" target="_blank">👁️ Voir</a> '

        # Lien vers les traductions et audios
        trans_url = reverse('admin:artworks_artworktranslation_changelist') + f'?artwork__id__exact={obj.id}'
        buttons += f'<a class="button" href="{trans_url}" style="background: #3b82f6; color: white;">🌍 Traductions & Audios</a> '

        buttons += f'<a class="button" href="{reverse("admin:download_qr_pdf", args=[obj.id])}">📄 QR PDF</a> '

        if hasattr(obj, 'view_3d') and obj.view_3d.is_active:
            buttons += f'<a class="button" href="{reverse("artwork_3d_view", args=[obj.id])}" target="_blank" style="background: #10b981; color: white;">🎮 Vue 3D</a>'

        return format_html(buttons)

    action_buttons.short_description = 'Actions'

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('<uuid:artwork_id>/qr-pdf/', self.admin_site.admin_view(self.download_qr_pdf),
                 name='download_qr_pdf'),
            path('generate-all-qr/', self.admin_site.admin_view(self.generate_all_qr),
                 name='generate_all_qr'),
        ]
        return custom_urls + urls

    def download_qr_pdf(self, request, artwork_id):
        """Génère un PDF avec le QR code pour impression"""
        artwork = Artwork.objects.get(id=artwork_id)

        buffer = io.BytesIO()
        p = canvas.Canvas(buffer, pagesize=A4)
        width, height = A4

        # Titre
        p.setFont("Helvetica-Bold", 24)
        p.drawCentredString(width / 2, height - 3 * cm, "QR Code - Œuvre")

        # Référence
        p.setFont("Helvetica-Bold", 18)
        p.drawCentredString(width / 2, height - 5 * cm, artwork.reference_code)

        # Titre de l'œuvre
        translation = artwork.translations.first()
        if translation:
            p.setFont("Helvetica", 14)
            p.drawCentredString(width / 2, height - 6.5 * cm, translation.title)

        # QR Code
        if artwork.qr_code:
            qr_path = artwork.qr_code.path
            p.drawImage(qr_path, width / 2 - 6 * cm, height - 18 * cm, 12 * cm, 12 * cm)

        # Instructions
        p.setFont("Helvetica", 10)
        p.drawCentredString(width / 2, 4 * cm, "Scannez ce code pour accéder aux informations de l'œuvre")

        # Ligne de coupe
        p.setDash(3, 3)
        p.rect(2 * cm, 2 * cm, width - 4 * cm, height - 4 * cm)

        p.showPage()
        p.save()

        buffer.seek(0)
        response = HttpResponse(buffer, content_type='application/pdf')
        response['Content-Disposition'] = f'attachment; filename="qr_code_{artwork.reference_code}.pdf"'
        return response

    def generate_all_qr(self, request):
        """Génère tous les QR codes manquants"""
        artworks = Artwork.objects.filter(qr_code='')
        count = 0

        for artwork in artworks:
            try:
                artwork.generate_qr_code()
                artwork.save(update_fields=['qr_code'])
                count += 1
            except Exception as e:
                messages.error(request, f'Erreur pour {artwork.reference_code}: {str(e)}')

        messages.success(request, f'{count} QR codes générés avec succès')
        return redirect('admin:artworks_artwork_changelist')

    # Actions en masse
    def publish_artworks(self, request, queryset):
        queryset.update(is_published=True, status='published')
        self.message_user(request, f'{queryset.count()} œuvres publiées')

    publish_artworks.short_description = "✅ Publier les œuvres sélectionnées"

    def unpublish_artworks(self, request, queryset):
        queryset.update(is_published=False, status='draft')
        self.message_user(request, f'{queryset.count()} œuvres dépubliées')

    unpublish_artworks.short_description = "❌ Dépublier les œuvres sélectionnées"

    def regenerate_qr_codes(self, request, queryset):
        count = 0
        for artwork in queryset:
            try:
                artwork.generate_qr_code()
                artwork.save(update_fields=['qr_code'])
                count += 1
            except Exception as e:
                messages.error(request, f'Erreur pour {artwork.reference_code}: {str(e)}')

        self.message_user(request, f'{count} QR codes régénérés')

    regenerate_qr_codes.short_description = "🔄 Régénérer les QR codes"

    def generate_qr_labels(self, request, queryset):
        """Génère un PDF avec tous les QR codes pour impression en série"""
        buffer = io.BytesIO()
        p = canvas.Canvas(buffer, pagesize=A4)
        width, height = A4

        # 4 QR codes par page (2x2)
        qr_size = 8 * cm
        margin = 2 * cm

        artworks = list(queryset)
        for i, artwork in enumerate(artworks):
            if i > 0 and i % 4 == 0:
                p.showPage()

            # Position
            row = (i % 4) // 2
            col = (i % 4) % 2
            x = margin + col * (width / 2 - margin)
            y = height - margin - (row + 1) * (height / 2 - margin)

            # Référence
            p.setFont("Helvetica-Bold", 12)
            p.drawString(x, y + qr_size + 0.5 * cm, artwork.reference_code)

            # QR Code
            if artwork.qr_code:
                p.drawImage(artwork.qr_code.path, x, y, qr_size, qr_size)

        p.showPage()
        p.save()

        buffer.seek(0)
        response = HttpResponse(buffer, content_type='application/pdf')
        response['Content-Disposition'] = 'attachment; filename="qr_labels_batch.pdf"'
        return response

    generate_qr_labels.short_description = "📋 Générer étiquettes QR (PDF)"


# ==================== AUTRES ADMINS ====================

@admin.register(Media)
class MediaAdmin(admin.ModelAdmin):
    list_display = ['artwork', 'media_type', 'get_preview', 'caption', 'order', 'uploaded_at']
    list_filter = ['media_type', 'uploaded_at']
    search_fields = ['artwork__reference_code', 'caption']

    def get_preview(self, obj):
        if obj.media_type == 'image' and obj.file:
            return format_html('<img src="{}" width="100" />', obj.file.url)
        elif obj.media_type == 'video' and obj.thumbnail:
            return format_html('<img src="{}" width="100" />', obj.thumbnail.url)
        return '-'

    get_preview.short_description = 'Aperçu'


@admin.register(Artwork3DView)
class Artwork3DViewAdmin(admin.ModelAdmin):
    list_display = ['artwork', 'get_preview', 'auto_rotate', 'is_active', 'created_at']
    list_filter = ['is_active', 'auto_rotate', 'created_at']
    search_fields = ['artwork__reference_code']
    inlines = [ArtworkDetailPointInline]

    fieldsets = (
        ('Œuvre', {
            'fields': ('artwork',)
        }),
        ('Image 360°', {
            'fields': ('panorama_image',),
            'description': 'Image panoramique équirectangulaire (ratio 2:1, min 4096x2048px)'
        }),
        ('Position initiale', {
            'fields': ('initial_yaw', 'initial_pitch', 'initial_fov')
        }),
        ('Options', {
            'fields': ('allow_zoom', 'allow_rotation', 'show_controls',
                       'auto_rotate', 'auto_rotate_speed')
        }),
        ('Audio', {
            'fields': ('ambient_audio',)
        }),
        ('Statut', {
            'fields': ('is_active',)
        }),
    )

    def get_preview(self, obj):
        if obj.panorama_image:
            return format_html('<img src="{}" width="200" />', obj.panorama_image.url)
        return 'Pas d\'image'

    get_preview.short_description = 'Aperçu panorama'


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    list_display = ['username', 'email', 'role', 'is_active', 'date_joined']
    list_filter = ['role', 'is_active']
    search_fields = ['username', 'email']


@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
    list_display = ['name', 'slug', 'get_icon', 'order']
    prepopulated_fields = {'slug': ('name',)}

    def get_icon(self, obj):
        if obj.icon:
            return format_html('<img src="{}" width="40" />', obj.icon.url)
        return '-'

    get_icon.short_description = 'Icône'


@admin.register(Exhibition)
class ExhibitionAdmin(admin.ModelAdmin):
    list_display = ['title', 'start_date', 'end_date', 'is_active', 'is_ongoing']
    list_filter = ['is_active', 'start_date']
    search_fields = ['title']
    prepopulated_fields = {'slug': ('title',)}

    def is_ongoing(self, obj):
        return obj.is_ongoing()

    is_ongoing.boolean = True
    is_ongoing.short_description = 'En cours'


@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
    list_display = ['artwork', 'user', 'get_excerpt', 'is_approved', 'is_flagged', 'created_at']
    list_filter = ['is_approved', 'is_flagged', 'created_at']
    search_fields = ['user__username', 'content']
    actions = ['approve_comments', 'reject_comments']

    def get_excerpt(self, obj):
        return obj.content[:50] + '...' if len(obj.content) > 50 else obj.content

    get_excerpt.short_description = 'Contenu'

    def approve_comments(self, request, queryset):
        queryset.update(is_approved=True, is_flagged=False)
        self.message_user(request, f'{queryset.count()} commentaires approuvés')

    approve_comments.short_description = "Approuver"

    def reject_comments(self, request, queryset):
        count = queryset.count()
        queryset.delete()
        self.message_user(request, f'{count} commentaires supprimés')

    reject_comments.short_description = "Supprimer"


@admin.register(Statistics)
class StatisticsAdmin(admin.ModelAdmin):
    list_display = ['date', 'total_visits', 'unique_visitors', 'qr_scans', 'most_viewed_artwork']
    list_filter = ['date']
    readonly_fields = ['date', 'total_visits', 'unique_visitors', 'qr_scans',
                       'most_viewed_artwork', 'avg_time_per_artwork']


@admin.register(Language)
class LanguageAdmin(admin.ModelAdmin):
    list_display = ['code', 'name', 'native_name', 'is_active', 'order']
    list_filter = ['is_active']
    search_fields = ['code', 'name']
    ordering = ['order', 'code']
    list_editable = ['order', 'is_active']


# Configuration du site admin
admin.site.site_header = "Administration MCN Museum"
admin.site.site_title = "MCN Museum"
admin.site.index_title = "Gestion du Musée des Civilisations Noires"