# -*- coding: UTF-8 -*-
import datetime

from django.db.models import Q
from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_dataquery.db import DB
from django.db import transaction
from gm_types.gaia import SEARCH_KEYWORDS_POSITION, SEARCH_KEYWORDS_TYPE, HOT_SEARCH_JUMP_TYPE
from gm_types.error import ERROR
from rpc.tool.dict_mixin import to_dict
from api.models import SearchKeyword, User, SearchActivity, SearchKeywordOperationRecord
from api.models.search import TopicAggregation
from rpc.exceptions import GaiaRPCFaultException


class SearchKeywordDB(DataBuilder):
    def getval_cities_name(self, obj):
        return [x.name for x in obj.cities.all()]

    def getval_regions_name(self, obj):
        return [x.name for x in obj.regions.all()]

    def getval_time_range(self, obj):
        start_time = obj.start_time
        end_time = obj.end_time
        return str(start_time.strftime("%Y-%m-%d %H:%M:%S")) + '--' + str(end_time.strftime("%Y-%m-%d %H:%M:%S"))

    def getval_operate_user(self, obj):
        s = SearchKeywordOperationRecord.objects.filter(searchkeyword_id=obj.id).order_by('-operate_time').first()
        return s.operate_user.last_name if s else ''

    def getval_operate_time(self, obj):
        s = SearchKeywordOperationRecord.objects.filter(searchkeyword_id=obj.id).order_by('-operate_time').first()
        return str(s.operate_time.strftime("%Y-%m-%d %H:%M:%S")) if s else ''

    def getval_status(self, obj):
        if obj.start_time and obj.end_time:
            if obj.start_time <= datetime.datetime.now() <= obj.end_time:
                return u"是"
            else:
                return u"否"
        else:
            return u"否"


@DB
class SearchKeywordDQ(DataSQLQuery):
    model = SearchKeyword
    data_model = SearchKeywordDB
    distinct = True

    @staticmethod
    def params_check(_type, jump_type):
        if _type == SEARCH_KEYWORDS_TYPE.NEW_WIKI and jump_type != HOT_SEARCH_JUMP_TYPE.NORMAL:
            raise GaiaRPCFaultException(
                error=ERROR.UNIVERSAL,
                message=u'百科tab,跳转类型目前只支持正常搜索',
                data=None)

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        operate_user_id = kwargs.pop('operate_user_id')
        rank = kwargs.get('rank', '')
        start_time = kwargs.get('start_time', '')
        end_time = kwargs.get('end_time', '')
        if 'type' in kwargs.keys():
            kwargs['position'] = SEARCH_KEYWORDS_POSITION.HOT
            if self.model.objects.filter(keyword=kwargs['keyword'], type=kwargs['type'],
                                         position=SEARCH_KEYWORDS_POSITION.HOT).exists():
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'该词在此tab已配置,不能重复配置，如需增加地区请在原配置上添加', data=None)
            self.params_check(kwargs["type"], kwargs["jump_type"])

        else:
            kwargs['position'] = SEARCH_KEYWORDS_POSITION.DEFAULT
            if self.model.objects.filter(keyword=kwargs['keyword'], position=SEARCH_KEYWORDS_POSITION.DEFAULT).exists():
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'该词已配置,不能重复配置，如需增加地区请在原配置上添加', data=None)
            now = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            if start_time < now or end_time < now:
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'生效时间, 失效时间不能小于当前编辑时间', data=None)
            if rank:
                searchkeyword = SearchKeyword.objects.filter(rank=rank).order_by('-id').first()
                success_time = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S')
                failure_time = datetime.datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S')
                if searchkeyword and searchkeyword.start_time and searchkeyword.end_time:
                    if searchkeyword.start_time <= success_time <= searchkeyword.end_time or searchkeyword.start_time <= failure_time <= searchkeyword.end_time:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'该位置已配置, 时间区间重合, 不能重复配置，如需增加请修改时间区间', data=None)
        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        SearchKeywordOperationRecord.objects.create(
            searchkeyword=obj,
            operate_user_id=operate_user_id,
            content=u'创建默认搜索词{}'.format(obj.keyword)
        )
        return to_dict(obj)

    def update(self, updates, **kwargs):
        operate_user_id = updates.pop('operate_user_id')
        _pk = kwargs.get("id", 0)
        search_keyword_obj = self.model.objects.get(pk=_pk)
        self.params_check(search_keyword_obj.type, updates.get("jump_type", HOT_SEARCH_JUMP_TYPE.NORMAL))
        if search_keyword_obj.position == SEARCH_KEYWORDS_POSITION.DEFAULT:
            content = ''
            keyword = updates.get('keyword','')
            rank = updates.get('rank','')
            regions = updates.get('regions','')
            cities = updates.get('cities','')
            jump_type = updates.get('jump_type','')
            jump_target = updates.get('jump_target','')
            explicit_word = updates.get('explicit_word','')
            start_time = updates.get('start_time','')
            end_time = updates.get('end_time','')

            #更新位置,开始结束时间时,判断是否有重合
            success_time = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') if start_time else search_keyword_obj.start_time
            failure_time = datetime.datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S') if end_time else search_keyword_obj.end_time
            now = str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
            new_rank = rank if rank else search_keyword_obj.rank
            if new_rank:
                q = Q(rank=new_rank) & ~Q(id=_pk)
                searchkeyword = SearchKeyword.objects.filter(q).order_by('-id').first()
                if searchkeyword and searchkeyword.start_time and searchkeyword.end_time:
                    if success_time == searchkeyword.start_time and failure_time == searchkeyword.end_time:
                        pass
                    elif searchkeyword.start_time <= success_time <= searchkeyword.end_time or searchkeyword.start_time <= failure_time <= searchkeyword.end_time:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'该位置已配置, 时间区间重合, 不能重复配置，如需增加请修改时间区间',
                                                data=None)
            if keyword:
                content += u'修改搜索词为{}/'.format(keyword)
            if rank:
                content += u'修改展示位置为{}/'.format(rank)
            if regions:
                content += u'修改展示大区为{}/'.format(regions)
            if cities:
                content += u'修改展示城市为{}/'.format(cities)
            if jump_type:
                content += u'修改跳转类型为{}/'.format(jump_type)
            if jump_target:
                content += u'修改跳转页面为{}/'.format(jump_target)
            if explicit_word:
                content += u'修改外显词为{}/'.format(explicit_word)
            if start_time:
                if not search_keyword_obj.start_time:
                    content += u'修改生效时间为{}/'.format(start_time)
                    if start_time < now:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'生效时间不能小于当前编辑时间', data=None)
                elif search_keyword_obj.start_time and start_time != str(search_keyword_obj.start_time.strftime("%Y-%m-%d %H:%M:%S")):
                    content += u'修改生效时间为{}/'.format(start_time)
                    if start_time < now:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'生效时间不能小于当前编辑时间', data=None)
            if end_time:
                if not search_keyword_obj.end_time:
                    content += u'修改失效时间为{}/'.format(end_time)
                    if end_time < now:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'失效时间不能小于当前编辑时间', data=None)
                elif search_keyword_obj.end_time and  end_time != str(search_keyword_obj.end_time.strftime("%Y-%m-%d %H:%M:%S")):
                    content += u'修改失效时间为{}/'.format(end_time)
                    if end_time < now:
                        raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'失效时间不能小于当前编辑时间', data=None)
            if content:
                SearchKeywordOperationRecord.objects.create(
                    searchkeyword=search_keyword_obj,
                    operate_user_id=operate_user_id,
                    content=content,
                )

        return super(SearchKeywordDQ.sqlquery, self).update(updates, **kwargs)


class TopicAggregationDB(DataBuilder):
    def getval_aggregate_id(self, obj):
        return obj.aggregate_id.split(",")


@DB
class TopicAggregationDQ(DataSQLQuery):
    model = TopicAggregation
    data_model = TopicAggregationDB
    distinct = True

    def create(self, **kwargs):
        kwargs['aggregate_id'] = kwargs.pop('aggregate_id', 0)
        kwargs['topic_id'] = kwargs.pop('topic_id', 0)
        kwargs['group_id'] = kwargs.pop('group_id', 0)

        return to_dict(self.model.objects.create(**kwargs))

    def update(self, updates, **kwargs):
        is_delete = updates.pop('is_delete', False)
        if is_delete:
            qs = TopicAggregation.objects.filter(**kwargs)
            count = qs.count()
            qs.delete()
            return count

        count = 0
        aggregate_id = updates.pop('aggregate_id', [])
        if aggregate_id:
            updates['aggregate_id'] = ','.join(aggregate_id)

        topic_id = kwargs.pop('topic_id', [])
        if topic_id:
            updates['topic_id'] = ','.join(topic_id)

        group_id = kwargs.pop('group_id', [])
        if group_id:
            updates['group_id'] = ','.join(group_id)

        with transaction.atomic(self.model.objects.db):
            for obj in self.model.objects.select_for_update().filter(**kwargs):
                count += 1
                for k, v in updates.items():
                    setattr(obj, k, v)
                obj.save()
        return count


class SearchActivityDB(DataBuilder):

    def getval_time_range(self, obj):
        start_time = obj.start_time
        end_time = obj.end_time
        return str(start_time.strftime("%Y-%m-%d %H:%M:%S")) + '--' + str(end_time.strftime("%Y-%m-%d %H:%M:%S"))


@DB
class SearchActivityDQ(DataSQLQuery):
    model = SearchActivity
    data_model = SearchActivityDB

    def filter_operator_id(self, srch_key, srch_val, regex=False):
        try:
            user_id = int(srch_val)
        except ValueError:
            return Q()
        return Q(operator_id=user_id)

    def update(self, updates, **kwargs):
        return super(SearchActivityDQ.sqlquery, self).update(updates, **kwargs)
