# coding=utf-8

from django.db import models
from django.db.models import Q
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager, Group, AbstractUser
from django.utils import timezone
from rest_framework.utils import model_meta
from utils.exceptions import CustomError
from django.conf import settings
from utils.wx.WXBizDataCrypt import WXBizDataCrypt
from utils.wx.wechat import WeChat
from apps.WechatApplet.models import WechatApplet

class UserManager(BaseUserManager):
    def create_superuser(self, username, password, **extra_fields):
        u = self.create_user(User.EMPLOYEE, username, password, **extra_fields)
        u.is_active = True
        u.is_superuser = True
        u.save(using=self._db)
        return u

    def create_user(self, type, username, password=None, **extra_fields):
        if not username:
            raise CustomError(u'请输入账号！')
        count = User.objects.filter(username=username).count()
        if count > 0:
            raise CustomError(u'该账号已存在！')
        user = self.model(
            type=type,
            username=username,
            is_superuser=False,
            last_login=timezone.now(),
            **extra_fields
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

class User(AbstractBaseUser, PermissionsMixin):
    EMPLOYEE = 1
    CUSTOMER = 2
    TYPE_CHOICES = (
        (EMPLOYEE, u'员工'),  # 内部员工
        (CUSTOMER, u'客户'),  # 客户
    )
    username = models.CharField(verbose_name=u'用户名', max_length=30, unique=True, db_index=True,
                                help_text=u'不多于20个字符。只能用字母、数字和字符。')
    # password = models.CharField(u'密码', max_length=128, blank=True,)

    is_active = models.BooleanField(verbose_name=u'是否可用', default=True, editable=False)
    date_joined = models.DateTimeField(verbose_name=u'注册时间', auto_now_add=True, editable=False)
    type = models.PositiveSmallIntegerField(verbose_name=u"类型", choices=TYPE_CHOICES, editable=False, default=CUSTOMER)
    name = models.CharField(max_length=20, verbose_name=u"姓名")
    gender = models.PositiveSmallIntegerField(choices=settings.GENDER_CHOICES, verbose_name=u"性别",
                                              default=settings.MALE)
    face = models.CharField(max_length=200, verbose_name=u'头像', null=True)
    ID_card = models.CharField(max_length=18, verbose_name=u"身份证号", null=True, blank=True)
    address = models.CharField(max_length=100, verbose_name=u"家庭住址", null=True, blank=True)
    tel = models.CharField(max_length=15, verbose_name=u"手机", null=True, )
    position = models.CharField(max_length=15, verbose_name=u"岗位", null=True)
    create_user = models.ForeignKey('self', verbose_name='创建者', null=True, on_delete=models.PROTECT)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = []

    class Meta:
        db_table = "auth_user"
        verbose_name = u"人员管理"
        unique_together = [
            ('username')
        ]
        ordering = ['-id']
        default_permissions = ()
        permissions = [
        ]

    def __unicode__(self):
        return self.username

    def change_password(self, new_password, confirm_password, old_password):
        if new_password != confirm_password:
            raise CustomError(u'两次输入的密码不一致，请检查')
        if not self.check_password(old_password):
            raise CustomError(u'原密码输入错误，请检查')
        self.set_password(new_password)
        self.save()

    def update_item(self, validated_data):
        def update():
            info = model_meta.get_field_info(self)
            for attr, value in validated_data.items():
                if attr in info.relations and info.relations[attr].to_many:
                    field = getattr(self, attr)
                    field.set(value)
                else:
                    setattr(self, attr, value)

        if not 'username' in validated_data:
            raise CustomError(u'账号不能为空！')
        count = User.objects.filter(username=validated_data['username']).exclude(id=self.id).count()
        if count > 0:
            raise CustomError(u'该账号已存在！')

        if not 'password' in validated_data or not validated_data['password']:
            validated_data['password'] = self.password
            update()
        else:
            update()
            self.set_password(validated_data['password'])
        self.save()
        return self

    def is_login(self):
        if self.is_authenticated and self:
            return True
        return False

class CustomerWechat(models.Model):
    wechat_app = models.ForeignKey(WechatApplet, verbose_name=u'小程序', on_delete=models.PROTECT, editable=False)
    customer = models.ForeignKey(User, verbose_name=u'用户', on_delete=models.PROTECT, editable=False, null=True)
    openid = models.CharField(max_length=512, verbose_name=u"openid")
    session_key = models.CharField(max_length=512, verbose_name=u'session_key', null=True)

    # 保存客户+小程序的关联信息。如果一个客户登录多个小程序，这里会有多条数据
    class Meta:
        db_table = 'customer_wechat'
        verbose_name = u'微信客户'
        unique_together = [
            ('openid', 'wechat_app')
        ]
        default_permissions = ()

    @staticmethod
    def login(code, appid):
        wechat_applet = WechatApplet.getByAppid(appid)
        res = WeChat.code2Session(appid, wechat_applet.secret, code)
        instance = CustomerWechat.objects.filter(openid=res['openid'], wechat_app__authorizer_appid=appid).first()
        if not instance:
            instance = CustomerWechat.objects.create(
                wechat_app=wechat_applet,
                openid=res['openid'],
                session_key=res['session_key']
            )
        else:
            instance.session_key = res['session_key']
            instance.save()
        return instance

    @staticmethod
    def bindWechat(appid, openid, phoneEncryptedData, phoneIv):
        customer_wechat = CustomerWechat.objects.filter(openid=openid, wechat_app__authorizer_appid=appid).first()
        if not customer_wechat:
            raise CustomError(u'未找到相应的微信客户！')

        pc = WXBizDataCrypt(appid, customer_wechat.session_key)
        phon_data = pc.decrypt(phoneEncryptedData, phoneIv)
        tel = phon_data['purePhoneNumber']

        if customer_wechat.customer and customer_wechat.customer.username == tel:
            # 已绑定用户，且用户账号和手机号一致
            return customer_wechat.customer

        # 用户用手机号、密码登录后，在绑定微信，两个号码可能会不符
        # 张三是绑定用户。 张三的账号，在李四小程序上登录，绑定信息时，手机号可能不符。
        # 这种情况，应该返回tel对应的账号，或者创建tel账号
        user = User.objects.filter(username=tel).first()
        if not user:
            # 密码默认手机号
            user = User.objects.create_user(User.CUSTOMER, tel, password=tel,
                                            **{
                                                'tel': tel,
                                                'name': tel,
                                            }
                                            )

        customer_wechat.customer = user
        customer_wechat.save()
        return user

Group.add_to_class('create_user',
                   models.ForeignKey(User, verbose_name=u"创建人", on_delete=models.PROTECT, editable=False))
