from dati_geo_app.admin import (AjaxAutocompleteListFilterModelAdmin,
                                RicercaOrdinataMixin)
from drilldown_autocomplete import DrillDownAutocompleteAdmin
from import_export.admin import ImportExportModelAdmin
from polymorphic.admin import (PolymorphicChildModelAdmin,
                               PolymorphicChildModelFilter,
                               PolymorphicInlineSupportMixin,
                               PolymorphicParentModelAdmin,
                               StackedPolymorphicInline)

from django.contrib import admin
from django.core.cache import cache
from django.core.paginator import Paginator
from django.db.models import F

from . import models

# Modified version of a GIST I found in a SO thread
# cfr. http://masnun.rocks/2017/03/20/django-admin-expensive-count-all-queries/


class AutocompleteAdmin(admin.ModelAdmin):
    class Media:
        js = ('admin/js/autocomplete_auto_focus.js', )


class StackedInlineCollassati(admin.ModelAdmin):
    class Media:
        js = ('admin/js/stacked_inline_collassati.js',)
        css = { 'all': ('admin/css/stacked_inline_collassati.css',)}


class HiddenIfNotSuperuser(admin.ModelAdmin):
    def get_model_perms(self, request):
        if not request.user.is_superuser:
            return {}
        else:
            return super().get_model_perms(request)


class HiddenModel(admin.ModelAdmin):
    def get_model_perms(self, request):
        return {}


class CachingPaginator(Paginator):
    def _get_count(self):
        if not hasattr(self, "_count"):
            self._count = None
        if self._count is None:
            try:
                key = "adm:{0}:count".format(
                    hash(self.object_list.query.__str__()))
                self._count = cache.get(key, -1)
                if self._count == -1:
                    self._count = super().count
                    cache.set(key, self._count, 60)
            except:
                self._count = len(self.object_list)
        return self._count
    count = property(_get_count)

# # Main reusable Admin class for only viewing
# class ViewAdminMixin(admin.ModelAdmin):
#     def has_add_permission(self, request):
#         return False
#
#     def has_change_permission(self, request, obj=None):
#         return False
#
#     def has_delete_permission(self, request, obj=None):
#         return False

# --------------- FINE PREFISSO TEMPLATE ---------------


@admin.register(models.ContattoAziendale)
class ContattoAziendaleAdmin(ImportExportModelAdmin, AutocompleteAdmin):
    # resource = resources.ContattoAziendaleResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    autocomplete_fields = ('azienda','persona',)
    list_display = ('persona','azienda','is_personale')
    pass

@admin.register(models.Recapito)
class RecapitoAdmin(ImportExportModelAdmin, PolymorphicParentModelAdmin):
    # resource = resources.RecapitoResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    base_model = models.Recapito
    child_models = (models.Indirizzo, models.Sede, models.Email, models.Pec, models.Telefono, models.Fax,)
    list_filter = (PolymorphicChildModelFilter,)
    readonly_fields = ('descrizione','tipo',)
    list_display = ('tipo','soggetto','descrizione',)
    list_display_links = ('tipo','descrizione',)

    def descrizione(self,obj):
        attrib = obj.polymorphic_ctype.model
        if attrib == 'pec':
            attrib = 'email'
        if attrib == 'sede':
            attrib = 'indirizzo'
        return str(getattr(obj,attrib))

    def tipo(self, obj):
        return obj.polymorphic_ctype.model_class()._meta.verbose_name.title()
    tipo.admin_order_field = '_tipo'

    def get_queryset(self, request):
        qs=super().get_queryset(request).prefetch_related('polymorphic_ctype')
        qs=qs.annotate(_tipo=F('polymorphic_ctype__model'))
        return qs
    pass


@admin.register(models.Telefono)
class TelefonoAdmin(HiddenModel, PolymorphicChildModelAdmin, AutocompleteAdmin):
    # resource = resources.TelefonoResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    fields = ('soggetto','numero','interno','note',)
    autocomplete_fields = ('soggetto',)
    pass


@admin.register(models.Email)
class EmailAdmin(HiddenModel, PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, AutocompleteAdmin):
    # resource = resources.EmailResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    base_model = models.Recapito
    child_models = (models.Email, models.Pec,)
    fields = ('soggetto','indirizzo_email','note',)
    autocomplete_fields = ('soggetto',)
    pass


ddaf={
        'cap': {
            'relationship_path':  {
                'comune': 'comuni',
            },
            'filtered_by': [ 'comune' ],
            'reset_on_included': [],
            'reset_on_excluded': ['comune'],
            'reset_on_reset': [],
            'autoupdate_on_reset': True, # TODO: semplice flag autoupdate che mette a true questi prossimi tre
            'autoupdate_on_empty': True,
            'autoselect_on_singleton': True, # TODO: semplice flag autoupdate che mette a true questi ultimi tre
            'included_only': False,
        },
        'comune': {
            'relationship_path': {
                'cap': 'cap',
            },
            'filtered_by': [ 'cap' ],
            'reset_on_included': [],
            'reset_on_excluded': ['cap'],
            'reset_on_reset': [],
            'autoupdate_on_reset': True,
            'autoupdate_on_empty': True,
            'autoselect_on_singleton': True,
            'included_only': False,
        }
    }

class RecapitoInline(StackedPolymorphicInline, DrillDownAutocompleteAdmin):
    class IndirizzoInline(StackedPolymorphicInline.Child, DrillDownAutocompleteAdmin):
        model = models.Indirizzo
        autocomplete_fields = ('dug','comune','cap','nazione',)
        drilldown_autocomplete_fields = ddaf

    class SedeInline(StackedPolymorphicInline.Child):
        model = models.Sede
        autocomplete_fields = ('dug','comune','cap','nazione',)

    class EmailInline(StackedPolymorphicInline.Child):
        model = models.Email

    class PecInline(StackedPolymorphicInline.Child):
        model = models.Pec

    class TelefonoInline(StackedPolymorphicInline.Child):
        model = models.Telefono

    class FaxInline(StackedPolymorphicInline.Child):
        model = models.Fax

    model = models.Recapito
    child_inlines = (
        IndirizzoInline,
        SedeInline,
        EmailInline,
        PecInline,
        TelefonoInline,
        FaxInline,
    )


@admin.register(models.PersonaFisica)
class PersonaFisicaAdmin(PolymorphicInlineSupportMixin, PolymorphicChildModelAdmin, StackedInlineCollassati,AutocompleteAdmin):
    # resource = resources.PersonaFisicaResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    show_in_index = False
    get_model_perms = lambda self, req: {}
    search_fields = ('nome','cognome',)
    inlines = (RecapitoInline,)


@admin.register(models.PersonaGiuridica)
class PersonaGiuridicaAdmin(PolymorphicInlineSupportMixin, PolymorphicChildModelAdmin, StackedInlineCollassati,AutocompleteAdmin):
    # resource = resources.PersonaGiuridicaResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    show_in_index = False
    get_model_perms = lambda self, req: {}
    inlines = (RecapitoInline,)
    pass


@admin.register(models.Sede)
class SedeAdmin(ImportExportModelAdmin, AutocompleteAdmin):
    # resource = resources.SedeResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    list_display=('societa','comune','dug','duf',)
    autocomplete_fields=('dug','comune','cap','nazione','soggetto','societa',)
    pass


@admin.register(models.Fax)
class FaxAdmin(HiddenModel, PolymorphicChildModelAdmin, AutocompleteAdmin):
    # resource = resources.FaxResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    fields = ('soggetto','numero','note',)
    autocomplete_fields = ('soggetto',)
    pass


@admin.register(models.Pec)
class PecAdmin(HiddenModel, PolymorphicChildModelAdmin, AutocompleteAdmin):
    # resource = resources.PecResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    base_model = models.Email
    fields = ('soggetto','indirizzo_email','note',)
    autocomplete_fields = ('soggetto',)
    pass


@admin.register(models.SoggettoContattabile)
class SoggettoContattabileAdmin(PolymorphicParentModelAdmin):
    # resource = resources.SoggettoContattabileResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    base_model = models.SoggettoContattabile
    child_models = (models.PersonaFisica, models.PersonaGiuridica,)
    list_filter = (PolymorphicChildModelFilter,)
    readonly_fields = ('descrizione','tipo',)
    list_display = ('descrizione','tipo',)
    search_fields = ('personafisica__nome','personafisica__cognome','personagiuridica__denominazione',)

    def descrizione(self,obj):
        return str(getattr(obj,obj.polymorphic_ctype.model))

    def tipo(self, obj):
        return getattr(obj,obj.polymorphic_ctype.model)._meta.verbose_name.title()
    
    def get_queryset(self, request):
        qs=super().get_queryset(request).prefetch_related('polymorphic_ctype')
        return qs
    pass


@admin.register(models.Indirizzo)
class IndirizzoAdmin(HiddenModel, DrillDownAutocompleteAdmin, RicercaOrdinataMixin, AjaxAutocompleteListFilterModelAdmin, PolymorphicChildModelAdmin, AutocompleteAdmin):
    # resource = resources.IndirizzoResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    list_per_page = 15
    paginator = CachingPaginator
    show_full_result_count = False
    fields=('soggetto','dug','duf','civico','cap','comune','altro',)
    search_fields = ('soggetto','indirizzo','cap_id__exact',)
    autocomplete_fields = ('soggetto','dug','cap','comune',)
    drilldown_autocomplete_fields = ddaf
    list_display = ('soggetto','indirizzo', 'cap','comune','provincia','regione',)
    ordering = ('comune_id','duf','civico',)
    autocomplete_list_filter = ('comune',)
    list_filter = ('comune__provincia__regione_id',)

    # def get_queryset(self, request):
    #     queryset = super().get_queryset(request).select_related('comune__provincia__regione').annotate(indirizzo=Concat('dug_id',Value(' '),'duf',Value(' '),'civico'))
    #     return queryset

    def provincia(self, obj):
        return obj.comune.provincia
    provincia.short_description = 'Provincia'
    provincia.admin_order_field = 'comune__provincia_id'

    def regione(self, obj):
        return obj.comune.provincia.regione_id
    regione.short_description = 'Regione'
    regione.admin_order_field = 'comune__provincia__regione_id'

    def indirizzo(self, obj):
        return obj.indirizzo
    indirizzo.short_description = 'Indirizzo'
    indirizzo.admin_order_field = ('comune_id','duf','civico',)
    pass


class SedeInline(admin.TabularInline):
    model = models.Sede
    autocomplete_fields = ('dug','comune','cap','nazione','comune','cap',)
    extra = 0

class PersonaInline(admin.TabularInline):
    model = models.ContattoAziendale
    autocomplete_fields = ('persona',)
    extra = 0

@admin.register(models.Societa)
class SocietaAdmin(ImportExportModelAdmin, AutocompleteAdmin):
    # resource = resources.SocietaResource
    # list_per_page = 15
    # paginator = CachingPaginator
    # show_full_result_count = False
    inlines = (SedeInline,PersonaInline,)
    search_fields = ('ragione_sociale',)
    autocomplete_fields = ('soggetto','nazione',)
    pass
