import gevent
from django.conf import settings

from qa.models import Answer, Question, QuestionTagV3, AnswerTagV3
from talos.models.diary import Diary, DiaryTagV3
from talos.models.topic import Problem, ProblemTagV3
from talos.models.tractate import Tractate, TractateTagV3
from utils.rpc import rpc_client


CACHE_KEY = '{content_type}'
HISTORY_RECORD = 'record:{content_type}'
CONTENT_TYPE = ['diary', 'topic', 'question', 'answer', 'tractate']
CONTENT_TABLE_MAP = {
    'topic': Problem,
    'diary': Diary,
    'tractate': Tractate,
    'question': Question,
    'answer': Answer,
}

TAG_TABLE_MAP = {
    'topic': ProblemTagV3,
    'diary': DiaryTagV3,
    'tractate': TractateTagV3,
    'question': QuestionTagV3,
    'answer': AnswerTagV3,
}


class TagMapTool:
    """
    新老标签数据清洗
    """
    BATCH_SIZE = 50
    # doc: http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=36540529
    RPC_URL = 'doris/search/content_tagv3_info'

    @classmethod
    def current_model(cls, content_type):
        return CONTENT_TABLE_MAP.get(content_type)

    @classmethod
    def current_tag_model(cls, content_type):
        return TAG_TABLE_MAP.get(content_type)

    @classmethod
    def request_task(cls, _id, content_type):
        try:
            result = rpc_client[cls.RPC_URL](
                content_id=_id, content_type=content_type
            ).unwrap()
            # result = {
            #     "content_id": _id,
            #     "tags_info": {"first_solutions": [], "first_positions": [], "project_tags": [1, 2, 3, 4, 6]},
            #     "content_type": content_type,
            # }
        except:
            result = {}
        return result

    @classmethod
    def get_tag_map_result(cls, content_ids, content_type):
        result = []
        tasks = [gevent.spawn(cls.request_task, _id, content_type) for _id in content_ids]
        gevent.joinall(tasks)
        for res in tasks:
            result.append(res.value)

        return result

    @classmethod
    def get_content_ids(cls, content_type, start_id):
        model = cls.current_model(content_type)
        content_ids = list(model.objects.using(settings.SLAVE_DB_NAME).filter(
            id__gt=start_id, is_online=True,
        ).values_list('id', flat=True).order_by('id')[:cls.BATCH_SIZE])

        return content_ids

    @classmethod
    def create_info(cls, data, content_type):
        model = cls.current_tag_model(content_type)
        content_objects = []
        for content_id, _id in data:
            if content_type == 'topic':
                content_objects.append(
                    model(
                        tag_v3_id=_id,
                        problem_id=content_id,
                    ))
            elif content_type == 'diary':
                content_objects.append(
                    model(
                        tag_v3_id=_id,
                        diary_id=content_id,
                    ))
            elif content_type == 'tractate':
                content_objects.append(
                    model(
                        tag_v3_id=_id,
                        tractate_id=content_id,
                    ))
            elif content_type == 'question':
                content_objects.append(
                    model(
                        tag_v3_id=_id,
                        question_id=content_id,
                    ))
            elif content_type == 'answer':
                content_objects.append(
                    model(
                        tag_v3_id=_id,
                        answer_id=content_id,
                    ))
        return content_objects

    @classmethod
    def get_max_id(cls, content_type):
        model = cls.current_model(content_type)
        sql = """select id from api_{} order by id desc limit 1"""
        if content_type == 'topic':
            sql = sql.format('problem')
        else:
            sql = sql.format(content_type)

        db_max_id = model.objects.raw(sql)
        if not db_max_id:
            return 0
        max_id = db_max_id[0].id

        return max_id
