from collections import defaultdict
from cached_property import cached_property

import time
from django.core.management import BaseCommand
from django.conf import settings
from gm_types.gaia import TAG_TYPE, TAG_V3_TYPE

from talos.models.diary import (
    Diary,
    DiaryTagV3,
    DiaryTag,
)
from talos.models.topic import (
    Problem,
    ProblemTag,
    ProblemTagV3,
)
from qa.models.answer import (
    Answer,
    AnswerTagV3,
    Question,
    QuestionTagV3,
    AnswerTag,
    QuestionTag,
)
from tags.models.tag import (
    TagV3,
    TagMapOldTag,
    Tag,
)

CONTENT_TYPE_MAP = {
    "diary": (Diary, DiaryTagV3, "diary_id", DiaryTag, 'tag_id'),
    "topic": (Problem, ProblemTagV3, "problem_id", ProblemTag, 'tag_id'),
    "question": (Question, QuestionTagV3, "question_id", QuestionTag, 'tag'),
    "answer": (Answer, AnswerTagV3, "answer_id", AnswerTag, 'tag'),
}


class TagTool(object):

    def __init__(self, content_type):

        self.content_model, self.relation_model_v3, self.content_field_id, self.relation_model_v1, self.tag_v1_field = CONTENT_TYPE_MAP.get(content_type)

    @cached_property
    def tags_v1(self):
        """所有1.0运营标签"""

        tag_types = [TAG_TYPE.YUNYING]
        # tag_types = [TAG_TYPE.CITY, TAG_TYPE.PROVINCE, TAG_TYPE.COUNTRY]
        tag1_ids = set(
            Tag.objects.using(settings.ZHENGXING_DB).filter(
                tag_type__in=tag_types, is_online=True).values_list('id', flat=True)
        )
        return tag1_ids

    @cached_property
    def get_tag3(self):
        """所有3.0运营标签 包括交易运营、社区运营"""

        tag_types = [TAG_V3_TYPE.EXCHANGE, TAG_V3_TYPE.COMMUNITY]
        # tag_types = [TAG_V3_TYPE.CITY, TAG_V3_TYPE.PROVINCE, TAG_V3_TYPE.COUNTRY]
        tag3_ids = set(
            TagV3.objects.using(settings.ZHENGXING_DB).filter(
                tag_type__in=tag_types, is_online=True).values_list('id', flat=True)
        )
        return tag3_ids

    @cached_property
    def tag1_map_tag3(self):
        """1.0运营标签与3.0标签的映射关系"""

        maps = TagMapOldTag.objects.using(settings.ZHENGXING_DB).filter(
            old_tag_id__in=self.tags_v1).values_list('tag_id', 'old_tag_id')

        tag_map_old_tag = {}
        for tag_id, old_tag_id in maps:
            if not tag_id or tag_id not in self.get_tag3:
                continue

            tag_map_old_tag[old_tag_id] = tag_id

        return tag_map_old_tag

    def get_tag1_content_map(self, tag_ids):
        """1.0运营标签与内容关联关系"""

        tag_content_map = defaultdict(set)
        query = {"{}__in".format(self.tag_v1_field): list(tag_ids)}
        fields = [self.content_field_id, self.tag_v1_field]
        tags = self.relation_model_v1.objects.using(settings.SLAVE_DB_NAME).filter(**query).values_list(
            *fields
        )
        for content_id, tag_id in tags:
            tag_content_map[tag_id].add(content_id)

        return dict(tag_content_map)

    def get_tag3_content_map(self, tag1_ids):
        """3.0运营标签与内容关联关系"""

        tag1_content_map = self.get_tag1_content_map(tag1_ids)
        if not tag1_content_map:
            return []

        all_relations = []
        tag3_ids = []
        for tag1_id in tag1_ids:
            tag3_id = self.tag1_map_tag3.get(tag1_id)
            content_ids = tag1_content_map.get(tag1_id)

            if not all([tag3_id, content_ids]):
                continue

            tag3_ids.append(tag3_id)
            all_relations.extend([(tag3_id, content_id) for content_id in content_ids])

        fields = ['tag_v3_id', self.content_field_id]

        exist_relations = set(
            self.relation_model_v3.objects.using(settings.SLAVE_DB_NAME).filter(
                tag_v3_id__in=tag3_ids).values_list(*fields)
        )
        print("所有关系：", all_relations)
        print("已经存在的关系：", exist_relations)
        need_create = set(all_relations) - exist_relations

        creation = [{self.content_field_id: content_id, 'tag_v3_id': tag_id} for tag_id, content_id in need_create]
        print("需要创建的关系", creation)

        return [
            self.relation_model_v3(**item)
            for item in creation
        ]


class Command(BaseCommand):

    """python django_manage.py operation_tag_map --content_type="""

    def add_arguments(self, parser):
        parser.add_argument(
            '--content_type',
            help=u'内容类型(单选), choice is diary/topic/question/answer ...'
        )

    def handle(self, *args, **options):
        begin = time.time()
        content_type = options['content_type']
        if content_type not in CONTENT_TYPE_MAP:
            print("内容参数有误，请重新输入")
            return

        t = TagTool(content_type=content_type)
        tag1_ids = list(t.tags_v1)

        create_info = []
        while tag1_ids:
            if not tag1_ids:
                break

            create_info.extend(t.get_tag3_content_map(tag1_ids[:10]))
            tag1_ids = tag1_ids[10:]

        print('需要创建关联关系个数', len(create_info))
        while create_info:
            if not create_info:
                break
            t.relation_model_v3.objects.bulk_create(create_info[:500])
            create_info = create_info[500:]

        print('Done cost {}s'.format(int(time.time() - begin)))
