# coding=utf-8
from _mysql import IntegrityError

from django.db import transaction
from django.db.models import Q
from django.conf import settings
from gm_types.gaia import TAG_TYPE, ZONE_TYPE_V2

from api.models import Zone, OverHeadTopic, TagRelatedTag, OverHeadDiary
from hera.queries.zone import CampaignZoneDQ
from rpc.decorators import bind_context
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.dict_mixin import to_dict
from rpc.tool.log_tool import info_logger
from answer.models import OverHeadAnswer, OverHeadQuestion

uri_pre = 'hera/zone'


@bind_context(uri_pre + '/detail')
def zone_get(ctx, zone_id):
    """
    获取圈子详细信息
    """
    if zone_id is None:
        return None
    zone = Zone.objects.get(pk=zone_id)
    diaries = OverHeadDiary.objects.filter(zone_id=zone.id, deleted=False)
    # 2017.5.16 讨论贴替换为问答
    # topics = OverHeadTopic.objects.filter(zone_id=zone_id, deleted=False)
    answers = OverHeadAnswer.objects.filter(zone=zone_id, deleted=False)
    questions = OverHeadQuestion.objects.filter(zone=zone_id, deleted=False)
    zone_info = to_dict(obj=zone)
    zone_info['diary'] = [{'id': item.diary_id, 'rank': item.rank} for item in diaries]
    # zone_info['topic'] = [{'id': item.topic_id, 'rank': item.rank} for item in topics]
    zone_info['question'] = [{'id': item.question.id, 'rank': item.rank} for item in questions]
    zone_info['answer'] = [{'id': item.answer.id, 'rank': item.rank} for item in answers]

    return zone_info


@bind_context(uri_pre + '/getby_tag')
def zone_getbytag(ctx, tag_id):
    """
    根据tag获取该tag的圈子的数量
    :param ctx:
    :param tag_id:
    :return:
    """
    if tag_id is None:
        return 0
    count = Zone.objects.filter(tag_id=tag_id).count()
    return count


@transaction.atomic
@bind_context(uri_pre + '/edit')
def zone_edit(ctx, zone_info, zone_id=None, zone_type=ZONE_TYPE_V2.NORMAL_ZONE):
    """
    圈子编辑 2016-11-19 create by oldman
    :param zone_id:
    :param zone_type:
    """
    if zone_info is None:
        return None
    # 2017.5.16 讨论贴替换为问答
    # topics = zone_info.pop('topics')
    questions = zone_info.pop('questions')
    answers = zone_info.pop('answers')
    diaries = zone_info.pop('diaries')
    zone_info['zone_type'] = zone_type
    if zone_id is None:
        try:
            zone = Zone.objects.create(**zone_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            zone = Zone.objects.get(id=zone_id)
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException
        for k, v in zone_info.iteritems():
            setattr(zone, k, v)
        zone.save()
    # 2017.5.16 讨论贴替换为问答
    # old_topics = set(OverHeadTopic.objects.filter(zone_id=zone_id, deleted=False))
    # new_topics = set()
    old_answers = set(OverHeadAnswer.objects.filter(zone=zone_id, deleted=False))
    new_answers = set()
    old_questions = set(OverHeadQuestion.objects.filter(zone=zone_id, deleted=False))
    new_questions = set()
    old_diaries = set(OverHeadDiary.objects.filter(zone_id=zone_id, deleted=False))
    new_diaries = set()
    # 2017.5.16 讨论贴替换为问答
    # for topic in topics:
    #     _topic = OverHeadTopic.objects.get_or_create(zone_id=zone.id, topic_id=int(topic['id']))[0]
    #     _topic.rank = topic['rank']
    #     _topic.deleted = False
    #     _topic.save()
    #     new_topics.add(_topic)
    for answer in answers:
        _answer= OverHeadAnswer.objects.get_or_create(zone=zone.id, answer_id=int(answer['id']))[0]
        _answer.rank = answer['rank']
        _answer.deleted = False
        _answer.save()
        new_answers.add(_answer)

    for question in questions:
        _question= OverHeadQuestion.objects.get_or_create(zone=zone.id, question_id=int(question['id']))[0]
        _question.rank = question['rank']
        _question.deleted = False
        _question.save()
        new_questions.add(_question)

    for diary in diaries:
        _diary = OverHeadDiary.objects.get_or_create(zone_id=zone.id, diary_id=int(diary['id']))[0]
        _diary.rank = diary['rank']
        _diary.deleted = False
        _diary.save()
        new_diaries.add(_diary)
    # 2017.5.16 讨论贴替换为问答
    # for item in old_topics - new_topics:
    #     item.deleted = True
    #     item.save()

    for item in old_answers - new_answers:
        item.deleted = True
        item.save()

    for item in old_questions - new_questions:
        item.deleted = True
        item.save()

    for item in old_diaries - new_diaries:
        item.deleted = True
        item.save()

    return {'zone_id': zone.id}


@bind_context(uri_pre + '/query')
def zone_query(ctx, options):
    dqobj = CampaignZoneDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/get_overheadtopics')
def overheadtopics_get(ctx, zone_id):
    """
    根据zone_id获取顶置贴
    """
    if zone_id is None:
        return None
    overheadtopics = OverHeadTopic.objects.filter(zone_id=zone_id)
    overheadtopics_info = [{
                               'topic_id': item.topic.id,
                               'title': item.title,
                               'rank': item.rank,
                           } for item in overheadtopics]
    return overheadtopics_info


@bind_context(uri_pre + '/get_relatedtag')
def relatedtag_get(ctx, zone_id):
    """
    根据zone_id获取关联圈子
    """
    if zone_id is None:
        return None
    relatedtag = TagRelatedTag.objects.filter(zone_id=zone_id)
    relatedtag_info = [{
                           'tag_id': item.relatedzone.id,
                           'rank': item.rank,
                       } for item in relatedtag]
    return relatedtag_info


@bind_context(uri_pre + '/edit_overheadtopics')
def overheadtopics_edit(ctx, zone_id, overheadtopics_info):
    """
    编辑项目圈子的顶置贴
    """
    if zone_id is None or overheadtopics_info is None:
        return None
    old_overheadtopics = set(OverHeadTopic.objects.filter(zone_id=zone_id))
    new_overheadtopics = set(OverHeadTopic.objects.get_or_create(
        zone_id=zone_id,
        topic_id=item['topic_id'],
        title=item['title'],
        rank=item['rank']
    )[0] for item in overheadtopics_info)
    for item in (old_overheadtopics - new_overheadtopics):
        item.delete()


@bind_context(uri_pre + '/edit_relatedtag')
def relatedtag_edit(ctx, zone_id, relatedtags_info):
    """
    编辑项目圈子的关联tag
    """
    if zone_id is None or relatedtags_info is None:
        return None
    old_relatedzones = set(TagRelatedTag.objects.filter(zone_id=zone_id))
    new_relatedzones = set(TagRelatedTag.objects.get_or_create(
        zone_id=zone_id,
        relatedzone_id=item['tag_id'],
        rank=item['rank']
    )[0] for item in relatedtags_info)
    for item in (old_relatedzones - new_relatedzones):
        item.delete()


@bind_context(uri_pre + '/choices')
def zone_choices(ctx, q='', page=1, num=30, initial=None, tag_type=None):
    page = int(page)
    num = int(num)

    if initial is not None:
        if isinstance(initial, (list, tuple)):
            qry = Q(id__in=initial)
        else:
            qry = Q(id=initial)
    else:
        qry = Q(id__contains=q) | Q(tag__name__contains=q)
    if tag_type is not None:
        if isinstance(tag_type, (list, tuple)):
            qry &= Q(tag__tag_type__in=tag_type)
        else:
            qry &= Q(tag__tag_type=tag_type)
    qry &= Q(is_online=True)
    query = Zone.objects.using(settings.SLAVE_DB_NAME).filter(qry).order_by('-id')
    total_count = query.count()
    start_pos = (page - 1) * num
    start_pos = start_pos if start_pos >= 0 else 0
    results = [
        {
            'id': obj.id,
            'text': u'{}:{}/{}'.format(
                obj.id, obj.tag.name, TAG_TYPE.getDesc(obj.tag.tag_type)),
        } for obj in query[start_pos: start_pos + num]
        ]
    return {'total_count': total_count, 'results': results, 'page': page, 'num': num}
