from django.contrib import admin
from django.utils.html import format_html
from django.contrib import messages
from django.utils import timezone
from django.http import FileResponse, HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import path, reverse
from django.conf import settings
import os
from datetime import datetime
from .models import DatabaseBackup
from .views import BackupManager


@admin.register(DatabaseBackup)
class DatabaseBackupAdmin(admin.ModelAdmin):
    list_display = ['name', 'status_badge', 'backup_type', 'file_size_display', 'download_link', 'created_by', 'created_at', 'completed_at']
    list_filter = ['status', 'backup_type', 'created_at']
    search_fields = ['name', 'notes', 'error_message']
    readonly_fields = ['file_path', 'file_size', 'status', 'created_by', 'created_at', 'completed_at', 'error_message', 'file_size_display_field']
    
    fieldsets = (
        ('Temel Bilgiler', {
            'fields': ('name', 'backup_type', 'status', 'notes')
        }),
        ('Yedek Dosya Bilgileri', {
            'fields': ('file_path', 'file_size_display_field')
        }),
        ('Zaman Bilgileri', {
            'fields': ('created_by', 'created_at', 'completed_at')
        }),
        ('Hata Bilgileri', {
            'fields': ('error_message',),
            'classes': ('collapse',)
        }),
    )
    
    actions = ['create_new_backup', 'restore_selected_backup', 'download_backup', 'delete_backup_files']

    def status_badge(self, obj):
        """Durum için renkli badge gösterir"""
        colors = {
            'pending': '#FFA500',
            'in_progress': '#2196F3',
            'completed': '#4CAF50',
            'failed': '#F44336',
        }
        color = colors.get(obj.status, '#999')
        return format_html(
            '<span style="background-color: {}; color: white; padding: 3px 10px; border-radius: 3px; font-weight: bold;">{}</span>',
            color,
            obj.get_status_display()
        )
    status_badge.short_description = 'Durum'
    
    def file_size_display(self, obj):
        """Dosya boyutunu gösterir"""
        return obj.get_file_size_display()
    file_size_display.short_description = 'Dosya Boyutu'
    
    def file_size_display_field(self, obj):
        """Read-only field için dosya boyutu"""
        return obj.get_file_size_display()
    file_size_display_field.short_description = 'Dosya Boyutu'
    
    def download_link(self, obj):
        """İndir butonu gösterir"""
        if obj.file_path and obj.status == 'completed' and os.path.isfile(obj.file_path):
            url = f'/admin/backup/databasebackup/{obj.pk}/download/'
            return format_html(
                '<a href="{}" class="button" style="background-color: #4CAF50; color: white; padding: 5px 10px; '
                'text-decoration: none; border-radius: 3px; display: inline-block;">📥 İndir</a>',
                url
            )
        return format_html('<span style="color: {};">-</span>', '#999')
    download_link.short_description = 'İndir'

    def get_urls(self):
        """Admin için özel URL'ler ekler"""
        urls = super().get_urls()
        custom_urls = [
            path('create-backup/', self.admin_site.admin_view(self.create_backup_view), name='backup_create'),
            path('upload-backup/', self.admin_site.admin_view(self.upload_backup_view), name='backup_upload'),
            path('<int:backup_id>/download/', self.admin_site.admin_view(self.download_backup_file), name='backup_download'),
        ]
        return custom_urls + urls

    def changelist_view(self, request, extra_context=None):
        """Change list view'a ekstra context ekler"""
        extra_context = extra_context or {}
        extra_context['show_create_backup_button'] = True
        extra_context['show_upload_backup_button'] = True
        return super().changelist_view(request, extra_context=extra_context)

    def create_backup_view(self, request):
        """Yeni yedek oluşturma view'i"""
        from django.shortcuts import redirect
        from django.urls import reverse

        # Yeni bir backup objesi oluştur
        timestamp = timezone.now().strftime('%Y%m%d_%H%M%S')
        backup = DatabaseBackup.objects.create(
            name=f"Manuel Yedek - {timezone.now().strftime('%Y-%m-%d %H:%M:%S')}",
            backup_type='manual',
            created_by=request.user,
            status='pending'
        )

        # Yedekleme işlemini başlat
        manager = BackupManager()
        success, message = manager.create_backup(backup)

        if success:
            self.message_user(request, message, messages.SUCCESS)
        else:
            self.message_user(request, message, messages.ERROR)

        # Liste sayfasına yönlendir
        return redirect(reverse('admin:backup_databasebackup_changelist'))

    def upload_backup_view(self, request):
        """Yedek dosyası yükleme view'i"""
        if request.method == 'POST':
            uploaded_file = request.FILES.get('backup_file')
            backup_name = request.POST.get('backup_name', '')

            if not uploaded_file:
                self.message_user(request, "Lütfen bir dosya seçin", messages.ERROR)
                return redirect(reverse('admin:backup_upload'))

            # Dosya uzantısı kontrolü
            if not uploaded_file.name.endswith('.sql'):
                self.message_user(request, "Sadece .sql uzantılı dosyalar yüklenebilir", messages.ERROR)
                return redirect(reverse('admin:backup_upload'))

            # Dosya boyutu kontrolü (max 500MB)
            max_size = 500 * 1024 * 1024  # 500MB in bytes
            if uploaded_file.size > max_size:
                self.message_user(request, "Dosya çok büyük. Maksimum 500MB olabilir", messages.ERROR)
                return redirect(reverse('admin:backup_upload'))

            try:
                # Backup klasörünü kontrol et
                manager = BackupManager()
                backup_dir = manager.backup_dir

                # Dosya adını oluştur (timestamp ekle)
                timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                original_name = os.path.splitext(uploaded_file.name)[0]
                filename = f"uploaded_{original_name}_{timestamp}.sql"
                file_path = os.path.join(backup_dir, filename)

                # Dosyayı kaydet
                with open(file_path, 'wb+') as destination:
                    for chunk in uploaded_file.chunks():
                        destination.write(chunk)

                # Veritabanı kaydı oluştur
                if not backup_name:
                    backup_name = f"Yüklenen Yedek - {uploaded_file.name}"

                backup = DatabaseBackup.objects.create(
                    name=backup_name,
                    file_path=file_path,
                    file_size=uploaded_file.size,
                    status='completed',
                    backup_type='manual',
                    created_by=request.user,
                    completed_at=timezone.now(),
                    notes=f"Dosya yüklendi: {uploaded_file.name}"
                )

                self.message_user(
                    request,
                    f"Yedek dosyası başarıyla yüklendi: {uploaded_file.name} ({backup.get_file_size_display()})",
                    messages.SUCCESS
                )
                return redirect(reverse('admin:backup_databasebackup_changelist'))

            except Exception as e:
                self.message_user(request, f"Dosya yüklenirken hata oluştu: {str(e)}", messages.ERROR)
                return redirect(reverse('admin:backup_upload'))

        # GET request - form göster
        context = {
            **self.admin_site.each_context(request),
            'title': 'Yedek Dosyası Yükle',
            'opts': self.model._meta,
            'has_view_permission': self.has_view_permission(request),
        }
        return render(request, 'admin/backup/upload_backup.html', context)

    def download_backup_file(self, request, backup_id):
        """Yedek dosyasını indirir"""
        backup = get_object_or_404(DatabaseBackup, pk=backup_id)

        if not backup.file_path:
            self.message_user(request, "Yedek dosyası bulunamadı", messages.ERROR)
            return HttpResponse("Dosya bulunamadı", status=404)

        if not os.path.isfile(backup.file_path):
            self.message_user(request, "Yedek dosyası disk üzerinde bulunamadı", messages.ERROR)
            return HttpResponse("Dosya disk üzerinde bulunamadı", status=404)

        # Dosyayı indir
        try:
            response = FileResponse(open(backup.file_path, 'rb'), content_type='application/sql')
            filename = os.path.basename(backup.file_path)
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
        except Exception as e:
            return HttpResponse(f"Dosya indirilemedi: {str(e)}", status=500)

    def save_model(self, request, obj, form, change):
        """Model kaydedilirken created_by alanını otomatik doldur"""
        if not change:  # Yeni kayıt
            obj.created_by = request.user
        super().save_model(request, obj, form, change)
    
    def create_new_backup(self, request, queryset):
        """Yeni bir yedek oluşturur"""
        # Yeni bir backup objesi oluştur
        timestamp = timezone.now().strftime('%Y-%m-%d %H:%M:%S')
        backup = DatabaseBackup.objects.create(
            name=f"Manuel Yedek - {timestamp}",
            backup_type='manual',
            created_by=request.user,
            status='pending'
        )
        
        # Yedekleme işlemini başlat
        manager = BackupManager()
        success, message = manager.create_backup(backup)
        
        if success:
            self.message_user(request, message, messages.SUCCESS)
        else:
            self.message_user(request, message, messages.ERROR)
    
    create_new_backup.short_description = "Yeni Yedek Oluştur"
    
    def restore_selected_backup(self, request, queryset):
        """Seçili yedeği geri yükler"""
        if queryset.count() != 1:
            self.message_user(
                request,
                "Lütfen geri yüklemek için sadece bir yedek seçin",
                messages.WARNING
            )
            return
        
        backup = queryset.first()
        
        if backup.status != 'completed':
            self.message_user(
                request,
                "Sadece tamamlanmış yedekler geri yüklenebilir",
                messages.WARNING
            )
            return
        
        if not backup.file_path:
            self.message_user(
                request,
                "Yedek dosya yolu bulunamadı",
                messages.ERROR
            )
            return
        
        # Restore işlemi (migration'lar da dahil)
        manager = BackupManager()
        success, message = manager.restore_backup(backup.file_path)
        
        if success:
            # Otomatik migration çalıştır
            try:
                from django.core.management import call_command
                import io
                call_command('migrate', '--noinput', stdout=io.StringIO(), stderr=io.StringIO())
                self.message_user(request, f"{message} Migration'lar uygulandı. Sayfayı yenileyin.", messages.SUCCESS)
            except:
                self.message_user(request, f"{message} Sayfayı yenileyin.", messages.SUCCESS)
        else:
            self.message_user(request, message, messages.ERROR)
    
    restore_selected_backup.short_description = "Seçili Yedeği Geri Yükle"
    
    def download_backup(self, request, queryset):
        """Seçili yedeği indirir"""
        if queryset.count() != 1:
            self.message_user(
                request,
                "Lütfen indirmek için sadece bir yedek seçin",
                messages.WARNING
            )
            return

        backup = queryset.first()

        if backup.status != 'completed':
            self.message_user(
                request,
                "Sadece tamamlanmış yedekler indirilebilir",
                messages.WARNING
            )
            return

        if not backup.file_path or not os.path.isfile(backup.file_path):
            self.message_user(
                request,
                "Yedek dosyası bulunamadı",
                messages.ERROR
            )
            return

        # Dosyayı indir
        try:
            response = FileResponse(open(backup.file_path, 'rb'), content_type='application/sql')
            filename = os.path.basename(backup.file_path)
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
        except Exception as e:
            self.message_user(
                request,
                f"Dosya indirilemedi: {str(e)}",
                messages.ERROR
            )
            return

    download_backup.short_description = "Seçili Yedeği İndir"

    def delete_backup_files(self, request, queryset):
        """Seçili yedeklerin dosyalarını siler"""
        deleted_count = 0
        error_count = 0
        
        manager = BackupManager()
        
        for backup in queryset:
            if backup.file_path:
                success, message = manager.delete_backup_file(backup.file_path)
                if success:
                    backup.file_path = None
                    backup.file_size = None
                    backup.save()
                    deleted_count += 1
                else:
                    error_count += 1
        
        if deleted_count > 0:
            self.message_user(
                request,
                f"{deleted_count} yedek dosyası silindi",
                messages.SUCCESS
            )
        
        if error_count > 0:
            self.message_user(
                request,
                f"{error_count} yedek dosyası silinemedi",
                messages.WARNING
            )
    
    delete_backup_files.short_description = "Yedek Dosyalarını Sil"
    
    def has_delete_permission(self, request, obj=None):
        """Silme iznini kontrol et - Tüm admin kullanıcıları silebilir"""
        return request.user.is_staff
