from datetime import timedelta

from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import Group, User
from django.db.models import Q
from django.utils import timezone
from unfold.admin import ModelAdmin
from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm

from .admin_ui import PortalAdminMixin
from .models import Document, PortalConfiguration, Provider


try:
    admin.site.unregister(User)
    admin.site.unregister(Group)
except admin.sites.NotRegistered:
    pass


@admin.register(User)
class UserAdmin(PortalAdminMixin, BaseUserAdmin, ModelAdmin):
    portal_icon = "manage_accounts"
    portal_kicker = "SISTEMA"
    portal_description = "Utilizadores internos, permissões de acesso e credenciais administrativas do portal."
    portal_tone = "navy"
    portal_stats = ()
    portal_use_fieldset_tabs = False
    form = UserChangeForm
    add_form = UserCreationForm
    change_password_form = AdminPasswordChangeForm
    list_per_page = 25
    warn_unsaved_form = True


@admin.register(Group)
class GroupAdmin(PortalAdminMixin, BaseGroupAdmin, ModelAdmin):
    portal_icon = "admin_panel_settings"
    portal_kicker = "SISTEMA"
    portal_description = "Grupos e permissões para separar responsabilidades administrativas, financeiras e técnicas."
    portal_tone = "violet"
    portal_stats = ()
    portal_use_fieldset_tabs = False
    list_per_page = 25
    warn_unsaved_form = True


@admin.register(Provider)
class ProviderAdmin(PortalAdminMixin, ModelAdmin):
    portal_icon = "business"
    portal_kicker = "GESTÃO COMERCIAL"
    portal_description = "Fornecedores de domínios, alojamento, servidores e pagamentos, com referências de conta e suporte."
    portal_tone = "navy"
    portal_stats = (
        {"label": "Fornecedores", "icon": "business", "tone": "primary", "caption": "Total registado"},
        {"label": "Ativos", "icon": "verified", "tone": "success", "filters": {"is_active": True}, "caption": "Em utilização"},
        {"label": "Registadores", "icon": "language", "tone": "violet", "filters": {"provider_type": Provider.ProviderType.REGISTRAR}, "caption": "Gestão de domínios"},
        {"label": "Alojamento / cloud", "icon": "cloud", "tone": "cyan", "method": "count_infrastructure", "caption": "Infraestrutura"},
    )
    portal_related_links = (
        {"label": "Serviços", "icon": "inventory_2", "url_name": "admin:services_service_changelist"},
        {"label": "Servidores", "icon": "dns", "url_name": "admin:technical_server_changelist"},
        {"label": "Domínios", "icon": "language", "url_name": "admin:domains_domain_changelist"},
    )

    list_display = ("name", "provider_type", "support_email", "is_active")
    list_filter = ("provider_type", "is_active")
    search_fields = ("name", "support_email", "account_reference")
    list_editable = ("is_active",)
    list_fullwidth = True
    readonly_fields = ("public_id", "created_at", "updated_at")
    fieldsets = (
        ("Fornecedor", {"fields": ("name", "provider_type", "is_active", "website"), "description": "Identificação e categoria do fornecedor."}),
        ("Suporte", {"fields": ("support_email", "support_phone"), "description": "Canais usados para pedidos e incidentes."}),
        ("Conta segura", {"fields": ("account_reference",), "description": "Referência da conta ou cofre; nunca guardar passwords."}),
        ("Notas", {"fields": ("notes",)}),
        ("Sistema", {"fields": ("public_id", "created_at", "updated_at"), "classes": ("collapse",)}),
    )

    def count_infrastructure(self, request, queryset):
        return queryset.filter(provider_type__in=(Provider.ProviderType.HOSTING, Provider.ProviderType.SERVER)).count()


@admin.register(PortalConfiguration)
class PortalConfigurationAdmin(PortalAdminMixin, ModelAdmin):
    portal_icon = "settings"
    portal_kicker = "SISTEMA"
    portal_description = "Configuração global da empresa, instruções de pagamento e calendário padrão de notificações."
    portal_tone = "navy"
    portal_stats = (
        {"label": "Configuração global", "icon": "settings", "tone": "primary", "caption": "Um único registo"},
    )
    portal_use_fieldset_tabs = True
    readonly_fields = ("public_id", "created_at", "updated_at")
    fieldsets = (
        ("Identificação", {"fields": ("company_name", "company_nif", "company_email", "company_phone", "portal_base_url"), "description": "Dados apresentados nas comunicações e documentos."}),
        ("Pagamentos", {"fields": ("mbway_phone", "iban"), "description": "Instruções de pagamento usadas nos avisos aos clientes."}),
        ("Avisos", {"fields": ("default_notice_days", "second_notice_days", "final_notice_days", "internal_notification_email", "reply_to_email"), "description": "Antecedência padrão, respostas e alertas internos."}),
        ("Segurança de email", {"fields": ("email_test_mode", "email_test_recipient"), "description": "Mantenha o modo de teste ativo até confirmar todos os modelos e o SMTP."}),
        ("Automação", {"fields": ("auto_prepare_notifications", "auto_send_notifications", "notification_max_attempts", "notification_retry_minutes"), "description": "Controlo de preparação, envio e repetição automática."}),
        ("Notas", {"fields": ("notes",)}),
        ("Sistema", {"fields": ("public_id", "created_at", "updated_at"), "classes": ("collapse",)}),
    )

    def has_add_permission(self, request):
        return not PortalConfiguration.objects.exists()

    def has_delete_permission(self, request, obj=None):
        return False


@admin.register(Document)
class DocumentAdmin(PortalAdminMixin, ModelAdmin):
    portal_icon = "folder"
    portal_kicker = "DOCUMENTOS"
    portal_description = "Arquivo privado de contratos, faturas, recibos, comprovativos e relatórios ligados aos registos do portal."
    portal_tone = "amber"
    portal_stats = (
        {"label": "Documentos", "icon": "folder", "tone": "primary", "caption": "Arquivo total"},
        {"label": "Visíveis ao cliente", "icon": "visibility", "tone": "success", "filters": {"visible_to_client": True}, "caption": "Preparados para o portal"},
        {"label": "Sem ficheiro", "icon": "file_present", "tone": "warning", "filters": {"file": ""}, "caption": "Metadados incompletos"},
        {"label": "Expiram em 30 dias", "icon": "event_busy", "tone": "danger", "method": "count_expiring", "caption": "Requer renovação"},
    )
    portal_related_links = (
        {"label": "Clientes", "icon": "groups", "url_name": "admin:clients_client_changelist"},
        {"label": "Pagamentos", "icon": "payments", "url_name": "admin:billing_payment_changelist"},
        {"label": "Suporte", "icon": "support_agent", "url_name": "admin:support_supportticket_changelist"},
    )

    list_display = ("document_identity", "category", "client", "service", "issued_on", "expires_on", "visible_to_client", "uploaded_by")
    list_filter = ("category", "visible_to_client", "issued_on", "expires_on")
    search_fields = ("title", "reference", "notes", "client__name", "service__name", "support_ticket__subject")
    autocomplete_fields = ("client", "service", "payment", "support_ticket", "uploaded_by")
    readonly_fields = ("public_id", "created_at", "updated_at")
    list_filter_submit = True
    list_fullwidth = True
    fieldsets = (
        ("Documento", {"fields": ("title", "category", "file", "reference"), "description": "Identificação e ficheiro armazenado em área privada."}),
        ("Associações", {"fields": ("client", "service", "payment", "support_ticket"), "description": "Associe pelo menos um contexto ao documento."}),
        ("Datas e visibilidade", {"fields": ("issued_on", "expires_on", "visible_to_client", "uploaded_by"), "description": "Validade e disponibilização segura no portal do cliente."}),
        ("Notas", {"fields": ("notes",)}),
        ("Sistema", {"fields": ("public_id", "created_at", "updated_at"), "classes": ("collapse",)}),
    )

    def count_expiring(self, request, queryset):
        today = timezone.localdate()
        return queryset.filter(expires_on__range=(today, today + timedelta(days=30))).count()

    @admin.display(description="Documento", ordering="title")
    def document_identity(self, obj):
        return obj.title

    def save_model(self, request, obj, form, change):
        if not obj.uploaded_by_id:
            obj.uploaded_by = request.user
        super().save_model(request, obj, form, change)
