from datetime import timedelta

from django.apps import apps
from django.conf import settings
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.db import models
from django.contrib.auth.models import UserManager as DjangoUserManager

from users.licenses import MYSKILLBOX_LICENSES


class RoleManager(models.Manager):
    use_in_migrations = True

    TEACHER_KEY = 'teacher'
    STUDENT_KEY = 'student'
    PARENT_KEY = 'parent'

    DEFAULT_ROLES = {
        TEACHER_KEY: _(u'Lehrperson'),
        STUDENT_KEY: _(u'Schüler'),
        # PARENT_KEY: _(u'Aufsichtsperson'),
        # SCHOOL_ADMIN_KEY: _(u'Schuladministrator')
    }

    READONLY_ROLES = []

    DEFAULT_ROLE_KEYS = DEFAULT_ROLES.keys()

    def is_key_in_defaults(self, key):
        return key in self.DEFAULT_ROLE_KEYS

    def is_key_readonly(self, key):
        return key in self.READONLY_ROLES

    def get_roles_for_user(self, user):
        return self.model.objects.filter(user_roles__user=user)

    def create_default_roles(self):
        for key, value in self.DEFAULT_ROLES.items():
            role, created = self.get_or_create(name=value, key=key)

            can_manage_school_class_content, = self._create_default_permissions()

            if key == "teacher":
                role.role_permission.add(can_manage_school_class_content.id)

    def get_default_teacher_role(self):
        return self._get_default_role(self.TEACHER_KEY)

    def get_default_student_role(self):
        return self._get_default_role(self.STUDENT_KEY)

    def _get_default_role(self, key):
        try:
            return self.get(name=self.DEFAULT_ROLES[key])
        except self.model.DoesNotExist:
            return None

    def _create_default_permissions(self):
        content_type = ContentType.objects.get_for_model(self.model)
        # edit_events = Permission.objects.get(content_type=content_type, codename="can_edit_events")
        # edit_own_comments = Permission.objects.get(content_type=content_type, codename="can_edit_own_comments")
        # delete_comments = Permission.objects.get(content_type=content_type, codename="can_delete_comments")
        # admin_school = Permission.objects.get(content_type=content_type, codename="can_admin_school")
        can_manage_school_class_content = Permission.objects.get(content_type=content_type,
                                                                 codename='can_manage_school_class_content')

        return can_manage_school_class_content,


class UserRoleManager(models.Manager):
    def get_or_create_role_for_user(self, user, role_key):
        from users.models import Role
        try:
            role = Role.objects.get(key=role_key)
        except Role.DoesNotExist:
            return None

        try:
            user_role = self.model.objects.get(role=role, user=user)
            return user_role
        except self.model.DoesNotExist:
            return self._create_user_role(user, role)

    def _create_user_role(self, user, role):
        user_role = self.model(user=user, role=role)
        user_role.save()
        return user_role


class UserManager(DjangoUserManager):

    def _create_user_with_random_password_no_save(self, first_name, last_name, email):
        user, created = self.model.objects.get_or_create(email=email, username=email)
        user.first_name = first_name
        user.last_name = last_name
        # Todo: remove if not used
        # user.set_password(self.model.objects.make_random_password())
        user.set_unusable_password()
        return user

    def create_user_with_random_password(self, first_name, last_name, email):
        user = self._create_user_with_random_password_no_save(first_name, last_name, email)
        user.save()
        return user

    def create_user_from_hep(self, user_data):
        try:
            user = self.model.objects.get(email=user_data['email'])
            user.set_unusable_password()
        except self.model.DoesNotExist:
            user = self._create_user_with_random_password_no_save(user_data['first_name'],
                                                                   user_data['last_name'],
                                                                   user_data['email'])

        user.hep_id = user_data['id']
        user.save()

        # todo: how to handle
        # if user.hep_group_id == settings.HEP_MYSKILLBOX_GROUP_ID:
        #     apps.get_model('users.UserData').objects.create(user=user, accepted_terms=True)

        return user

    def get_or_create_hep_user(self, user_data):

        try:
            user = self.get(hep_id=user_data['id'])
        except self.model.DoesNotExist:
            user = self.create_user_from_hep(user_data)

        return user


class LicenseManager(models.Manager):

    def create_license_for_role(self, licensee, activation_date, raw, role, order_id, isbn):
        Role = apps.get_model('users', 'Role')
        expiry_date = activation_date + timedelta(MYSKILLBOX_LICENSES[isbn]['duration'])

        if role == 'teacher':
            user_role = Role.objects.get_default_teacher_role()
        else:
            user_role = Role.objects.get_default_student_role()

        new_license = self._create_license_for_role(licensee, expiry_date, raw, user_role, order_id, isbn,
                                                    activation_date)
        new_license.licensee.license_expiry_date = new_license.expire_date
        new_license.licensee.save()

        return new_license

    def _create_license_for_role(self, licensee, expiry_date, raw, role, order_id, isbn, activation_date):
        return self.create(licensee=licensee, expire_date=expiry_date, new_api_raw=raw, for_role=role, order_id=order_id,
                           isbn=isbn, hep_created_at=activation_date)

    def get_active_license_for_user(self, user):
        licenses = self.filter(licensee=user, expire_date__gte=timezone.now()).order_by('-expire_date')
        if len(licenses) == 0:
            return None

        license = licenses[0]

        # update license on user
        user.license_expiry_date = license.expire_date
        user.save()

        return license

