# -*- coding: UTF-8 -*-

from datetime import datetime

from django.conf import settings
from django.db.models import Q, F, Max
from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_dataquery.db import DB
from gm_dataquery.client import Model

from gm_types.gaia import CASH_BACK_STATUS, PROBLEM_REVIEW_STATUS_CHOICES, DIARY_CONTENT_LEVEL
from gm_types.gaia import USER_CLASSIFY
from gm_upload.utils.image_utils import Picture
from services.talos_service import diary_num_and_cover_by_id
from .models import DiaryVM
from talos.models.diary.diaryfeed import TIDiaryScore
from talos.models.diary.diarycheck import DiaryCheck
from talos.models.diary import DiaryTagV3
from statistic.models import ClassifyUser

class DiaryVMDB(DataBuilder):
    def getval_user__last_name(self, obj):
        return obj.user_nickname

    def getval_doctor__name(self, obj):
        return obj.doctor_name

    def getval_hospital__name(self, obj):
        return obj.hospital_name

    def getval_service__name(self, obj):
        return obj.service_name

    def getval_is_cash_back(self, obj):
        return bool(obj.order_id and obj.order_cash_back_status == CASH_BACK_STATUS.SUCCESS)

    def getval_cash_back_time(self, obj, default=''):
        return str(obj.order_cashback_time or '')

    def getval_has_service(self, obj):
        return bool(obj.service_id)

    def getval_has_doctor(self, obj):
        return bool(obj.doctor_id)

    def getval_diary_amount(self, obj):
        diary_amount = diary_num_and_cover_by_id(id=obj.id).get('diary_amount')
        return diary_amount

    def getval_to_check_num(self, obj):
        q = Q(review_status=PROBLEM_REVIEW_STATUS_CHOICES.NOT_REVIEW) & Q(is_online=True)
        return obj.relobj.topics.filter(q).count()

    def getval_content(self, obj):
        return DIARY_CONTENT_LEVEL.getDesc(obj.content_level)

    def getval_rank_score(self, obj):
        heat_score, audit_score, choucheng_score = obj.relobj.get_index_rank()
        diary_score = heat_score * settings.DIARY_SCORE_WEIGHT['HEAT_SCORE_WEIGHT'] + \
            audit_score * settings.DIARY_SCORE_WEIGHT['AUDIT_SCORE_WEIGHT'] + \
            choucheng_score * settings.DIARY_SCORE_WEIGHT['CHOUCHENG_SCORE_WEIGHT']
        return '%.3f' % diary_score

    def getval_choucheng_score(self, obj):
        return obj.relobj.get_index_rank()[2]

    def getval_tag_name(self, obj):
        return u'、'.join([t.name for t in obj.relobj.tags])

    def getval_additional_score(self, obj):
        diary_rank = getattr(obj.relobj, 'diary_rank', False)
        return diary_rank.additional_score if diary_rank else 0

    def getval_get_diary_operate(self, obj):
        return obj.relobj.get_diary_operate

    def getval_vote_num(self, obj):
        return obj.relobj.vote_num

    # def getval_tags(self, obj):
    #     return list(obj.rel_tags.all().values_list('tag_id', flat=True))

    def getval_tag_v3_ids(self, obj):
        return list(DiaryTagV3.objects.filter(diary_id=obj.id).values_list("tag_v3_id", flat=True))

    def batch_feed_weight_id(self, data, items):
        raw = Model('mimas', 'diaryfeedweight', ['id', 'diary_id']).query(
            diary_id=[x.id for x in items]
        )['data']
        _map = {x['diary_id']: x['id'] for x in raw}
        [x.update(feed_weight_id=_map.get(x['pk'])) for x in data]
        return data

    def batch_tidb_score(self, data, items):
        query = TIDiaryScore.objects.filter(diary_id__in=[x.id for x in items])
        ids = [x['maxid'] for x in query.values('diary_id').annotate(maxid=Max('id'))]
        qlist = TIDiaryScore.objects.filter(id__in=ids)
        _map = {
            x.diary_id: {
                'score': x.score,
                'quality_score': x.quality_score,
                'social_score': x.social_score,
                'category_score': x.category_score,
                'profit_score': x.profit_score,
                'update_score': x.update_score,
                'time_score': x.time_score,
                'adjust_score': x.adjust_score,
            } for x in qlist
        }
        [x.update(_map.get(x['pk'], {})) for x in data]
        return data

    def getval_is_import(self, obj):
        return obj.relobj.is_import

    def getval_low_quality(self, obj):
        return obj.low_quality or 0

    def getval_low_quality_deal(self, obj):
        return obj.low_quality_deal

    def getval_diary_pre_cover(self, obj):
        cover = obj.relobj.cover
        _image_url = ""
        for image_info in cover:
            if image_info.get("desc", "") == "Before":
                _image_url = image_info.get("image", "")
                break
        return Picture(_image_url).raw

    def getval_diary_post_cover(self, obj):
        cover = obj.relobj.cover
        _image_url = ""
        for image_info in cover:
            if image_info.get("desc", "") == "After":
                _image_url = image_info.get("image", "")
                break
        return Picture(_image_url).raw

    def getval_diary_check_content(self, obj):
        diary_id = obj.relobj_id
        diary_check_obj = DiaryCheck.objects.filter(diary_id=diary_id).last()
        _content = ""
        if diary_check_obj:
            _content = diary_check_obj.check_content
        return _content

@DB
class DiaryDQ(DataSQLQuery):
    model = DiaryVM
    data_model = DiaryVMDB
    default_using = getattr(settings, 'MIMAS_HERA_READ_DB', '')

    def filter_is_real(self, srch_key, srch_val, regex=False):
        user_ids = ClassifyUser.objects.using(settings.SLAVE_DB_NAME).filter(
            classify=USER_CLASSIFY.MODEL).values_list('user_id', flat=True)
        q = Q(user_id__in=list(user_ids))
        if srch_val == u'1':
            return ~q
        else:
            return q

    def filter_created_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_last_modified(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_operation_time(self, srch_key, srch_val, regex=False):
        return self._qry_time_range(srch_key, srch_val, regex)

    def filter_is_cash_back(self, srch_key, srch_val, regex=False):
        q = ~Q(order_id__isnull=True) & Q(order_cash_back_status=CASH_BACK_STATUS.SUCCESS)
        if srch_val == u'1':
            return q
        else:
            return ~q

    def filter_wait_review(self, srch_key, srch_val, regex=False):
        q = Q(
            service_id__isnull=False, order_id__isnull=False,
            order_cash_back_status=CASH_BACK_STATUS.WAIT,
        )
        if srch_val == '1':
            q &= Q(not_review_topic_num__gt=0)
        return q

    def filter_cash_back_status(self, srch_key, srch_val, regex=False):
        if not srch_val:
            return None
        q = None
        q_default = Q(service_id__isnull=False) & Q(order_id__isnull=False)
        if srch_val == '1':
            # 待返现日记本
            q = q_default & Q(order_cash_back_status=CASH_BACK_STATUS.WAIT)
        elif srch_val == '2':
            # 已返现日记本
            q = q_default & Q(order_cash_back_status=CASH_BACK_STATUS.SUCCESS)
        return q

    def filter_has_service(self, srch_key, srch_val, regex=False):
        q = ~Q(service_id__isnull=True)
        if srch_val == u'1':
            return q
        else:
            return ~q

    def filter_has_doctor(self, srch_key, srch_val, regex=False):
        q = ~Q(doctor_id__isnull=True)
        if srch_val == u'1':
            return q
        else:
            return ~q

    def filter_not_empty(self, srch_key, srch_val, regex=False):
        if srch_val == u'1':
            return Q(not_empty=True)
        else:
            return Q()

    def filter_service_is_online(self, srch_key, srch_val, regex=False):
        q = None
        q_default = Q(service_id__isnull=False)
        if srch_val == '1':
            q = q_default & Q(service_is_online=True)
        elif srch_val == '0':
            q = q_default & Q(service_is_online=False)
        return q

    def filter_service_order_status(self, srch_key, srch_val, regex=False):
        if srch_val:
            return Q(order_status__in=srch_val)
        return Q()

    def filter_reply_num(self, srch_key, srch_val, regex=False):
        if srch_val and srch_val.isdigit():
            return Q(reply_num__gt=srch_val)
        return Q()

    def filter_operation(self, srch_key, srch_val, regex=False):
        self.distinct = True
        q = Q(relobj__diary_operations__operation=srch_val)
        q &= Q(relobj__diary_operations__operate_time__gte=F('audit_time')) | Q(audit_time__isnull=True)
        return q

    def filter_has_additional_score(self, srch_key, srch_val, regex=False):
        q = Q(diaryrank_additional_score=0) | Q(diaryrank_id__isnull=True)
        if srch_val == '1':
            return ~q
        elif srch_val == '0':
            return q

    def filter_tags(self, srch_key, srch_val, regex=False):
        if not isinstance(srch_val, list):
            srch_val = [srch_val]
        tag_ids = [int(tag) for tag in srch_val]
        return Q(rel_tags__tag_id__in=tag_ids)

    def filter_has_feed_weight(self, key, val, regex=False):
        if not val:
            return Q()
        now = str(datetime.now())
        data = Model('mimas', 'diaryfeedweight', ['id', 'diary_id']).query(
            start_time__lt=now, end_time__gt=now
        )['data']
        q = Q(id__in=[x['diary_id'] for x in data])
        if val == u'1':
            return q
        else:
            return ~q

    def filter_is_import(self, srch_key, srch_val, regex=False):
        return Q(relobj__is_import=bool(int(srch_val)))

    def filter_is_real_case(self, srch_key, srch_val, regex=False):
        user_ids = ClassifyUser.objects.using(settings.SLAVE_DB_NAME).filter(
            classify=USER_CLASSIFY.MODEL).values_list('user_id', flat=True)
        q = Q(user_id__in=list(user_ids))
        if srch_val == USER_CLASSIFY.MODEL:
            return q
        elif srch_val == USER_CLASSIFY.NORMAL:
            return ~q
        else:
            return Q()

    def filter_low_quality_deal(self, srch_key, srch_val, regex=False):

        if srch_val == '1':
            return Q(low_quality_deal=True)
        elif srch_val == '0':
            return Q(low_quality_deal=False)

    def filter_low_quality(self, srch_key, srch_val, regex=False):

        if srch_val == '1':
            return Q(low_quality__gte=1)

        elif srch_val == '0':
            return Q(low_quality=0)

    def filter_tag_v3_ids(self, srch_key, srch_val, regex=False):

        diary_ids = list(DiaryTagV3.objects.filter(
            tag_v3_id=int(srch_val)
        ).values_list("diary_id", flat=True))

        return Q(pk__in=diary_ids)
