from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from datetime import date
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver
from simple_history.models import HistoricalRecords
from django_currentuser.middleware import get_current_user, get_current_authenticated_user
from django.conf import settings
from django.contrib.auth.base_user import BaseUserManager
from django.db import transaction
from django.contrib.auth.models import Group
from rolepermissions.checkers import has_permission, has_role
from users.roles import SuperAdminRole
from django_currentuser.db.models import CurrentUserField


class MyUserManager(BaseUserManager):
    """
    Custom user model manager where email is the unique identifiers
    for authentication instead of usernames.
    """
    use_in_migrations = True

    def create_user(self, email, phone, password, **extra_fields):
        """
        Create and save a User with the given email and password.
        """
        email = self.normalize_email(email)
        user = self.model(email=email,
                          phone=phone,
                          is_active=False,
                          **extra_fields)
        user.set_password(password)
        # print(user)
        # return
        if not email:
            raise ValueError(_('The Email must be set'))
        elif not phone:
            raise ValueError(
                _('The phone number is already registered with an account'))
        else:
            user.save()
            from rolepermissions.roles import assign_role
            from users.roles import AuthenticatedUser, AllowAnyRole
            assign_role(user, AuthenticatedUser)
            assign_role(user, AllowAnyRole)
            user.save()
            return user

    # python manage.py createsuperuser
    def create_superuser(self, email, phone, password, is_staff, is_active):
        user = self.model(email=email,
                          phone=phone,
                          is_staff=is_staff,
                          is_active=is_active)
        print(user)
        user.set_password(password)
        user.save(using=self._db)

        # Give permission to the superuser
        from rolepermissions.roles import assign_role
        from .roles import SuperAdminRole, ManagerRole, EmployeeRole, AuthenticatedUser, CustomerRole, AllowAnyRole
        assign_role(user, SuperAdminRole)
        assign_role(user, ManagerRole)
        assign_role(user, EmployeeRole)
        assign_role(user, AuthenticatedUser)
        assign_role(user, CustomerRole)
        assign_role(user, AllowAnyRole)
        user.save()
        return user


class UserModel(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=127,
                              unique=True,
                              null=False,
                              blank=False)
    username = models.CharField(max_length=100, blank=False, null=True)
    sys_id = models.AutoField(primary_key=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    phone = models.CharField(max_length=100)
    first_name = models.CharField(max_length=100, blank=True)
    last_name = models.CharField(max_length=100, blank=True)
    other_name = models.CharField(max_length=100, blank=True)
    date_of_birth = models.DateField(blank=True, null=True)
    gender = models.CharField(max_length=1,
                              choices=settings.GENDER,
                              blank=True)
    photo_url = models.CharField(max_length=500, blank=True)
    bio = models.TextField(max_length=500, blank=True)
    uAccountType = models.CharField(
        max_length=8,
        choices=settings.UACCOUNTTYPE,
        default=settings.UACCOUNT_CONFIG["UACCOUNTTYPE_DEFAULT"])
    dateJoined = models.DateTimeField(auto_now_add=True)

    # USERNAME_FIELD = settings.UACCOUNT_CONFIG["USERNAME_FIELD"]
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['phone', 'is_staff', 'is_active']

    objects = MyUserManager()

    class Meta:
        app_label = "users"
        db_table = "users"
        ordering = ('dateJoined', )

    # HISTORY
    history = HistoricalRecords()

    def __str__(self):
        return self.email

    def get_full_name(self):
        return self.email

    def get_short_name(self):
        return self.email

    # this methods are require to login super user from admin panel
    def has_perm(self, perm, obj=None):
        return self.is_staff and has_role(self, SuperAdminRole)

    # this methods are require to login super user from admin panel
    def has_module_perms(self, app_label):
        return self.is_staff and has_role(self, SuperAdminRole)


class UserDocument(models.Model):
    name = models.CharField(max_length=100)
    file_hash = models.CharField(max_length=500, blank=True)
    purpose = models.CharField(max_length=300)
    url = models.CharField(max_length=200)
    # HISTORY
    history = HistoricalRecords()

    #RELATIONS
    owner = models.ForeignKey(settings.AUTH_USER_MODEL,
                              on_delete=models.CASCADE)


class Address(models.Model):
    apartment = models.CharField(max_length=200, blank=True)
    street = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)
    postCode = models.CharField(max_length=100, blank=True)
    zipCode = models.CharField(max_length=100, blank=True)

    #RELATIONS
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE)
    # HISTORY
    history = HistoricalRecords()


def get_anonymous_user_instance(UserModel):
    ''' Required for guardian anonymous user creation'''
    return UserModel(email='Anonymous@digisave.com', phone='+000000000')


class UserLoginActivity(models.Model):
    # Login Status
    SUCCESS = 'S'
    FAILED = 'F'

    LOGIN_STATUS = ((SUCCESS, 'Success'), (FAILED, 'Failed'))

    login_IP = models.GenericIPAddressField(null=True, blank=True)
    login_datetime = models.DateTimeField(auto_now=True)
    user = CurrentUserField()
    login_username = models.CharField(max_length=100, null=True, blank=True)
    status = models.CharField(max_length=1,
                              default=SUCCESS,
                              choices=LOGIN_STATUS,
                              null=True,
                              blank=True)
    user_agent_info = models.CharField(max_length=255)

    class Meta:
        verbose_name = 'user_login_activity'
        verbose_name_plural = 'user_login_activities'
        ordering = ('login_datetime', )

    def __str__(self):
        if self.login_username:
            return self.login_username
        else:
            return self.login_IP

class KYC(models.Model):
    EMPLOYMENT_STATUS = (('Unemployed', 'Unemployed'), ('Employed', 'Employed'))
    RELATIONSHIP_STATUS = (('married', 'married'), ('single', 'single'), ('divorced', 'divorced'), ('widowed', 'widowed'))
    ID_TYPE = (('national_id', 'National ID'), ('voters_card', 'Voters card'), ('drivers_licence', 'Drivers Licence'), ('international_passport', 'International Passport'))
    relationshipStatus = models.CharField(max_length=11,
                              choices=RELATIONSHIP_STATUS,)
    employmentStatus = models.CharField(max_length=11,
                              choices=EMPLOYMENT_STATUS,)
    mothersMaidenName = models.CharField(max_length=100)
    idType = models.CharField(max_length=20,
                              choices=ID_TYPE,)
    idNumber = models.CharField(max_length=100)
    idIssueDate = models.DateField(blank=True, null=True)
    idExpireDate = models.DateField(blank=True, null=True)

    #RELATIONS
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE)


    def __str__(self):
        return self.idType

    class Meta:
        ordering = ('pk', )


class NextOfKin(models.Model):
    firstName = models.CharField(max_length=100)
    lastName = models.CharField(max_length=100)
    middleName = models.CharField(max_length=100, blank=True, null=True)
    dateOfBirth = models.DateField(blank=True, null=True)
    occupation = models.CharField(max_length=100)
    relationsShip = models.CharField(max_length=100)
    email = models.CharField(max_length=100)
    apartment = models.CharField(max_length=200, blank=True)
    street = models.CharField(max_length=100, blank=True)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100)

    # RELATIONS
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE)

    def __str__(self):
        return self.firstName + ' ' + self.lastName+' '+self.middleName

    class Meta:
        ordering = ('pk', )