#! -*- coding: utf-8 -*-

from django.db import models
from django.db import connection
from django.contrib.auth.models import User

from api.models.tag import Tag
from api.models.user import User
from api.models.types import USER_TAG_CHOICES
from rpc.tool.log_tool import logging_exception

class UserTagRelation(models.Model):

    """
    user:     user
    related_tag: follow/create tag id
    """

    user = models.ForeignKey(User)
    related_tag = models.ForeignKey(Tag)
    tag_type = models.CharField(max_length=1, choices=USER_TAG_CHOICES)

    class Meta:
        db_table = 'relation_usertagrelation'
        app_label = 'relation'
        unique_together = (('user', 'related_tag', 'tag_type'),)

    @classmethod
    def remove_none_exist_tag(cls, user, tag_id):
        """ 选出follow或create的无效的tag并删除记录 """
        try:
            rels = cls.objects.filter(user=user, related_tag=tag_id)
        except cls.DoesNotExist:
            return
        for rel in rels:
            rel.delete()
        return

    @classmethod
    def _get_tags_obj(cls, user_id, tag_type):
        """ 获得tag对应的Tag对象 删除无效的tag """
        result = []
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return
        try:
            rels = cls.objects.filter(user=user, tag_type=tag_type).values()
        except cls.DoesNotExist:
            return result
        tag_ids = [rel['related_tag_id'] for rel in rels]
        for tag_id in tag_ids:
            try:
                tag = Tag.objects.get(id=tag_id)
            except Tag.DoesNotExist:
                cls.remove_none_exist_tag(user, tag_id)
                continue
            result.append(tag)
        return result

    @classmethod
    def follow_tag(cls, user_id, tag_id):
        """ follow a tag """
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            return

        try:
            rel = cls.objects.get_or_create(
                user=user,
                related_tag=tag,
                tag_type=USER_TAG_CHOICES.FOLLOWED
            )
        except:
            pass

        return

    @classmethod
    def create_tag(cls, user_id, tag_id):
        """ create a tag """
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            return
        rel = cls.objects.get_or_create(user=user,
                                        related_tag=tag,
                                        tag_type=USER_TAG_CHOICES.CREATED)
        return


    @classmethod
    def unfollow_tag(cls, user_id, tag_id):
        """ unfollow a tag """
        # try:
        #     user = User.objects.get(id=user_id)
        # except User.DoesNotExist:
        #     return
        # try:
        #     tag = Tag.objects.get(id=tag_id)
        # except Tag.DoesNotExist:
        #     return
        # try:
        #     rel = cls.objects.get(user=user,
        #                           related_tag=tag,
        #                           tag_type=USER_TAG_CHOICES.FOLLOWED)
        #     rel.delete()
        #     return
        # except cls.DoesNotExist:
        #     return
        return cls.unfollow_tags(user_id, [tag_id, ])

    @classmethod
    def unfollow_tags(cls, user_id, tag_ids):
        """
        批量取消关注 tag
        :param user_id: user_id
        :param tag_ids:  tags_ids list
        :return:
        """
        rel = cls.objects.filter(user=user_id, related_tag_id__in=tag_ids, tag_type=USER_TAG_CHOICES.FOLLOWED)
        rel.delete()
        return

    @classmethod
    def user_follow_tag(cls, user_id, tag_id):
        """ 判断是否followed指定的tag """
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            return
        try:
            rels = cls.objects.get(user=user,
                                   related_tag=tag,
                                   tag_type=USER_TAG_CHOICES.FOLLOWED)
        except cls.DoesNotExist:
            return False
        return True


    @classmethod
    def user_followed_by_tag_ids(cls, user_id, tag_ids):
        """
        通过 tag_ids 判断用户关注的状态
        :param user_id: user_id
        :param tag_ids: tag id  list
        :return: count
        """

        user_followed_tags = cls.objects.filter(user_id=user_id, related_tag_id__in=tag_ids,
                                                tag_type=USER_TAG_CHOICES.FOLLOWED).values_list("related_tag", flat=True)
        followed = False if set(tag_ids) - set(user_followed_tags) else True
        return followed

    @classmethod
    def followed_tags_obj(cls, user_id):
        """ 得到指定用户所有follow(tag_type为'0')的tag对象 """
        return cls._get_tags_obj(user_id, USER_TAG_CHOICES.FOLLOWED)

    @classmethod
    def created_tags_obj(cls, user_id):
        """ 得到指定用户所有create(tag_type为'1')的tag对象 """
        return cls._get_tags_obj(user_id, USER_TAG_CHOICES.CREATED)

    @classmethod
    def multi_follow_tags(cls, user_id, tag_ids):
        """
        this method is extremely tricky and only used for the sake of performance
        """
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            return
        tag_cnt = Tag.objects.filter(pk__in=tag_ids).count()
        if tag_cnt != len(tag_ids):
            return

        tbl_name = cls._meta.db_table
        get_field = cls._meta.get_field
        cols = '(`%s`,`%s`,`%s`)' % (get_field('user').column, get_field('related_tag').column, get_field('tag_type').column)
        vals = ','.join([
            '(%d,%d,\'%s\')' % (int(user_id), int(tag_id), USER_TAG_CHOICES.FOLLOWED) for tag_id in tag_ids
        ])

        try:
            cursor = connection.cursor()
            cursor.execute('INSERT IGNORE INTO `%(tbl_name)s` %(cols)s VALUES %(vals)s' % {
                'tbl_name':tbl_name,
                'cols':cols,
                'vals':vals,
            }) # django's SQL escaping f**king sucks here
        except:
            logging_exception()
