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

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

from api.models import CashBackOrder
from api.models import CASH_BACK_STATUS, PROBLEM_REVIEW_STATUS_CHOICES, DIARY_CONTENT_LEVEL
from services.talos_service import diary_num_and_cover_by_id
from talos.models.diary import Diary, DiaryTagV3
from talos.services.user import UserService
from talos.services.order import OrderService
from talos.services.hospital import HospitalService
from talos.services.goods import GoodsService

from . import TalosDataSQLQuery


class DiaryDB(DataBuilder):
    def _get_cashback_order(self, obj):
        var_name = '__get_cashback_order'
        key = obj.order_id

        def get_object(obj):
            object_ = CashBackOrder.objects.get(order_id=obj.order_id) if obj.order_id else None
            return object_

        object_ = getattr(getattr(self, var_name, {}), key, None)
        if not object_:
            object_ = get_object(obj)
            setattr(getattr(self, var_name, {}), key, object_)
        return object_

    def getval_user__last_name(self, obj):
        user = UserService.get_user_by_user_id(obj.user_id)
        return user.nickname

    def getval_doctor__name(self, obj):
        return obj.doctor.name

    def getval_hospital__name(self, obj):
        hospital = HospitalService.get_hospital_from_hospital_id(obj.hospital_id)
        return hospital.name

    def getval_service__name(self, obj):
        service = GoodsService.get_service_by_service_id(obj.service_id)
        return service.name

    def getval_is_cash_back(self, obj):
        order = OrderService.get_order_from_order_id(obj.order_id)
        if order is not None and order.cash_back_status == CASH_BACK_STATUS.SUCCESS:
            return True
        return False

    def getval_cash_back_time(self, obj, default=''):
        cash_back_order = self._get_cashback_order(obj)
        if cash_back_order:
            return str(cash_back_order.created_at)

    def getval_cash_back_order_id(self, obj, default=''):
        """
        返现号
        """
        cash_back_order = self._get_cashback_order(obj)
        if cash_back_order:
            return cash_back_order.id

    def getval_has_service(self, obj):
        return True if obj.service_id else False

    def getval_has_doctor(self, obj):
        return True if obj.doctor_id else False

    def getval_not_empty(self, obj):
        # return True if obj.diary_amount != 0 else False
        diary_amount = diary_num_and_cover_by_id(id=obj.id).get('diary_amount')
        return True if diary_amount != 0 else False

    def getval_to_check_num(self, obj):
        q = Q(review_status=PROBLEM_REVIEW_STATUS_CHOICES.NOT_REVIEW) & Q(is_online=True)
        return obj.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.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.get_index_rank()[2]

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

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

    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_tag_v3_ids(self, obj):
        return list(
            DiaryTagV3.objects.filter(diary_id=obj.id).values_list("tag_v3_id", flat=True))


@DB
class DiaryDQ(TalosDataSQLQuery):
    model = Diary
    data_model = DiaryDB

    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__isnull=False,
            order__cash_back_status=CASH_BACK_STATUS.WAIT,
        )
        if srch_val == '1':
            q &= Q(
                topics__review_status=PROBLEM_REVIEW_STATUS_CHOICES.NOT_REVIEW,
                topics__is_online=True,
            )
            self.distinct = True
        return q

    def filter_cash_back_status(self, srch_key, srch_val, regex=False):
        if not srch_val:
            return None
        q = None
        if srch_val == '1':
            # 待返现日记本
            q = Q(service_id__isnull=False) & Q(order_id__isnull=False) & Q(order__cash_back_status=CASH_BACK_STATUS.WAIT)
        elif srch_val == '2':
            # 已返现日记本
            q = Q(service_id__isnull=False) & Q(order_id__isnull=False) & 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':
            self.distinct = True
            return Q(topics__is_online=True)
        else:
            return Q()

    def filter_service_is_online(self, srch_key, srch_val, regex=False):
        if srch_val == '1':
            return Q(service__is_online=True)
        elif srch_val == '0':
            return 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(diary_operations__operation=srch_val)
        q &= Q(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(diary_rank__additional_score=0) | Q(diary_rank__isnull=True)
        if srch_val == '1':
            return ~q
        elif srch_val == '0':
            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)
