# -*- coding: UTF-8 -*-
from django.db import IntegrityError
from django.db.models import Q, Min
from django.db import transaction
from api.tool.servicehome_tool import ServiceHomeLayout
from hera.queries.servicerecommend import ServiceRecommendDQ
from launch.models import ServiceConfigureRelevant, ServiceConfigureRelationCity, ServiceConfigureRelationRegion
from rpc.tool.error_code import CODES, gen
from rpc.decorators import bind_context
from api.models.slide import Slide
from api.models.special import Special
from api.models.servicehome import ServiceActivity, ServiceRecommend
from rpc.tool.dict_mixin import to_dict
from api.models.types import SERVICE_ACTIVITY_TYPE
from ..datatables import SpecialItemDT
from api.models.special import SpecialItem
from rpc.tool.log_tool import info_logger
from api.models.service import ServiceFilter, Service
from rpc.tool.log_tool import logging_exception
from api.tool.servicehome_tool import BasicServiceHomeFilter
from hera.datatables import DataTable
from gm_types.gaia import SLIDE_POSITION
from gm_types.gaia import SERVICE_FILTER_TYPE
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException

from rpc.exceptions import GaiaRPCFaultException
from ..queries.servicehome import RecommendDQ, ServiceFilterDQ
from api.models import CategoryGadget, ServiceHomeOperation, ServiceRelatedOperation
from api.tool.servicehome_tool import SeckillDeploy, SceneButton, SideButton

uri_pre = 'hera/servicehome'


@bind_context(uri_pre + '/get_layout')
def layout_get(ctx):
    layout = ServiceHomeLayout.get()
    return layout


@bind_context(uri_pre + '/set_layout')
def layout_set(ctx, layout_info):
    ServiceHomeLayout.set(layout_info)
    return gen(CODES.SUCCESS)


@bind_context(uri_pre + '/get_slide_visible')
def get_slide_visible(ctx):
    return Slide.get_visible(position=SLIDE_POSITION.SERVICE_HOME)


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


@bind_context(uri_pre + '/get_filter')
def filter_get(ctx):
    layout = BasicServiceHomeFilter.get()
    return layout


@bind_context(uri_pre + '/set_filter')
def filter_set(ctx, layout_info):
    BasicServiceHomeFilter.set(layout_info)
    return gen(CODES.SUCCESS)


@bind_context(uri_pre + '/recommend_get')
def recommend_get(ctx):
    try:
        special_recommend = Special.objects.get(type=Special.SPECIAL_TYPE.RECOMMEND)
    except Special.DoesNotExist:
        special_recommend = Special()
        special_recommend.title = u'所长推荐'
        special_recommend.type = Special.SPECIAL_TYPE.RECOMMEND
        special_recommend.save()

    return to_dict(special_recommend)


@bind_context(uri_pre + '/recommend_list')
def recommend_datatable(ctx, options):
    """
    美购推荐
    """
    dtobj = ServiceRecommendDQ()
    return dtobj.process(**options)


@bind_context(uri_pre + '/recommend_edit')
def special_recommend_edit(ctx, recommand_items):
    if not recommand_items:
        return
    item_ids = []
    for item_info in recommand_items:
        try:
            with transaction.atomic():
                servicerecommand_item = ServiceRecommend.objects.get_or_create(service_id=item_info['service_id'])[0]
                for k, v in item_info.iteritems():
                    setattr(servicerecommand_item, k, v)
                servicerecommand_item.is_delete = False
                servicerecommand_item.save()
        except Exception as e:
            info_logger.info(__import__('traceback').format_exc())
            continue
        item_ids.append(servicerecommand_item.id)
    return item_ids


@bind_context(uri_pre + '/recommend_listupdate')
def recommend_listupdate(ctx, items):
    info = []
    for obj in items:
        recommend_item = ServiceRecommend.objects.get(pk=obj['key'])
        recommend_item.rank = obj['rank']
        recommend_item.is_recommend = obj['is_recommend']
        recommend_item.save()
        info.append(obj['key'])
    return info


@bind_context(uri_pre + '/recommend_del')
def recommend_delitem(ctx, recommendid):
    servicecommend = ServiceRecommend.objects.get(id=recommendid)
    servicecommend.is_delete = True
    servicecommend.save()


@bind_context(uri_pre + '/add_service')
def recommend_add_service(ctx, serviceids):
    """
    批量添加service
    """
    if not serviceids:
        return []
    services = Service.objects.filter(id__in=serviceids)
    data = []
    for service in services:
        try:
            serviceitems_price_info = [x.get_default_price_info() for x in service.items.filter(is_delete=False)]

            serviceitems_price_info.sort(key=lambda x: x['pre_payment_price'])
            if len(serviceitems_price_info) > 0:
                data.append({
                    'service_id': service.id,
                    'service_name': service.name,
                    'service_pre_payment_price': serviceitems_price_info[0]['pre_payment_price'],
                    'service_gengmei_price': serviceitems_price_info[0]['gengmei_price'],
                    'service_discount': serviceitems_price_info[0]['discount'],
                })
        except:
            info_logger.info(__import__('traceback').format_exc())
            continue
    return data


@bind_context(uri_pre + '/activity/edit')
def service_activity_edit(ctx, activity_type, activity_info=None):
    valid_type = [k for k, desc in SERVICE_ACTIVITY_TYPE]
    if activity_type is None or activity_type not in valid_type:
        raise GaiaRPCFaultException(error=1, message=u'无效的活动类型', data=None)

    activity = ServiceActivity.objects.filter(activity_type=activity_type)
    name = SERVICE_ACTIVITY_TYPE.getDesc(activity_type)
    if len(activity) == 0:
        activity = ServiceActivity()
        activity.name = name
        activity.activity_type = activity_type
        activity.save()

    activity = activity[0]
    if activity_info is not None:
        activity_info['special_id'] = activity_info.pop('special', None)
        for k, v in activity_info.iteritems():
            setattr(activity, k, v)
        activity.save()

    return to_dict(activity)


@bind_context(uri_pre + '/add_service_filter')
def service_add_filter_item(ctx, data):
    """
    添加美购筛选项
    """
    if data.get('type') == SERVICE_FILTER_TYPE.TIP:
        filters = ServiceFilter.objects.filter(type=SERVICE_FILTER_TYPE.TIP, value=data.get('value'))
        if filters:
            raise GaiaRPCFaultException(error=1, message=u'tip重复', data=None)

    service_filter = ServiceFilter.objects.create(**data)
    return {
        'id': service_filter.id,
    }


@bind_context(uri_pre + '/edit_service_filter')
def service_edit_filter(ctx, filters, items):
    for item in items:
        service_filter = ServiceFilter.objects.get(id=item['id'])
        service_filter.ordering = item['ordering']
        service_filter.is_online = item['is_online']
        service_filter.save()
    return {}


@bind_context(uri_pre + '/service_filter_query')
def service_filter_query(ctx, options):
    dqobj = ServiceFilterDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/service_filter_list')
def service_filter_datatable(ctx, req_data):
    dtobj = DataTable(ServiceFilter)
    return dtobj.process(req_data)


@bind_context(uri_pre + '/service_filter_get')
def service_filter_detail(ctx, service_filter_id, options=None):
    try:
        service_filter = ServiceFilter.objects.get(id=service_filter_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    data = to_dict(service_filter, **options)
    return data


@bind_context(uri_pre + '/service_filter_edit')
def service_filter_edit(ctx, service_filter_id=None, service_filter_info=None):
    if service_filter_info is None:
        return None

    if service_filter_id is None:
        # 不能添加名字重复的 tip
        if int(service_filter_info['type']) == SERVICE_FILTER_TYPE.TIP:
            filters = ServiceFilter.objects.filter(type=SERVICE_FILTER_TYPE.TIP, value=service_filter_info['value'])
            if filters:
                raise GaiaRPCFaultException(error=1, message=u'tip名称重复', data=None)

        try:
            service_filter = ServiceFilter.objects.create(**service_filter_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        # 不能添加名字重复的 tip
        if int(service_filter_info['type']) == SERVICE_FILTER_TYPE.TIP:
            q = ~Q(id=service_filter_id)
            q &= Q(type=SERVICE_FILTER_TYPE.TIP, value=service_filter_info['value'])
            filters = ServiceFilter.objects.filter(q)
            if filters:
                raise GaiaRPCFaultException(error=1, message=u'tip名称重复', data=None)

        try:
            service_filter = ServiceFilter.objects.get(id=service_filter_id)
            for k, v in service_filter_info.iteritems():
                setattr(service_filter, k, v)
            service_filter.save()
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException

    return service_filter.id


@bind_context(uri_pre + '/categorygadget_edit')
def categorygadget_edit(ctx, categorygadget_id=None, categorygadget_info=None):

    if categorygadget_id is None:
        categorygadget = CategoryGadget.objects.create(**categorygadget_info)
    else:
        categorygadget = CategoryGadget.objects.get(id=categorygadget_id)
        for k, v in categorygadget_info.iteritems():
            setattr(categorygadget, k, v)
        categorygadget.save()
    return {
        'categorygadget_id': categorygadget.id,
    }


@bind_context(uri_pre + '/seckill/get')
def seckill_show(ctx):
    return SeckillDeploy.get()


@bind_context(uri_pre + '/seckill/edit')
def seckill_edit(ctx, deploy_info):
    SeckillDeploy.set(deploy_info)


@bind_context(uri_pre + '/scenebutton/get')
def seckill_show(ctx):
    return SceneButton.get()


@bind_context(uri_pre + '/scenebutton/edit')
def seckill_edit(ctx, deploy_info):
    SceneButton.set(deploy_info)


@bind_context(uri_pre + '/side_button/get')
def side_show(ctx):
    return SideButton.get()


@bind_context(uri_pre + '/side_button/edit')
def side_edit(ctx, deploy_info):
    SideButton.set(deploy_info)


@bind_context(uri_pre + '/operation_edit')
def operation_edit(ctx, id=None, info=None):
    details = info.pop('details', [])
    if id is None:
        regions = info.pop('regions')
        cities = info.pop('cities')
        operation = ServiceHomeOperation.objects.create(**info)
        operation.regions = regions
        operation.cities = cities
    else:
        operation = ServiceHomeOperation.objects.get(id=id)
        for k, v in info.iteritems():
            setattr(operation, k, v)
        operation.save()
        ServiceRelatedOperation.objects.filter(servicehome_id=id).delete()
    for d in details:
        if d['id'] == '':
            continue
        related_info = {}
        related_info['image'] = d['img']
        related_info['jump_id'] = d['id']
        related_info['position'] = int(d['num']) + 1
        related_info['jump_type'] = int(d['jump_type'])
        related_info['servicehome_id'] = operation.id
        ServiceRelatedOperation.objects.create(**related_info)
    return {
        'operation_id': operation.id,
    }


@bind_context(uri_pre + '/relatedoperation_filter_get')
def relatedoperation_filter_get(ctx, servicehome_id=None, options=None):
    try:
        s = ServiceHomeOperation.objects.get(id=servicehome_id)
        relatedoperation = ServiceRelatedOperation.objects.filter(servicehome_id=servicehome_id)
    except:
        raise RPCNotFoundException
    data = [{},{},{}]
    for i in relatedoperation:
        info = {}
        info['img'] = i.image
        info['id'] = i.jump_id
        info['jump_type'] = i.jump_type
        data[int(i.position)-1]=info
    return {
            "details": data,
            "display_port": s.display_port,
            'operation_type':s.operation_type,
            'start_time':str(s.start_time),
            'end_time':str(s.end_time),
            'user_type':s.user_type,
            'payment_type':s.payment_type,
            'is_online':s.is_online,
            'regions':list(s.regions.values_list('id',flat=True)),
            'cities':list(s.cities.values_list('id',flat=True)),
            'device_type': s.device_type
        }

@bind_context(uri_pre + '/operation_replication')
def operation_replication(ctx, id=None):
    # 美购首页运营位复制功能
    old_operation = ServiceHomeOperation.objects.get(id=id)
    with transaction.atomic():
        servicehomeoperation = ServiceHomeOperation.objects.create(
            operation_type=old_operation.operation_type,
            start_time=old_operation.start_time,
            end_time=old_operation.end_time,
            user_type=old_operation.user_type,
            payment_type=old_operation.payment_type,
            is_online=old_operation.is_online,
            display_port=old_operation.display_port,
            details=old_operation.details,
            device_type=old_operation.device_type
        )
        servicehomeoperation.regions = list(old_operation.regions.values_list('id',flat=True))
        servicehomeoperation.cities = list(old_operation.cities.values_list('id',flat=True))
        old_servicerelatedoperation = ServiceRelatedOperation.objects.filter(servicehome_id=id)
        if old_servicerelatedoperation:
            ServiceRelatedOperation.objects.bulk_create([
                ServiceRelatedOperation(
                    image=servicerelatedoperation.image,
                    jump_id=servicerelatedoperation.jump_id,
                    jump_type=servicerelatedoperation.jump_type,
                    servicehome=servicehomeoperation,
                    position=servicerelatedoperation.position,
                )
                for servicerelatedoperation in old_servicerelatedoperation]
            )
    return {
        'operation_id': servicehomeoperation.id,
    }

@bind_context(uri_pre + '/delete')
def service_configure_delete(ctx, service_configure_relevant_id):
    """
    根据ID删除一个service_configure_relevant
    """
    service_configure_relevant = ServiceConfigureRelevant.objects.get(pk=service_configure_relevant_id)
    with transaction.atomic():
        service_configure_relevant.delete()
        ServiceConfigureRelationCity.objects.filter(service_configure_relevant_id=service_configure_relevant_id).delete()
        ServiceConfigureRelationRegion.objects.filter(service_configure_relevant_id=service_configure_relevant_id).delete()

    return {'id': service_configure_relevant_id}
