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

from django.db.models import Q
from django.conf import settings
from django.utils.dateparse import parse_datetime, parse_date
from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_dataquery.db import DB
from gm_dataquery.dict_mixin import to_dict
from gm_types.error import ERROR
from rpc.exceptions import GaiaRPCFaultException
from api.models.user import User
from api.models.sign_activity import SignActivity, SignPrize, ActivityPrize, UserReceive
from api.models.sign_v2 import (
    SignBigPrizeV2,
    ExchangedRecordV2,
    SignBlindBox,
    SignBlindExchangePrize,
    SignUserExchangedPrize,
    ExchangedRecordV3,
    SignPrizeV3,
)
from api.models.user import UserExtra


class SignActivityDB(DataBuilder):

    def get_relation(self, obj):
        return ActivityPrize.objects.filter(activity_id=obj.id).order_by('cost')

    def getval_rule(self, obj, need_escape=True):
        return obj.rule

    def getval_start_time(self, obj):
        return obj.start_time.strftime('%Y-%m-%d')

    def getval_end_time(self, obj):
        return obj.end_time.strftime('%Y-%m-%d')

    def getval_banner_first(self, obj):
        return json.loads(obj.banner)['first']['img']

    def getval_banner_first_jump(self, obj):
        return json.loads(obj.banner)['first']['jump']

    def getval_banner_second(self, obj):
        return json.loads(obj.banner)['second']['img']

    def getval_banner_second_jump(self, obj):
        return json.loads(obj.banner)['second']['jump']

    def getval_banner_third(self, obj):
        return json.loads(obj.banner)['third']['img']

    def getval_banner_third_jump(self, obj):
        return json.loads(obj.banner)['third']['jump']

    def getval_prize_first(self, obj):
        return self.get_relation(obj)[0].prize.id if len(list(self.get_relation(obj))) >= 1 else ''

    def getval_prize_first_count(self, obj):
        return self.get_relation(obj)[0].count if len(list(self.get_relation(obj))) >= 1 else ''

    def getval_prize_first_cost(self, obj):
        return self.get_relation(obj)[0].cost if len(list(self.get_relation(obj))) >= 1 else ''

    def getval_prize_second(self, obj):
        return self.get_relation(obj)[1].prize.id if len(list(self.get_relation(obj))) >= 2 else ''

    def getval_prize_second_count(self, obj):
        return self.get_relation(obj)[1].count if len(list(self.get_relation(obj))) >= 2 else ''

    def getval_prize_second_cost(self, obj):
        return self.get_relation(obj)[1].cost if len(list(self.get_relation(obj))) >= 2 else ''

    def getval_prize_third(self, obj):
        return self.get_relation(obj)[2].prize.id if len(list(self.get_relation(obj))) >= 3 else ''

    def getval_prize_third_count(self, obj):
        return self.get_relation(obj)[2].count if len(list(self.get_relation(obj))) >= 3 else ''

    def getval_prize_third_cost(self, obj):
        return self.get_relation(obj)[2].cost if len(list(self.get_relation(obj))) >= 3 else ''

    def getval_prize_fourth(self, obj):
        return self.get_relation(obj)[3].prize.id if len(list(self.get_relation(obj))) >= 4 else ''

    def getval_prize_fourth_count(self, obj):
        return self.get_relation(obj)[3].count if len(list(self.get_relation(obj))) >= 4 else ''

    def getval_prize_fourth_cost(self, obj):
        return self.get_relation(obj)[3].cost if len(list(self.get_relation(obj))) >= 4 else ''

    def getval_prize_fifth(self, obj):
        return self.get_relation(obj)[4].prize.id if len(list(self.get_relation(obj))) >= 5 else ''

    def getval_prize_fifth_count(self, obj):
        return self.get_relation(obj)[4].count if len(list(self.get_relation(obj))) >= 5 else ''

    def getval_prize_fifth_cost(self, obj):
        return self.get_relation(obj)[4].cost if len(list(self.get_relation(obj))) >= 5 else ''

    def getval_prize_sixth(self, obj):
        return self.get_relation(obj)[5].prize.id if len(list(self.get_relation(obj))) >= 6 else ''

    def getval_prize_sixth_count(self, obj):
        return self.get_relation(obj)[5].count if len(list(self.get_relation(obj))) >= 6 else ''

    def getval_prize_sixth_cost(self, obj):
        return self.get_relation(obj)[5].cost if len(list(self.get_relation(obj))) >= 6 else ''


@DB
class SignActivityDQ(DataSQLQuery):
    model = SignActivity
    data_model = SignActivityDB

    @classmethod
    def create(cls, **kwargs):
        end_time = parse_date(kwargs["end_time"])
        start_time = parse_date(kwargs["start_time"])
        kwargs["end_time"] = datetime.datetime(end_time.year, end_time.month, end_time.day, hour=23, minute=59, second=59)
        kwargs["start_time"] = datetime.datetime(start_time.year, start_time.month, start_time.day)
        if kwargs["end_time"] < datetime.datetime.now():
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='结束时间不能小于当前时间', data=None)
        if kwargs["end_time"] < kwargs["start_time"]:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='结束时间不能小于开始时间', data=None)

        check_start_time = SignActivity.objects.filter(start_time__lt=kwargs["start_time"],
                                                       end_time__gt=kwargs["start_time"])
        check_end_time = SignActivity.objects.filter(start_time__lt=kwargs["end_time"],
                                                     end_time__gt=kwargs["end_time"])
        if check_start_time or check_end_time:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='该活动与其他活动时间有重叠', data=None)

        banner_index, banner = ['first', 'second', 'third'], {}
        for item in banner_index:
            banner[item] = {
                'img': kwargs.get('banner_'+item, ''),
                'jump': kwargs.get('banner_'+item+'_jump', ''),
            }

        activity_obj = {
            'name': kwargs.get('name'),
            'start_time': kwargs.get('start_time'),
            'end_time': kwargs.get('end_time'),
            'rule': kwargs.get('rule'),
            'is_online': True,
            'banner': json.dumps(banner)
        }
        activity = SignActivity.objects.create(**activity_obj)

        relation_list = []
        prize_index = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
        prizes_qurset = SignPrize.objects.filter(id__in=[int(kwargs.get('prize_'+item))
                                                         if kwargs.get('prize_'+item) else None for item in prize_index])
        prizes = {str(prize.id): prize for prize in prizes_qurset}
        for item in prize_index:
            if kwargs.get('prize_'+item):
                relation_obj = ActivityPrize(
                    activity=activity,
                    prize=prizes.get(kwargs.get('prize_' + item)),
                    count=kwargs.get('prize_' + item + '_count'),
                    total=kwargs.get('prize_' + item + '_count'),
                    cost=kwargs.get('prize_' + item + '_cost')
                )
                relation_list.append(relation_obj)
            else:
                continue

        ActivityPrize.objects.bulk_create(relation_list)        #批量创建  是一个list

        return to_dict(activity)

    @classmethod
    def update(cls, updates, **kwargs):
        end_time = parse_date(updates["end_time"])
        start_time = parse_date(updates["start_time"])
        updates["end_time"] = datetime.datetime(end_time.year, end_time.month, end_time.day, hour=23,
                                                minute=59, second=59)
        updates["start_time"] = datetime.datetime(start_time.year, start_time.month, start_time.day)
        activity = SignActivity.objects.get(id=int(kwargs.get('id')))

        if updates["end_time"] < datetime.datetime.now():
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='结束时间不能小于当前时间', data=None)
        if updates["end_time"] < updates["start_time"]:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='结束时间不能小于开始时间', data=None)
        if updates["end_time"] < activity.end_time:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='结束时间不能向前修改', data=None)

        activity.start_time = updates.get('start_time') if updates.get('start_time') else activity.start_time
        activity.end_time = updates.get('end_time') if updates.get('end_time') else activity.endtime
        check_start_time = SignActivity.objects.filter(start_time__lt=activity.start_time, end_time__gt=activity.start_time).exclude(id=int(kwargs.get('id')))
        check_end_time = SignActivity.objects.filter(start_time__lt=activity.end_time, end_time__gt=activity.end_time).exclude(id=int(kwargs.get('id')))
        if check_start_time or check_end_time:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='该活动与其他活动时间有重叠', data=None)

        banners = json.loads(activity.banner)

        banner_index, banner = ['first', 'second', 'third'], {}
        for item in banner_index:
            banner[item] = {
                'img': updates.get('banner_'+item, '') if updates.has_key('banner_'+item)
                            else banners[item]['img'],
                'jump': updates.get('banner_'+item+'_jump', '') if updates.has_key('banner_'+item+'_jump')
                            else banners[item]['jump'],
            }

        activity.name = updates.get('name') if updates.get('name') else activity.name
        activity.start_time = updates.get('start_time') if updates.get('start_time') else activity.start_time
        activity.end_time = updates.get('end_time') if updates.get('end_time') else activity.endtime
        activity.rule = updates.get('rule') if updates.get('rule') else activity.rule
        activity.is_online = True
        activity.banner = json.dumps(banner)
        activity.save()

        prize_index = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
        relation_qurset = ActivityPrize.objects.filter(activity_id=activity.id).order_by('cost')
        relation_qurset = list(relation_qurset)
        index = 0
        for item in prize_index:
            if updates.get('prize_' + item + '_count') or updates.get('prize_' + item) or updates.get('prize_' + item + '_cost') \
                    or updates.get('prize_' + item) == '':
                try:
                    relation = relation_qurset[index]
                    if updates.get('prize_' + item) or updates.get('prize_' + item) == '':
                        if updates.get('prize_' + item):
                            prize = SignPrize.objects.get(id=int(updates.get('prize_' + item)))
                            relation.prize = prize
                            relation.count = updates.get('prize_' + item + '_count') if updates.has_key('prize_' + item + '_count') else relation.count
                            relation.cost = updates.get('prize_' + item + '_cost') or relation.cost
                            relation.save()
                        elif updates.get('prize_' + item) == '':
                            ActivityPrize.objects.filter(id=relation.id).delete()
                except:
                    prize = SignPrize.objects.get(id=int(updates.get('prize_' + item))) if updates.get('prize_' + item) else None
                    relation_obj = ActivityPrize(
                        activity=activity,
                        prize=prize,
                        count=updates.get('prize_' + item + '_count', 0),
                        total=updates.get('prize_' + item + '_count', 0),
                        cost=updates.get('prize_' + item + '_cost', 0)
                    )
                    relation_obj.save()
            index = index + 1


class SignActivityPrizeDB(DataBuilder):

    pass


@DB
class SignActivityPrizeDQ(DataSQLQuery):
    model = SignPrize
    data_model = SignActivityPrizeDB

    @classmethod
    def create(cls, **kwargs):
        if kwargs.get('price') and kwargs.get('price') <= 0:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='商品价格不能小于0元', data=None)
        obj = {
            'name': kwargs.get('name', ''),
            'short_name': kwargs.get('short_name', ''),
            'img_url': kwargs.get('img_url', ''),
            'price': kwargs.get('price', 0),
            'total': kwargs.get('total', 0),
            'count': kwargs.get('count', 0),
        }
        result = SignPrize.objects.create(**obj)
        return to_dict(result)

    @classmethod
    def update(cls, updates, **kwargs):
        if updates.get('price') and updates.get('price') <= 0:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='商品价格不能小于0元', data=None)
        prize = SignPrize.objects.get(id=int(kwargs.get('id')))
        prize.count = updates.get('count') if updates.get('count') else prize.count
        prize.name = updates.get('name') if updates.get('name') else prize.name
        prize.short_name = updates.get('short_name') if updates.get('short_name') else prize.short_name
        prize.img_url = updates.get('img_url') if updates.get('img_url') else prize.img_url
        prize.price = updates.get('price') if updates.get('price') else prize.price
        prize.save()


    def filter_activity_id(self, srch_key, srch_val, regex=False):
        prizes = ActivityPrize.objects.filter(activity_id=srch_val).values_list('prize_id', flat=True)
        return Q(id__in=list(prizes))

    def filter_activity_name(self, srch_key, srch_val, regex=True):
        prizes = ActivityPrize.objects.filter(activity__name__icontains=srch_val).values_list('prize_id', flat=True)
        return Q(id__in=list(prizes))


class SignActivityCashDB(DataBuilder):

    def get_user(self, obj):
        user = UserExtra.objects.get(user_id=obj.user_id)
        return user

    def getval_user_adress(self, obj):
        return self.get_user(obj).address

    def getval_user_name(self, obj):
        return self.get_user(obj).user.last_name

    def getval_prize_name(self, obj):
        return obj.prize.name

    def getval_user_id(self, obj):
        return obj.user_id

    def getval_user_city(self, obj):
        return self.get_user(obj).city.name

    def getval_user_phone(self, obj):
        return self.get_user(obj).phone

    def getval_count(self, obj):
        return obj.count

    def getval_activity_id(self, obj):
        return obj.activity.id

    def getval_prize_id(self, obj):
        return obj.prize.id

    def getval_send_goods(self, obj):
        if obj.express_no:
            return True
        else:
            return False


@DB
class SignActivityCashDQ(DataSQLQuery):
    model = UserReceive
    data_model = SignActivityCashDB

    def filter_user_name(self, srch_key, srch_val, regex=True):
        users = UserExtra.objects.using(settings.SLAVE_DB_NAME).filter(user__last_name__icontains=srch_val)\
                                 .values_list('user_id', flat=True)
        return Q(user_id__in=list(users))

    def filter_send_goods(self, srch_key, srch_val, regex=False): 
        if int(srch_val):
            return ~Q(express_no='')
        else:
            return Q(express_no='')


class SignBigPrizeV2DB(DataBuilder):
    def getval_jump_name(self, obj):
        return u"点击进入详情"


@DB
class SignBigPrizeV2DQ(DataSQLQuery):
    model = SignBigPrizeV2
    data_model = SignBigPrizeV2DB

    @classmethod
    def create(cls, **kwargs):
        obj = {
            'name': kwargs.get('name', ''),
            'img_url': kwargs.get('img_url', ''),
            'count': kwargs.get('count', 0),
            'exchange_days': kwargs.get('exchange_days', 0),
            'init_count': kwargs.get('count', 0),
        }
        result = SignBigPrizeV2.objects.create(**obj)
        return to_dict(result)


class ExchangedRecordV2DB(DataBuilder):

    def get_user(self, obj):
        user = UserExtra.objects.get(user_id=obj.user_id)
        return user

    def getval_user_adress(self, obj):
        return self.get_user(obj).address

    def getval_user_name(self, obj):
        return self.get_user(obj).user.last_name

    def getval_prize_name(self, obj):
        return obj.prize.name

    def getval_user_id(self, obj):
        return obj.user_id

    def getval_user_city(self, obj):
        return self.get_user(obj).city.name

    def getval_user_phone(self, obj):
        return self.get_user(obj).phone

    def getval_activity_id(self, obj):
        return obj.activity.id

    def getval_prize_id(self, obj):
        return obj.prize.id

    def getval_send_goods(self, obj):
        if obj.express_no:
            return True
        else:
            return False


@DB
class ExchangedRecordV2DQ(DataSQLQuery):
    model = ExchangedRecordV2
    data_model = ExchangedRecordV2DB

    def filter_user_name(self, srch_key, srch_val, regex=True):
        users = User.objects.using(settings.SLAVE_DB_NAME).filter(last_name__icontains=srch_val)\
                                 .values_list('id', flat=True)

        return Q(user_id__in=list(users))

    def filter_send_goods(self, srch_key, srch_val, regex=False):
        if int(srch_val):
            return ~Q(express_no=0)
        else:
            return Q(express_no=0)

    def filter_user_id(self, srch_key, srch_val, regex=False):
        return Q(user_id=int(srch_val))


class SignBlindBoxDB(DataBuilder):
    def getval_adress(self, obj):
        return ""

    def getval_probily(self, obj):
        if not obj.is_online:
            return u"0%"
        problity_list = list(SignBlindBox.objects.filter(is_online=True).values_list("probability", flat=True))
        return u"{problity}%".format(problity=round(float(100 * obj.probability) / float(sum(problity_list)), 2))

@DB
class SignBlindBoxDQ(DataSQLQuery):
    model = SignBlindBox
    data_model = SignBlindBoxDB

    @classmethod
    def create(cls, **kwargs):
        ordinary_count = SignBlindBox.objects.filter(is_online=True, is_final=False).count()
        final_count = SignBlindBox.objects.filter(is_online=True, is_final=True).count()
        if final_count and kwargs.get("is_final"):
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='只能配置一个在线隐藏卡片', data=None)

        if ordinary_count >= 9 and kwargs.get("is_online") and not kwargs.get("is_final"):
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='普通卡片只能配置9个', data=None)

        card = SignBlindBox.objects.create(**kwargs)

        return to_dict(card)


    @classmethod
    def update(self, updates, **kwargs):
        ordinary_count = SignBlindBox.objects.filter(is_online=True, is_final=False).count()
        final_count = SignBlindBox.objects.filter(is_online=True, is_final=True).count()

        card = SignBlindBox.objects.filter(id=int(kwargs.get("id"))).first()
        if not card:
            return

        is_final = updates.get("is_final") or card.is_final
        is_online = updates.get("is_online") or card.is_online
        if final_count and updates.get("is_final") and is_online:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='只能配置一个在线隐藏卡片', data=None)

        if ordinary_count >= 9 and updates.get("is_online"):
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message='普通卡片只能配置9个', data=None)

        card.is_final = is_final
        card.is_online = is_online
        card.name = updates.get("name") or card.name
        card.img_url = updates.get("img_url") or card.img_url
        card.probability = updates.get("probability") or card.probability
        card.show_order = updates.get("show_order") or card.show_order
        card.save()


class SignBlindExchangePrizeDB(DataBuilder):
    def getval_blind_box_ids(self, obj):
        return obj.blind_box_list


@DB
class SignBlindExchangePrizeDQ(DataSQLQuery):
    model = SignBlindExchangePrize
    data_model = SignBlindExchangePrizeDB


class ExchangedRecordV3DB(DataBuilder):

    def get_user(self, obj):
        user = UserExtra.objects.get(user_id=obj.user_id)
        return user

    def getval_user_adress(self, obj):
        return self.get_user(obj).address

    def getval_user_name(self, obj):
        return self.get_user(obj).user.last_name

    def getval_prize_name(self, obj):
        prize = SignBlindExchangePrize.objects.filter(id=obj.prize_id).first()
        return prize.name if prize else ""

    def getval_user_id(self, obj):
        return obj.user_id

    def getval_user_city(self, obj):
        return self.get_user(obj).city.name

    def getval_user_phone(self, obj):
        return self.get_user(obj).phone

    def getval_activity_id(self, obj):
        return obj.activity.id

    def getval_prize_id(self, obj):
        return obj.prize_id

    def getval_send_goods(self, obj):
        if obj.express_no:
            return True
        else:
            return False


@DB
class ExchangedRecordV3DQ(DataSQLQuery):
    model = SignUserExchangedPrize
    data_model = ExchangedRecordV3DB

    def filter_user_name(self, srch_key, srch_val, regex=True):
        users = User.objects.using(settings.SLAVE_DB_NAME).filter(last_name__icontains=srch_val)\
                                 .values_list('id', flat=True)

        return Q(user_id__in=list(users))

    def filter_send_goods(self, srch_key, srch_val, regex=False):
        if int(srch_val):
            return ~Q(express_no=0)
        else:
            return Q(express_no=0)

    def filter_user_id(self, srch_key, srch_val, regex=False):
        return Q(user_id=int(srch_val))


class SignPrizeV3DB(DataBuilder):
    pass


@DB
class SignPrizeV3DQ(DataSQLQuery):
    model = SignPrizeV3
    data_model = SignPrizeV3DB


class ExchangedRecordV4DB(DataBuilder):

    def get_user(self, obj):
        user = UserExtra.objects.get(user_id=obj.user_id)
        return user

    def getval_user_adress(self, obj):
        return self.get_user(obj).address

    def getval_user_name(self, obj):
        return self.get_user(obj).user.last_name

    def getval_prize_name(self, obj):
        prize = SignPrizeV3.objects.filter(id=obj.prize_id).first()
        return prize.name if prize else ""

    def getval_user_id(self, obj):
        return obj.user_id

    def getval_user_city(self, obj):
        return self.get_user(obj).city.name

    def getval_user_phone(self, obj):
        return self.get_user(obj).phone

    def getval_activity_id(self, obj):
        return obj.activity.id

    def getval_prize_id(self, obj):
        return obj.prize_id

    def getval_send_goods(self, obj):
        if obj.express_no:
            return True
        else:
            return False


@DB
class ExchangedRecordV4DQ(DataSQLQuery):
    model = ExchangedRecordV3
    data_model = ExchangedRecordV4DB

    def filter_user_name(self, srch_key, srch_val, regex=True):
        users = User.objects.using(settings.SLAVE_DB_NAME).filter(last_name__icontains=srch_val)\
                                 .values_list('id', flat=True)

        return Q(user_id__in=list(users))

    def filter_send_goods(self, srch_key, srch_val, regex=False):
        if int(srch_val):
            return ~Q(express_no=0)
        else:
            return Q(express_no=0)

    def filter_user_id(self, srch_key, srch_val, regex=False):
        return Q(user_id=int(srch_val))

