from datetime import datetime, time
from django.core.mail import send_mail
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.http import base36_to_int, int_to_base36
from django.conf import settings
from django.utils.crypto import constant_time_compare, salted_hmac
from .validators import ASCIIUsernameValidator


class User(models.Model):
    username = models.CharField(
        _('username'),
        max_length=25,
        unique=True,
        help_text=_('Required. 25 characters or fewer. Letters, digits and _ only.'),
        validators=[ASCIIUsernameValidator()],
        error_messages={
            'unique': _("A _user with that username already exists."),
        },
    )
    password = models.CharField(_('password'), max_length=128)
    last_login = models.DateTimeField(_('last login'), blank=True, null=True)
    email = models.EmailField(_('email address'), unique=True)

    class Meta:
        db_table = '_user'
        verbose_name = verbose_name_plural = '用户信息表'

    def set_password(self, password):
        # TODO: 密码强度检验，密码hash存储
        self.password = password

    def send_email(self, subject, message, from_email=None, **kwargs):
        send_mail(subject, message, from_email, [self.email], **kwargs)

    def make_token(self):
        return self._make_token(_timestamp())

    def check_token(self, token):
        if not token:
            return False
        try:
            ts_b36, hash_str = token.split('-')
        except ValueError:
            return False

        try:
            ts = base36_to_int(ts_b36)
        except ValueError:
            return False

        if self._make_token(ts) != token:
            return False

        timestamp = _timestamp()
        if (timestamp - ts) > settings.PASSWORD_RESET_TIMEOUT:
            return False

        return True

    def _make_token(self, timestamp):
        ts_b36 = int_to_base36(timestamp)
        salt = settings.SALT
        value = self._make_hash_value(timestamp)
        secret = settings.SECRET_KEY
        hash_str = salted_hmac(
            salt, value, secret=secret, algorithm='sha256'
        ).hexdigest()[::2]
        token = "%s-%s" % (ts_b36, hash_str)
        return token

    def _make_hash_value(self, timestamp):
        return f'{self.pk}{self.password}{timestamp}{self.email}'


def _timestamp():
    dt = datetime.now()
    return int((dt - datetime(2001, 1, 1)).total_seconds())


class LoginToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tokens')
    token = models.CharField(max_length=256)


from folder.models import Folder
# 引入内置信号
from django.db.models.signals import post_save
# 引入信号接收器的装饰器
from django.dispatch import receiver


class Profile(models.Model):
    # 对应django自带的user
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    # 对应的根目录
    root_folder = models.ForeignKey(Folder, null=True, on_delete=models.DO_NOTHING, related_name='profile')

    def __str__(self):
        return '_user {}'.format(self.user.username)


# 信号接收函数，每当新建User实例的时候自动调用
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)


# 信号接收函数，每当更新User实例的时候自动调用
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    pass
    # instance.profile.save()


# 信号接收函数，每当新建Profile实例的时候自动调用
@receiver(post_save, sender=Profile)
def create_root_folder(sender, instance, created, **kwargs):
    # pass
    if created:
        root_folder = Folder.objects.create()
        instance.root_folder = root_folder
        instance.save()
