#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    新老标签数据映射转换
"""
import json
import multiprocessing
from collections import defaultdict
from itertools import chain
from django.core.management import BaseCommand

from talos.models.tractate import (
    TractateTag,
    TractateNewTag,
)
from talos.services import AgileTagService

count = 100


class Command(BaseCommand):
    def new_mapping_old(self, has_bind_new_tag_tractate_ids):

        # 老标签 id
        _new_tag_ids = list(TractateNewTag.objects.values_list("tag_id", flat=True).distinct())
        new_mapping_old_dic = {}
        for j in range(0, len(_new_tag_ids), count):
            _mapping_tag_ids = _new_tag_ids[j: j + count]
            # 取到映射数据
            new_mapping_old_dic.update(
                AgileTagService.get_relation_old_tags_by_agile_tag_ids(_mapping_tag_ids)
            )

        # 走索引查新标签
        for i in range(0, len(has_bind_new_tag_tractate_ids), count):
            _search_ids = has_bind_new_tag_tractate_ids[i: i + count]

            print("new mapping old count:{}; nums:{}".format((i // count) + 1, len(_search_ids)))

            # 把数据转换下，存成字典
            tracate_new_mapping_old_dic = defaultdict(list)
            tracate_new_mapping_old_bluk_create_list = []

            # 根据新老标签映射关系，批量创建老标签数据
            for trac_id, t_id in TractateNewTag.objects.filter(
                    tractate_id__in=_search_ids
            ).values_list("tractate_id", "tag_id"):
                old_tag_ids = new_mapping_old_dic.get(int(t_id), [])
                tracate_new_mapping_old_dic[trac_id].extend(old_tag_ids)
            else:
                _old_tractate_ids = set(tracate_new_mapping_old_dic.keys())
                tractate_old_tag_has_in_sql = set(TractateTag.objects.filter(
                    tractate_id__in=_old_tractate_ids).values_list("tractate_id", flat=True).distinct())

                for k, v in tracate_new_mapping_old_dic.items():
                    v = list(filter(None, set(v)))
                    if k and v and k not in tractate_old_tag_has_in_sql:
                        print("write to api_tractate_tag tractate_id:{}; old_tags_id:{}".format(k, json.dumps(v)))
                        tracate_new_mapping_old_bluk_create_list.extend(
                            [TractateTag(
                                tractate_id=k,
                                tag_id=_old_tag_id
                            ) for _old_tag_id in set(v)]
                        )
                if tracate_new_mapping_old_bluk_create_list:
                    TractateTag.objects.bulk_create(tracate_new_mapping_old_bluk_create_list)


    def old_mapping_new(self, has_mapping_old_tag_tractate_ids):
        # 取到所有需要映射新标签的帖子id,同时需要去除已经同步老标签数据的新帖子
        need_old_mapping_new_tractate_ids = list(
            TractateTag.objects.exclude(
                tractate_id__in=has_mapping_old_tag_tractate_ids
            ).values_list("tractate_id", flat=True).distinct()
        )

        # 新老标签映射取出来
        old_mapping_new_dic = {}
        _old_tag_ids = list(TractateTag.objects.values_list("tag_id", flat=True).distinct())
        for j in range(0, len(_old_tag_ids), count):
            _mapping_tag_ids = _old_tag_ids[j: j + count]
            # 取到映射数据
            old_mapping_new_dic.update(
                AgileTagService.get_relation_agile_tags_by_old_tag_ids(_mapping_tag_ids)
            )

        for i in range(0, len(need_old_mapping_new_tractate_ids), count):
            _search_ids = need_old_mapping_new_tractate_ids[i: i + count]
            print("old mapping new count:{}; nums:{}".format((i // count) + 1, len(_search_ids)))

            # 把数据转换下，存成字典
            tracate_old_mapping_new_dic = defaultdict(list)
            tracate_old_mapping_new_bluk_create_list = []

            # 根据新老标签映射关系，批量创建老标签数据
            for trac_id, t_id in TractateTag.objects.filter(
                    tractate_id__in=_search_ids
            ).values_list("tractate_id", "tag_id"):
                old_tag_ids = old_mapping_new_dic.get(int(t_id), [])
                tracate_old_mapping_new_dic[trac_id].extend(old_tag_ids)
            else:
                _old_tractate_ids = set(tracate_old_mapping_new_dic.keys())
                tractate_new_tag_has_in_sql = set(TractateNewTag.objects.filter(
                    tractate_id__in=_old_tractate_ids).values_list("tractate_id", flat=True).distinct())

                for k, v in tracate_old_mapping_new_dic.items():
                    v = list(filter(None, set(v)))
                    if k and v and k not in tractate_new_tag_has_in_sql:
                        print("write to api_tractate_new_tag tractate_id:{}; new_tags_id:{}".format(k, json.dumps(v)))
                        tracate_old_mapping_new_bluk_create_list.extend(
                            [TractateNewTag(
                                tractate_id=k,
                                tag_id=_old_tag_id
                            ) for _old_tag_id in set(v)]
                        )
                if tracate_old_mapping_new_bluk_create_list:
                    TractateNewTag.objects.bulk_create(tracate_old_mapping_new_bluk_create_list)

    def handle(self, *args, **options):
        print("START")
        # 先从 新标签入手，取新标签对应的老标签
        _has_bind_new_tag_tractate_ids = list(TractateNewTag.objects.values_list("tractate_id", flat=True).distinct())

        print("new mapping old start")
        self.new_mapping_old(_has_bind_new_tag_tractate_ids)
        print("new mapping old end")

        print("old mapping new start")
        self.old_mapping_new(_has_bind_new_tag_tractate_ids)
        print("old mapping new end")

        print("END")
