"""
Everything related to the admin interface of ModelEvent is located in here
"""

from django.contrib.admin import register, RelatedOnlyFieldListFilter
from django.utils.html import format_html

from automated_logging.admin.base import ReadOnlyTabularInlineMixin, ReadOnlyAdminMixin
from automated_logging.helpers import Operation
from automated_logging.models import (
    ModelValueModification,
    ModelRelationshipModification,
    ModelEvent,
)


class ModelValueModificationInline(ReadOnlyTabularInlineMixin):
    """ inline for all modifications """

    model = ModelValueModification

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.readonly_fields = [*self.readonly_fields, 'get_uuid', 'get_field']

    def get_uuid(self, instance):
        """ make the uuid small """
        return str(instance.id).split('-')[0]

    get_uuid.short_description = 'UUID'

    def get_field(self, instance):
        """ show the field name """
        return instance.field.name

    get_field.short_description = 'Field'

    fields = ('get_uuid', 'operation', 'get_field', 'previous', 'current')
    can_delete = False

    verbose_name = 'Modification'
    verbose_name_plural = 'Modifications'


class ModelRelationshipModificationInline(ReadOnlyTabularInlineMixin):
    """ inline for all relationship modifications """

    model = ModelRelationshipModification

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.readonly_fields = [*self.readonly_fields, 'get_uuid', 'get_field']

    def get_uuid(self, instance):
        """ make the uuid small """
        return str(instance.id).split('-')[0]

    get_uuid.short_description = 'UUID'

    def get_field(self, instance):
        """ show the field name """
        return instance.field.name

    get_field.short_description = 'Field'

    fields = ('get_uuid', 'operation', 'get_field', 'model')
    can_delete = False

    verbose_name = 'Relationship'
    verbose_name_plural = 'Relationships'


@register(ModelEvent)
class ModelEventAdmin(ReadOnlyAdminMixin):
    """ admin page specification for ModelEvent """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.readonly_fields = [
            *self.readonly_fields,
            'get_application',
            'get_user',
            'get_model_link',
        ]

    def get_modifications(self, instance):
        """
        Modifications in short form, are colored for better readability.

        Colors taken from
        https://github.com/django/django/tree/master/django/contrib/admin/static/admin/img
        """
        colors = {
            Operation.CREATE: '#70bf2b',
            Operation.MODIFY: '#efb80b',
            Operation.DELETE: '#dd4646',
        }
        return format_html(
            ', '.join(
                [
                    *[
                        f'<span style="color: {colors[Operation(m.operation)]};">'
                        f'{m.short()}'
                        f'</span>'
                        for m in instance.modifications.all()
                    ],
                    *[
                        f'<span style="color: {colors[Operation(r.operation)]};">'
                        f'{r.medium()[0]}'
                        f'</span>[{r.medium()[1]}]'
                        for r in instance.relationships.all()
                    ],
                ],
            )
        )

    get_modifications.short_description = 'Modifications'

    def get_model(self, instance):
        """
        get the model
        TODO: consider splitting this up to model/pk/value
        """
        return instance.entry.short()

    get_model.short_description = 'Model'

    def get_model_link(self, instance):
        """ get the model with a link to the entry """
        return self.model_admin_url(instance.entry)

    get_model_link.short_description = 'Model'

    def get_application(self, instance):
        """
        helper to get the application from the child ModelMirror
        :param instance:
        :return:
        """
        return instance.entry.mirror.application

    get_application.short_description = 'Application'

    def get_id(self, instance):
        """ shorten the id to the first 8 digits """
        return str(instance.id).split('-')[0]

    get_id.short_description = 'UUID'

    def get_user(self, instance):
        """ return the user with a link """
        return self.model_admin_url(instance.user) if instance.user else None

    get_user.short_description = 'User'

    list_display = (
        'get_id',
        'updated_at',
        'user',
        'get_application',
        'get_model',
        'get_modifications',
    )

    list_filter = (
        'updated_at',
        ('user', RelatedOnlyFieldListFilter),
        ('model__model__application', RelatedOnlyFieldListFilter),
        ('model__model', RelatedOnlyFieldListFilter),
    )

    date_hierarchy = 'updated_at'
    ordering = ('-updated_at',)

    fieldsets = (
        (
            'Information',
            {
                'fields': (
                    'id',
                    'get_user',
                    'updated_at',
                    'get_application',
                    'get_model_link',
                )
            },
        ),
        ('Introspection', {'fields': ('performance', 'snapshot')}),
    )
    inlines = [ModelValueModificationInline, ModelRelationshipModificationInline]

    show_change_link = True
