# -*- coding: utf8 -*-

import uuid
import traceback

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.hashers import check_password
from gm_types.gaia import LOGIN_AUTH_TYPE

from api.models import Area
from api.models.types import PLATFORM_CHANNEL, PROBLEM_FLAG_CHOICES
from api.tool.image_utils import get_full_path
from api.tool.common_tool import check_platform

from rpc.cache import count_cache


class Person(models.Model):
    """
    以下字段定义已复制到passport项目, 如需修改请联系passport负责人:
    id
    user
    """

    class Meta:
        app_label = 'api'

    id = models.UUIDField(primary_key=True, default=uuid.uuid1, editable=False)
    create_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True, db_index=True)
    user = models.OneToOneField(User, related_name="person")
    phone = models.CharField(
        max_length=20, verbose_name="手机号", unique=True, null=True)
    points = models.IntegerField(default=0, verbose_name=u'积分')
    platform = models.IntegerField(
        choices=PLATFORM_CHANNEL, default=PLATFORM_CHANNEL.UNKNOWN, verbose_name=u'用户来自哪个平台[iOS, Android, m站, pc站]'
    )
    password = models.CharField(
        max_length=128, verbose_name="新个人密码", blank=True, default='')
    is_puppet = models.BooleanField(u'是否马甲用户', default=False)
    email = models.CharField(max_length=64, unique=True, null=True)
    area = models.ForeignKey(Area, verbose_name='用户地区', related_name="persons")
    # update_time = models.DateTimeField(verbose_name=u'最后修改时间', auto_now=True, blank=True, null=True)

    @property
    def is_from_wanghong(self):
        try:
            return self.fenxiao is not None
        except Exception:
            return False

    def data(self, with_phone=False):
        from api.tool.user_tool import filter_user_nick_name, get_user_extra_by_user_id
        user_extra = get_user_extra_by_user_id(self.user.id)
        return {
            'id': self.id.hex,
            'uid': self.user.id,
            'phone': with_phone and self.phone or '',
            'points': self.points,
            'nickname': filter_user_nick_name(self.user),
            'portrait': get_full_path(user_extra.portrait) or get_full_path(u'img%2Fuser_portrait.png'),
            'password': True if self.password else False,
        }

    @classmethod
    def get_or_create(cls, user, platform=None):
        from api.tool.user_tool import get_user_extra_by_user_id

        platform = check_platform(platform)
        phone = None

        try:
            person = cls.objects.get(user=user)

            if platform:
                person.platform = platform
                person.save()
            return person

        except cls.DoesNotExist:
            pass

        get_user_extra_by_user_id(user.id)

        if len(user.username) == 11:
            u = user._get_full_field_content_('username')
            if u.isdigit():
                phone = u
        else:
            if user.userextra:
                p = user.userextra.phone
                if p and len(p) == 11 and p.isdigit():
                    phone = p

        if phone is not None:
            try:
                person = cls.objects.get(phone=phone)
                if len(person.user.username) == 11:
                    phone = None
                else:
                    if person.user.id != user.id:
                        person.phone = None

                        if platform:
                            person.platform = platform
                        person.save()
            except cls.DoesNotExist:
                pass

        person, created = cls.objects.get_or_create(
            user=user, platform=platform
        )
        if created:
            person.phone = phone

            if platform:
                person.platform = platform
            person.save()
        return person

    @classmethod
    def get_user_by_type_id(cls, account_type, account_id):
        if not account_id:
            return None

        per_obj = None
        try:
            if account_type == LOGIN_AUTH_TYPE.phone:
                per_obj = Person.objects.get(phone=account_id)
            elif account_type == LOGIN_AUTH_TYPE.Email:
                per_obj = Person.objects.get(email=account_id)
            else:
                pass
            return per_obj and per_obj.user
        except Person.DoesNotExist:
            pass
        except:
            print(traceback.format_exc())
        return None


    def _topic_count(self):
        Q = models.Q
        topic_filter = Q(flag=PROBLEM_FLAG_CHOICES.NORMAL, is_online=True)
        diary_q = Q(diary__isnull=True) | (
            Q(diary__isnull=False) & Q(diary__is_online=True))
        topic_filter = topic_filter & diary_q
        from talos.models.topic import Problem
        topic_number = Problem.objects.filter(user_id=self.user_id).filter(topic_filter).count()
        return topic_number

    def incr_topic_count(self):
        key = "topic:%s:count" % self.id.hex
        number = count_cache.get(key)
        expire_time = 3600
        if number:
            count_cache.setex(key, expire_time, int(number) + 1)
        else:
            topic_number = self._topic_count()
            count_cache.setex(key, expire_time, topic_number)

    def decr_topic_count(self):
        key = "topic:%s:count" % self.id.hex
        number = count_cache.get(key)
        expire_time = 3600
        if number:  # redis 中读取的值为string  if '0' 为 True 小心踩坑
            count_cache.setex(key, expire_time, int(number) - 1)
        else:
            topic_number = self._topic_count()
            count_cache.setex(key, expire_time, topic_number)

    @property
    def topic_count(self):
        key = "topic:%s:count" % self.id.hex
        number = count_cache.get(key)
        if not number:
            expire_time = 3600
            topic_number = self._topic_count()
            count_cache.setex(key, expire_time, topic_number)
            return topic_number
        else:
            return number

    def get_topic_count_db(self):
        number = self._topic_count()
        self.set_topic_count(number)
        return number

    def set_topic_count(self, number):
        if not isinstance(number, int):
            return False
        key = "topic:%s:count" % self.id.hex
        expire_time = 3600
        return count_cache.setex(key, expire_time, number)

    def incr_vote_count(self):
        key = "vote:%s:count" % self.id.hex
        count_cache.incr(key)

    def decr_vote_count(self):
        key = "vote:%s:count" % self.id.hex
        count_cache.decr(key)

    @property
    def vote_count(self):
        key = "vote:%s:count" % self.id.hex
        num = count_cache.get(key)
        if num:
            return num
        else:
            return '0'

    def __unicode__(self):
        return u"%d:%s" % (self.user.id, self.phone)

    @property
    def points_deduction_yuan(self):
        return self.points / settings.POINTS_PER_YUAN


def validate_password(enter_password, obj):
    if check_password(enter_password, obj.password):
        return True
    if isinstance(obj, Person):
        obj2 = obj.user
    elif isinstance(obj, User):
        obj2 = obj.person
    else:
        return False
    return check_password(enter_password, obj2.password)
