from django.contrib import admin
from django.forms import ModelForm
from django.utils.html import format_html
from django.utils.translation import gettext, gettext_lazy as _, ungettext
from reversion.admin import VersionAdmin

from django_ace import AceWidget
from judge.models import Profile
from judge.widgets import AdminPagedownWidget, AdminSelect2Widget


class ProfileForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        if "current_contest" in self.base_fields:
            # form.fields['current_contest'] does not exist when the user has only view permission on the model.
            self.fields[
                "current_contest"
            ].queryset = self.instance.contest_history.select_related("contest").only(
                "contest__name", "user_id", "virtual"
            )
            self.fields["current_contest"].label_from_instance = (
                lambda obj: "%s v%d" % (obj.contest.name, obj.virtual)
                if obj.virtual
                else obj.contest.name
            )

    class Meta:
        widgets = {
            "timezone": AdminSelect2Widget,
            "language": AdminSelect2Widget,
            "ace_theme": AdminSelect2Widget,
            "current_contest": AdminSelect2Widget,
        }
        if AdminPagedownWidget is not None:
            widgets["about"] = AdminPagedownWidget


class TimezoneFilter(admin.SimpleListFilter):
    title = _("timezone")
    parameter_name = "timezone"

    def lookups(self, request, model_admin):
        return (
            Profile.objects.values_list("timezone", "timezone")
            .distinct()
            .order_by("timezone")
        )

    def queryset(self, request, queryset):
        if self.value() is None:
            return queryset
        return queryset.filter(timezone=self.value())


class ProfileAdmin(VersionAdmin):
    fields = (
        "user",
        "display_rank",
        "about",
        "organizations",
        "timezone",
        "language",
        "ace_theme",
        "math_engine",
        "last_access",
        "ip",
        "mute",
        "is_unlisted",
        "is_banned_problem_voting",
        "notes",
        "is_totp_enabled",
        "user_script",
        "current_contest",
    )
    readonly_fields = ("user",)
    list_display = (
        "admin_user_admin",
        "email",
        "is_totp_enabled",
        "timezone_full",
        "date_joined",
        "last_access",
        "ip",
        "show_public",
    )
    ordering = ("user__username",)
    search_fields = ("user__username", "ip", "user__email")
    list_filter = ("language", TimezoneFilter)
    actions = ("recalculate_points",)
    actions_on_top = True
    actions_on_bottom = True
    form = ProfileForm

    def get_queryset(self, request):
        return super(ProfileAdmin, self).get_queryset(request).select_related("user")

    def get_fields(self, request, obj=None):
        if request.user.has_perm("judge.totp"):
            fields = list(self.fields)
            fields.insert(fields.index("is_totp_enabled") + 1, "totp_key")
            return tuple(fields)
        else:
            return self.fields

    def get_readonly_fields(self, request, obj=None):
        fields = self.readonly_fields
        if not request.user.has_perm("judge.totp"):
            fields += ("is_totp_enabled",)
        return fields

    def show_public(self, obj):
        return format_html(
            '<a href="{0}" style="white-space:nowrap;">{1}</a>',
            obj.get_absolute_url(),
            gettext("View on site"),
        )

    show_public.short_description = ""

    def admin_user_admin(self, obj):
        return obj.username

    admin_user_admin.admin_order_field = "user__username"
    admin_user_admin.short_description = _("User")

    def email(self, obj):
        return obj.user.email

    email.admin_order_field = "user__email"
    email.short_description = _("Email")

    def timezone_full(self, obj):
        return obj.timezone

    timezone_full.admin_order_field = "timezone"
    timezone_full.short_description = _("Timezone")

    def date_joined(self, obj):
        return obj.user.date_joined

    date_joined.admin_order_field = "user__date_joined"
    date_joined.short_description = _("date joined")

    def recalculate_points(self, request, queryset):
        count = 0
        for profile in queryset:
            profile.calculate_points()
            count += 1
        self.message_user(
            request,
            ungettext(
                "%d user have scores recalculated.",
                "%d users have scores recalculated.",
                count,
            )
            % count,
        )

    recalculate_points.short_description = _("Recalculate scores")

    def get_form(self, request, obj=None, **kwargs):
        form = super(ProfileAdmin, self).get_form(request, obj, **kwargs)
        if "user_script" in form.base_fields:
            # form.base_fields['user_script'] does not exist when the user has only view permission on the model.
            form.base_fields["user_script"].widget = AceWidget(
                "javascript", request.profile.ace_theme
            )
        return form