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

import requests, json
from gm_dataquery.dataquery import DataBuilder, DataSQLQuery
from gm_dataquery.db import DB
from gm_types.error import ERROR
from rpc.tool.dict_mixin import to_dict
from api.models import HomepageOperate, TabOperate, HomepageIcon, FestivalHomepageIcon, HomepageActivity, TabOperateV2, \
    FeedOperateV2, TabOperateV2TagV3
from rpc.exceptions import GaiaRPCFaultException
from gm_types.gaia import HOMEPAGE_OPERATE_TYPE, HOMEPAGE_OPERATE_LOCATION, SLIDE_USER_TYPE, SLIDE_PAYMENT_TYPE, \
    FEED_SERVICE_TYPE, FEED_SHOW_TYPE, TAB_TYPES_NEW, INDEX_CARD_TYPE, FEED_OPERATE_VERSION


class HomepageOperateDB(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()]


@DB
class HomepageOperateDQ(DataSQLQuery):
    model = HomepageOperate
    data_model = HomepageOperateDB
    distinct = True

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        if kwargs['location'] == HOMEPAGE_OPERATE_LOCATION.SECKILL and \
                kwargs['jump_type'] != HOMEPAGE_OPERATE_TYPE.SPECIAL and \
                kwargs['jump_type'] != HOMEPAGE_OPERATE_TYPE.SECKILL:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'秒杀横滑只能配置交易专题或者秒杀', data=None)
        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        return to_dict(obj)

    def update(self, updates, **kwargs):
        obj = self.model.objects.get(id=kwargs['id'])
        location = updates.get('location', obj.location)
        jump_type = updates.get('jump_type', obj.jump_type)
        if location == HOMEPAGE_OPERATE_LOCATION.SECKILL and \
                jump_type != HOMEPAGE_OPERATE_TYPE.SPECIAL and \
                jump_type != HOMEPAGE_OPERATE_TYPE.SECKILL:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'秒杀横滑只能配置交易专题或者秒杀', data=None)
        return super(HomepageOperateDQ.sqlquery, self).update(updates, **kwargs)


class TabOperateDB(DataBuilder):
    pass


@DB
class TabOperateDQ(DataSQLQuery):
    model = TabOperate
    data_model = DataBuilder


class TabOperateV2DB(DataBuilder):

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


@DB
class TabOperateV2DQ(DataSQLQuery):
    model = TabOperateV2
    data_model = TabOperateV2DB

    def create(self, **kwargs):
        tags = kwargs.pop('tags')
        tag_v3_ids = kwargs.pop("tag_v3_ids", [])
        obj = self.model.objects.create(**kwargs)
        obj.tags = tags

        _bulk_create_list = [TabOperateV2TagV3(
            tag_v3_id=tag_id,
            tab_operate_v2_id=obj.id
        ) for tag_id in tag_v3_ids]
        TabOperateV2TagV3.objects.bulk_create(_bulk_create_list)

        return to_dict(obj)

    def _update_tag_v3(self, operate_id, tag_ids):
        new_tag_ids = set(map(int, tag_ids))
        old_tag_ids = set(TabOperateV2TagV3.objects.filter(
            tab_operate_v2_id=operate_id).values_list("tag_v3_id", flat=True))

        for tag_id in (new_tag_ids - old_tag_ids):
            TabOperateV2TagV3.objects.get_or_create(**{
                "tag_v3_id": tag_id,
                "tab_operate_v2_id": operate_id,
            })

        need_del_ids = old_tag_ids - new_tag_ids
        if need_del_ids:
            TabOperateV2TagV3.objects.filter(**{
                "tab_operate_v2_id": operate_id,
                "tag_v3_id__in": need_del_ids
            }).delete()

    def update(self, updates, **kwargs):
        _tab_operate_id = kwargs.get("id", 0)

        if "tag_v3_ids" in updates:
            self._update_tag_v3(_tab_operate_id, updates.pop("tag_v3_ids", []))

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


class HomepageIconDB(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()]


@DB
class HomepageIconDQ(DataSQLQuery):
    model = HomepageIcon
    data_model = HomepageIconDB

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        if kwargs['jump_type'] == HOMEPAGE_OPERATE_TYPE.ALL_CATEGORY:
            if not (kwargs['user_type'] == SLIDE_USER_TYPE.ALL_USER and kwargs[
                'payment_type'] == SLIDE_PAYMENT_TYPE.ALL_PAYMENT):
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'跳转类型为全部页面的用户类型与支付类型只能为全部用户，全部支付类型',
                                            data=None)
        elif kwargs['jump_type'] == HOMEPAGE_OPERATE_TYPE.CATEGORY:
            if not kwargs['jump']:
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'跳转类型为品类落地页面的跳转配置不能为空', data=None)
        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        return to_dict(obj)

    def update(self, updates, **kwargs):
        obj = self.model.objects.get(id=kwargs['id'])
        payment_type = updates.get('payment_type', obj.payment_type)
        user_type = updates.get('user_type', obj.user_type)
        jump_type = updates.get('jump_type', obj.jump_type)
        jump = updates.get('jump', obj.jump)
        if jump_type == HOMEPAGE_OPERATE_TYPE.ALL_CATEGORY:
            if not (user_type == SLIDE_USER_TYPE.ALL_USER and payment_type == SLIDE_PAYMENT_TYPE.ALL_PAYMENT):
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'跳转类型为全部页面的用户类型与支付类型只能为全部用户，全部支付类型',
                                            data=None)
            if updates.get('cities') or updates.get('regions'):
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'跳转类型为全部页面的地区和城市只能为全部，后台不填', data=None)
        elif jump_type == HOMEPAGE_OPERATE_TYPE.CATEGORY:
            if not jump:
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'跳转类型为品类落地页面的跳转配置不能为空', data=None)
        return super(HomepageIconDQ.sqlquery, self).update(updates, **kwargs)


class FestivalHomepageIconDB(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()]


@DB
class FestivalHomepageIconDQ(DataSQLQuery):
    model = FestivalHomepageIcon
    data_model = FestivalHomepageIconDB

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        return to_dict(obj)


class HomepageActivityDB(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()]


@DB
class HomepageActivityDQ(DataSQLQuery):
    model = HomepageActivity
    data_model = HomepageActivityDB

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        return to_dict(obj)


class FeedOperateV2DB(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_tab_id_name(self, obj):
        if obj.tab_id:
            return TabOperateV2.objects.get(id=obj.tab_id).name
        return ""

    def getval_service_type_name(self, obj):
        return FEED_SERVICE_TYPE.getDesc(obj.service_type),

    def getval_location_name(self, obj):
        return TAB_TYPES_NEW.getDesc(obj.location),

    def getval_card_type_name(self, obj):
        return INDEX_CARD_TYPE.getDesc(obj.card_type),

@DB
class FeedOperateV2DQ(DataSQLQuery):
    model = FeedOperateV2
    data_model = FeedOperateV2DB

    def create(self, **kwargs):
        cities = kwargs.pop('cities')
        regions = kwargs.pop('regions')
        show_type = int(kwargs['show_type'])
        service_type = str(kwargs['service_type'])
        tab_id = kwargs['tab_id']  # tab_id 可能会传入空字符串，展示位置为精选时 tab_id 默认为0
        version = kwargs.get('version', FEED_OPERATE_VERSION.V1)
        try:
            rank = int(kwargs['rank'])
        except:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'展示位置只能是数字', data=None)
        if tab_id == '':
            tab_id = 0
        if kwargs.get('relevance_tag') == '':
            kwargs['relevance_tag'] = 0
        kwargs['tab_id'] = tab_id
        if show_type == FEED_SHOW_TYPE.D and service_type != FEED_SERVICE_TYPE.SUPPLY or \
                show_type != FEED_SHOW_TYPE.D and service_type == FEED_SERVICE_TYPE.SUPPLY:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'配置为补位时，业务类型需要保持一致', data=None)

        if version == FEED_OPERATE_VERSION.V1:
            if rank < 2 or rank > 36:
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'展示位置只能介于2-36', data=None)
        elif version == FEED_OPERATE_VERSION.V2:
            if rank < 1 or rank == 5:
                raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'展示位置只能是大于1的非5整数', data=None)

        image_size = {}
        if kwargs.get("image"):
            try:
                # 只在后台系统功能使用，没有考虑性能
                image_size = get_image_base_info(kwargs.get("image"))
            except:
                pass
        kwargs['width'] = image_size.get('width', 0)
        kwargs['height'] = image_size.get('height', 0)

        if "tab_type" in kwargs.keys() and not kwargs.get("tab_type"):
            kwargs.pop("tab_type")

        obj = self.model.objects.create(**kwargs)
        obj.cities = cities
        obj.regions = regions
        return to_dict(obj)

    def update(self, updates, **kwargs):
        obj = self.model.objects.get(id=kwargs['id'])
        show_type = int(updates.get('show_type', obj.show_type))
        service_type = str(updates.get('service_type', obj.service_type))

        if show_type == FEED_SHOW_TYPE.D and service_type != FEED_SERVICE_TYPE.SUPPLY or \
                show_type != FEED_SHOW_TYPE.D and service_type == FEED_SERVICE_TYPE.SUPPLY:
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'配置为补位时，业务类型需要保持一致', data=None)

        tab_id = updates.get('tab_id')  # tab_id 可能会传入空字符串，展示位置为精选时 tab_id 默认为0
        if tab_id is None:
            pass
        elif tab_id == '':
            updates['tab_id'] = 0
        if updates.get('relevance_tag') == '':
            updates['relevance_tag'] = 0
        if updates.get('rank') and (int(updates.get('rank')) < 2 or int(updates.get('rank')) > 36):  # rank不能为0
            raise GaiaRPCFaultException(error=ERROR.UNIVERSAL, message=u'展示位置只能介于2-36', data=None)
        if updates.get("image") is not None:
            try:
                # 只在后台系统功能使用，没有考虑性能
                result = get_image_base_info(updates.get("image"))
                updates['width'] = result['width']
                updates['height'] = result['height']
            except:
                pass
        return super(FeedOperateV2DQ.sqlquery, self).update(updates, **kwargs)


def get_image_base_info(url, suffix='-imageinfo?ref'):
    full_path = url + suffix
    resp = requests.get(full_path, verify=False)  # 不进行ssl验证，避免 SSLError
    data = json.loads(resp.text)
    ret_data = {
        'width': 0,
        'height': 0
    }
    if resp.status_code == 200:
        ret_data['width'] = data['width']
        ret_data['height'] = data['height']

    return ret_data
