# coding=utf-8
import json
from datetime import *
import datetime as time
from django.db import IntegrityError
from django.db import transaction
from api.models import ShowCity, ShowRegion, Region
from api.models.slide import Slide, SmallImage, ButtonGadget, ButtonSideslip, FeedOperateV2
from api.models.feed import IndexFeed
from api.models import SideSkidCategory, Tag
from api.tool.log_tool import logging_exception
from ..datatables import SlideDT, SmallimageDT
from hera.queries.sidesikidcategory import SideSkidCategoryDQ
from rpc.exceptions import RPCNotFoundException, RPCIntegrityError
from rpc.exceptions import GaiaRPCFaultException
from rpc.decorators import bind_context, bind
from rpc.tool.dict_mixin import to_dict
from rpc.tool.log_tool import info_logger
from gm_types.gaia import SLIDE_POSITION, GADGET_PAGE_TYPE, SLIDE_LOCATION
from gm_types.error import ERROR
from hera.utils import model_edit, m2m_save
from ..queries.gmhome import SlideDQ, SmallImageDQ
from ..queries.gmhome import IndexFunctionDQ
from api.models.slide import TabConfigDeploy, IndextabConfig, DisplaySite, SlideToDisplaySite
from api.models import IndexFunction

slide_pre = 'hera/slide'
smallimage_pre = 'hera/smallimage'
uri_pre = 'hera/gmhome'
uri_city = 'hera/slide_city'
uri_sideskid = 'hera/sideskid'
uri_function = 'hera/index_function'


@bind_context(slide_pre + '/query')
def slide_query(ctx, options):
    dqobj = SlideDQ()
    return dqobj.process(**options)


@bind_context(slide_pre + '/list')
def slide_datatable(request, req_data):
    dtobj = SlideDT(Slide)
    return dtobj.process(req_data)


@bind_context(slide_pre + '/get_visible')
def get_slide_visible(ctx, position=SLIDE_POSITION.FIRST):
    return {'visible': Slide.get_visible(position=position)}


@bind_context(slide_pre + '/set_visible')
def set_slide_visible(ctx, visible=True, position=SLIDE_POSITION.FIRST):
    Slide.set_visible(position=position, visible=visible)


@bind_context(slide_pre + '/get')
def slide_detail(ctx, slide_id, options=None):
    try:
        slide = Slide.objects.get(id=slide_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    data = to_dict(slide, **options)
    data['region'] = list(slide.showregion.all().values_list('region_id', flat=True))
    data['display_types'] = list(SlideToDisplaySite.objects.filter(slide_id=slide_id).values_list(
        'display_site__display_type', flat=True
    ))
    data['display_types'] = [int(i) for i in data['display_types']]
    if data['question']:
        data['question_id'] = data['question']['id']
        data['question'] = data['question']['id']
    if data['answer']:
        data['answer_id'] = data['answer']['id']
        data['answer'] = data['answer']['id']
    return data


@transaction.atomic()
@bind_context(slide_pre + '/edit')
def slide_edit(ctx, slide_id=None, slide_info=None):
    if slide_info is None:
        return None

    slide_info['service_id'] = slide_info.pop('service') or None
    slide_info['tag_id'] = slide_info.pop('tag') or None
    slide_info['special_id'] = slide_info.pop('special') or None
    slide_info['zone_single_id'] = slide_info.pop('zone_single') or None
    slide_info['question'] = slide_info.pop('question_id') or None
    slide_info['answer'] = slide_info.pop('answer_id') or None
    slide_info['content_polymer_id'] = slide_info.pop('content_polymer_id') or None
    for key in [
        'diary_id', 'topic_id', 'activity_id', 'zhiboconfig_id', 'column_id',
        'new_seckill_id', 'seckill_polymer_id'
    ]:
        slide_info[key] = slide_info.pop(key) or None
    region = slide_info.pop('region')
    display_types = slide_info.pop('display_types', [])
    if 'cities' in slide_info.keys():
        slide_info.pop('cities')
    if slide_id is None:
        try:
            slide = Slide.objects.create(**slide_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            slide = Slide.objects.get(id=slide_id)
            for k, v in slide_info.iteritems():
                setattr(slide, k, v)
            slide.save()
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException
    # 轮播图展示位置绑定 7760
    display_site_ids = DisplaySite.objects.filter(
        display_type__in=display_types).values_list('id', flat=True)
    if display_site_ids:
        SlideToDisplaySite.objects.filter(slide_id=slide.id).delete()
        SlideToDisplaySite.objects.bulk_create([
            SlideToDisplaySite(slide_id=slide.id, display_site_id=item)
            for item in display_site_ids]
        )
    new_region = set(Region.objects.filter(id__in=region))
    old_region = set(Region.objects.filter(showregion__in=slide.showregion.all()))
    for region in (new_region - old_region):
        ShowRegion.objects.get_or_create(slide_id=slide.id, region=region)
    ShowRegion.objects.filter(slide_id=slide.id, region__in=(old_region-new_region)).delete()
    return slide.id


@bind_context(slide_pre + '/replication_slide')
def replication_slide(ctx, slide_id):
    """复制轮播图"""
    new_slide = None
    slide = Slide.objects.get(id=slide_id)
    display_site_ids = SlideToDisplaySite.objects.filter(
        slide_id=slide.id).values_list('display_site_id', flat=True)
    region_ids = ShowRegion.objects.filter(
        slide_id=slide.id).values_list('region_id', flat=True)
    with transaction.atomic():
        try:
            new_slide_data = to_dict(slide,
                    fields=[
                        "slide_type",
                        "service_type",
                        "slide_layout",
                        "slide_img",
                        "new_slide_img",
                        "app_new_slide_img",
                        "slide_banner_img",
                        "color",
                        "slide_img_big",
                        "slide_img1",
                        "topic_id",
                        "service_id",
                        "diary_id",
                        "zone_single_id",
                        "url",
                        "ordering",
                        "created_time",
                        "effect_time",
                        "end_time",
                        "is_online",
                        "tag_id",
                        "special_id",
                        "activity_id",
                        "position",
                        "title",
                        "is_show_info",
                        "waterfalls_pic",
                        "user_id",
                        "zhiboconfig_id",
                        "not_show_title",
                        "show_as_diary",
                        "column_id",
                        "content_polymer_id",
                        "question",
                        "answer",
                        "location",
                        "user_type",
                        "payment_type",
                        "new_seckill_id",
                        "seckill_polymer_id",
                    ])
            new_slide = Slide.objects.create(**new_slide_data)
            stod_objs = [SlideToDisplaySite(slide=new_slide, display_site_id=display_site_id)
                         for display_site_id in display_site_ids]
            SlideToDisplaySite.objects.bulk_create(stod_objs)

            re_objs = [ShowRegion(slide=new_slide, region_id=region_id)
                         for region_id in region_ids]
            ShowRegion.objects.bulk_create(re_objs)
        except Exception as e:
            logging_exception()
            raise e

    return {'id': new_slide.id}


@bind_context(slide_pre + '/delete')
def slide_delete(ctx, slide_id):
    try:
        Slide.objects.get(pk=slide_id).delete()
    except:
        return None

    return slide_id


@bind_context(slide_pre + '/listupdate')
def slide_listupdate(ctx, items):
    info = []
    for obj in items:
        slide = Slide.objects.get(pk=obj['key'])
        slide.is_online = obj['is_online']
        slide.ordering = obj['rank']
        slide.save()
        info.append(obj['key'])
    return info

@transaction.atomic()
@bind_context(slide_pre + '/replication')
def slide_replication(ctx, slide_id=None):
    #品类聚合banner复制
    with transaction.atomic():
        old_slide = Slide.objects.get(id=slide_id)
        slide = Slide.objects.create(
            slide_type=old_slide.slide_type,
            service_type=old_slide.service_type,
            slide_layout=old_slide.slide_layout,
            slide_img=old_slide.slide_img,
            new_slide_img=old_slide.new_slide_img,
            app_new_slide_img=old_slide.app_new_slide_img,
            slide_banner_img=old_slide.slide_banner_img,
            color=old_slide.color,
            slide_img_big=old_slide.slide_img_big,
            slide_img1=old_slide.slide_img1,
            topic_id=old_slide.topic_id,
            service=old_slide.service,
            diary_id=old_slide.diary_id,
            zone_single=old_slide.zone_single,
            url=old_slide.url,
            ordering=old_slide.ordering,
            effect_time=old_slide.effect_time,
            end_time=old_slide.end_time,
            is_online=old_slide.is_online,
            tag=old_slide.tag,
            special=old_slide.special,
            activity_id=old_slide.activity_id,
            position=old_slide.position,
            title=old_slide.title,
            is_show_info=old_slide.is_show_info,
            waterfalls_pic=old_slide.waterfalls_pic,
            user=old_slide.user,
            zhiboconfig_id=old_slide.zhiboconfig_id,
            not_show_title=old_slide.not_show_title,
            show_as_diary=old_slide.show_as_diary,
            column_id=old_slide.column_id,
            content_polymer_id=old_slide.content_polymer_id,
            question=old_slide.question,
            answer=old_slide.answer,
            location=old_slide.location,
            user_type=old_slide.user_type,
            payment_type=old_slide.payment_type,
            new_seckill_id=old_slide.new_seckill_id,
            seckill_polymer_id=old_slide.seckill_polymer_id,
        )
        display_site_ids = SlideToDisplaySite.objects.filter(slide_id=slide_id).values_list('display_site_id', flat=True)
        region_ids = ShowRegion.objects.filter(slide_id=slide_id).values_list('region_id', flat=True)
        city_ids = ShowCity.objects.filter(slide_id=slide_id).values_list('city_id', flat=True)

        if display_site_ids:
            SlideToDisplaySite.objects.bulk_create([
                SlideToDisplaySite(slide_id=slide.id, display_site_id=display_site_id)
                for display_site_id in display_site_ids]
            )
        if region_ids:
            ShowRegion.objects.bulk_create([
                ShowRegion(slide_id=slide.id, region_id=region_id)
                for region_id in region_ids]
            )
        if city_ids:
            ShowCity.objects.bulk_create([
                ShowCity(slide_id=slide.id, city_id=city_id)
                for city_id in city_ids]
            )
    return {'id': slide.id}


@bind_context(smallimage_pre + '/query')
def smallimage_query(ctx, options):
    dqobj = SmallImageDQ()
    return dqobj.process(**options)


@bind_context(smallimage_pre + '/list')
def smallimage_datatable(request, req_data):
    dtobj = SmallimageDT(SmallImage)
    return dtobj.process(req_data)


@bind_context(smallimage_pre + '/get')
def smallimage_detail(ctx, smallimage_id, options=None):
    try:
        smallimage = SmallImage.objects.get(id=smallimage_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    data = to_dict(smallimage, **options)
    return data


@bind_context(smallimage_pre + '/edit')
def smallimage_edit(ctx, smallimage_id=None, smallimage_info=None):
    if smallimage_info is None:
        return None

    smallimage_info['service_id'] = smallimage_info.pop('service')
    smallimage_info['special_id'] = smallimage_info.pop('special')
    smallimage_info['tag_id'] = smallimage_info.pop('tag')
    for key in ['diary_id', 'topic_id', 'activity_id']:
        smallimage_info[key] = smallimage_info.pop(key) or None

    if 'cities' in smallimage_info.keys():
        smallimage_info.pop('cities')
    if smallimage_id is None:
        try:
            smallimage = SmallImage.objects.create(**smallimage_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            smallimage = SmallImage.objects.get(id=smallimage_id)
            for k, v in smallimage_info.iteritems():
                setattr(smallimage, k, v)
            smallimage.save()
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException

    return smallimage.id


@bind_context(smallimage_pre + '/listupdate')
def smallimage_listupdate(ctx, items):
    info = []
    for obj in items:
        smallimage = SmallImage.objects.get(pk=obj['key'])
        smallimage.is_online = obj['is_online']
        smallimage.ordering = obj['rank']
        smallimage.save()
        info.append(obj['key'])
    return info


@bind_context(smallimage_pre + '/get_visible')
def get_slide_visible(ctx):
    return SmallImage.get_visible()


@bind_context(smallimage_pre + '/set_visible')
def set_slide_visible(ctx, visible=True):
    SmallImage.set_visible(visible=visible)


@bind_context(uri_pre + '/get_button')
def get_button_layout(ctx):
    return ButtonGadget.get_buttons(page_type=GADGET_PAGE_TYPE.INDEX)


@bind_context(uri_pre + '/set_button')
def set_button_layout(ctx, layout_info):
    ButtonGadget.set_buttons(
        page_type=GADGET_PAGE_TYPE.INDEX,
        button_list=layout_info['button_list'],
        button_list_visible=layout_info['button_list_visible'])


@bind_context(uri_pre + '/sideslip/get_button')
def get_button_sideslip(ctx):
    return ButtonSideslip.get_buttons(page_type=0)


@bind_context(uri_pre + '/sideslip/set_button')
def set_button_sideslip(ctx, sideslip_info):
    ButtonSideslip.set_buttons(
        page_type=0,
        button_list=sideslip_info['button_list'])


@bind_context(uri_city + '/edit')
def edit_slide_city(ctx, slide_id, cities_info):
    if slide_id is None:
        return None
    old_cities = set(ShowCity.objects.filter(slide=slide_id))
    new_cities = set(ShowCity.objects.get_or_create(city_id=item,
                                                    slide_id=slide_id
                                                    )[0] for item in cities_info)
    for item in (old_cities - new_cities):
        item.delete()


@bind_context(uri_city + '/get')
def get_slide_city(ctx, slide_id):
    if slide_id is None:
        return None
    cities = ShowCity.objects.filter(slide=slide_id)
    list_cities = []
    for city in cities:
        list_cities.append(city.city_id)
    return list_cities


@bind_context(uri_sideskid + '/get')
def sideskidcategory_detail(ctx, obj_id, options=None):
    try:
        obj = SideSkidCategory.objects.get(id=obj_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    data = to_dict(obj, **options)
    data['polymer_id'] = obj.polymer_id
    return data


@bind_context(uri_sideskid + '/edit')
def sideskidcategory_edit(ctx, obj_id=None, obj_info=None):
    if obj_info is None:
        return None
    tag_ids = obj_info.pop('tags', [])
    if obj_info['is_online'] and obj_info['ordering'] is not None \
            and SideSkidCategory.objects.exclude(id=obj_id).filter(ordering=obj_info['ordering'], is_online=True):
        raise GaiaRPCFaultException(error=1, message='这个位置已有其它分类', data=None)
    obj = model_edit(SideSkidCategory, obj_id, obj_info)
    # process tags related
    m2m_save(Tag, obj.tags, tag_ids)

    return {'id': obj.id}


@bind_context(uri_sideskid + '/query')
def sideskidcategory_query(ctx, options):
    dqobj = SideSkidCategoryDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/get_tag_config')
def set_tag_icon(ctx, req_source=None):
    rkey = 'tabconfigdeploy{}'.format(req_source or '')
    return TabConfigDeploy.get_deploy(rkey)


@bind_context(uri_pre + '/set_tag_config')
def set_tag_icon(ctx, tab_config, req_source=None):
    rkey = 'tabconfigdeploy{}'.format(req_source or '')
    TabConfigDeploy.set_deploy(tab_config, rkey)


@bind_context(uri_pre + '/get_indextab_config')
def set_tag_icon(ctx):
    return IndextabConfig.get()


@bind_context(uri_pre + '/set_indextab_config')
def set_tag_icon(ctx, tab_config):
    IndextabConfig.set(tab_config)


@bind_context(uri_function + '/query')
def function_query(ctx, options):
    dqobj = IndexFunctionDQ()
    return dqobj.process(**options)


@bind_context(uri_function + '/get_visible')
def get_function_visible(ctx):
    return {'visible': IndexFunction.get_visible()}


@bind_context(uri_function + '/set_visible')
def set_function_visible(ctx, visible=True):
    IndexFunction.set_visible(visible=visible)


@bind_context(uri_function + '/edit')
def index_function_edit(ctx, id=None, data_info=None):
    if data_info['is_online']:
        IndexFunction.objects.filter(
            user_type=data_info['user_type'],
            is_payment=data_info['is_payment'],
            is_online=True).update(is_online=False)
    if id is None:
        obj = IndexFunction.objects.create(**data_info)
    else:
        obj = IndexFunction.objects.get(id=id)
        for k, v in data_info.iteritems():
            setattr(obj, k, v)
        obj.save()
    return obj.id


@bind('doctor/ssc/list')
def ssc_list():
    result = [{
        'id': ssc.id,
        'name': ssc.name
    } for ssc in SideSkidCategory.objects.filter(is_online=True)]
    return result


@bind(uri_sideskid + '/ssc/list')
def ssc_list():
    result = [{
        'id': ssc.id,
        'name': ssc.name
    } for ssc in SideSkidCategory.objects.filter(is_online=True)]
    return result


@bind(uri_sideskid + '/getname_byid')
def ssc_get_namebyid(ssc_id):
    ssc = SideSkidCategory.objects.get(id=ssc_id)
    return {'id': ssc.id, 'name': ssc.name}

@transaction.atomic()
@bind_context(slide_pre + '/feedoperatev2_replication')
def feedoperatev2_replication(ctx, feedoperatev2_id=None):
    #feeds流插入复制
    with transaction.atomic():
        old_feedoperatev2 = FeedOperateV2.objects.get(id=feedoperatev2_id)
        feedoperatev2 = FeedOperateV2.objects.create(
            name=old_feedoperatev2.name,
            location=old_feedoperatev2.location,
            tab_id=old_feedoperatev2.tab_id,
            image=old_feedoperatev2.image,
            service_type=old_feedoperatev2.service_type,
            show_type=old_feedoperatev2.show_type,
            card_type=old_feedoperatev2.card_type,
            card_id=old_feedoperatev2.card_id,
            user_type=old_feedoperatev2.user_type,
            payment_type=old_feedoperatev2.payment_type,
            is_online=old_feedoperatev2.is_online,
            rank=old_feedoperatev2.rank,
            width=old_feedoperatev2.width,
            height=old_feedoperatev2.height,
            start_time=old_feedoperatev2.start_time,
            end_time=old_feedoperatev2.end_time,
        )
        feedoperatev2.regions = list(old_feedoperatev2.regions.values_list('id', flat=True))
        feedoperatev2.cities = list(old_feedoperatev2.cities.values_list('id', flat=True))
    return {'id': feedoperatev2.id}
