from datetime import timedelta

from django import forms
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext

from misago.acl import algebra
from misago.acl.decorators import return_boolean
from misago.acl.models import Role
from misago.conf import settings


__all__ = [
    'allow_delete_user',
    'can_delete_user',
    'allow_delete_own_account',
    'can_delete_own_account',
]


class PermissionsForm(forms.Form):
    legend = _("Deleting users")

    can_delete_users_newer_than = forms.IntegerField(
        label=_("Maximum age of deleted account (in days)"),
        help_text=_("Enter zero to disable this check."),
        min_value=0,
        initial=0,
    )
    can_delete_users_with_less_posts_than = forms.IntegerField(
        label=_("Maximum number of posts on deleted account"),
        help_text=_("Enter zero to disable this check."),
        min_value=0,
        initial=0,
    )


def change_permissions_form(role):
    if isinstance(role, Role) and role.special_role != 'anonymous':
        return PermissionsForm
    else:
        return None


def build_acl(acl, roles, key_name):
    new_acl = {
        'can_delete_users_newer_than': 0,
        'can_delete_users_with_less_posts_than': 0,
    }
    new_acl.update(acl)

    return algebra.sum_acls(
        new_acl,
        roles=roles,
        key=key_name,
        can_delete_users_newer_than=algebra.greater,
        can_delete_users_with_less_posts_than=algebra.greater,
    )


def add_acl_to_user(user, target):
    target.acl['can_delete'] = can_delete_user(user, target)
    if target.acl['can_delete']:
        target.acl['can_moderate'] = True


def register_with(registry):
    registry.acl_annotator(get_user_model(), add_acl_to_user)


def allow_delete_user(user, target):
    newer_than = user.acl_cache['can_delete_users_newer_than']
    less_posts_than = user.acl_cache['can_delete_users_with_less_posts_than']
    if not newer_than and not less_posts_than:
        raise PermissionDenied(_("You can't delete users."))

    if user.pk == target.pk:
        raise PermissionDenied(_("You can't delete your account."))
    if target.is_staff or target.is_superuser:
        raise PermissionDenied(_("You can't delete administrators."))

    if newer_than:
        if target.joined_on < timezone.now() - timedelta(days=newer_than):
            message = ungettext(
                "You can't delete users that are members for more than %(days)s day.",
                "You can't delete users that are members for more than %(days)s days.",
                newer_than,
            )
            raise PermissionDenied(message % {'days': newer_than})
    if less_posts_than:
        if target.posts > less_posts_than:
            message = ungettext(
                "You can't delete users that made more than %(posts)s post.",
                "You can't delete users that made more than %(posts)s posts.",
                less_posts_than,
            )
            raise PermissionDenied(message % {'posts': less_posts_than})


can_delete_user = return_boolean(allow_delete_user)


def allow_delete_own_account(user, target):
    if not settings.MISAGO_ENABLE_DELETE_OWN_ACCOUNT and not user.is_deleting_account:
        raise PermissionDenied(_("You can't delete your account."))
    if user.pk != target.pk:
        raise PermissionDenied(_("You can't delete other users accounts."))
    if user.is_staff or user.is_superuser:
        raise PermissionDenied(
            _("You can't delete your account because you are an administrator.")
        )


can_delete_own_account = return_boolean(allow_delete_own_account)
