# coding=utf-8
from gm_logging.utils import logging_exception

from hera.queries.advertise_management import AdvertiseManagementDQ
from rpc.decorators import bind_context, bind
from api.models.advertise_management import AdvertiseManagement, ExtendTips, TagRelationAd
from api.models import City
from django.db import IntegrityError
from django.db import transaction
from django.conf import settings
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.dict_mixin import to_dict
from rpc.cache import req_data_cache
from django.db.models import Q, Count
import json
from gm_types.gaia import ADVER_MANAGEMENT_TYPE
from api.models.service import Service
from api.models.doctor import Doctor
from api.models.tag import Tag
from rpc.tool.queryset_tool import queryset_dec
from api.tasks.export_excel_task import export_advertisemanagement_excel

uri_pre = 'hera/advertisemanagement'

@bind_context(uri_pre + '/query')
def advertise_management_query(ctx, options):
    req_data_cache.set(ctx.session.session_key + 'advertise_management', json.dumps(options))
    dqobj = AdvertiseManagementDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/get')
def advertise_management_get(ctx, advertise_management_id):
    """
    获取广告位根据id
    """
    if advertise_management_id is None:
        return None
    try:
        advertise_management = AdvertiseManagement.objects.get(id=advertise_management_id)
    except IntegrityError:
        raise RPCIntegrityError
    advertise_management_data = to_dict(advertise_management)
    advertise_management_data['tags'] = [tag.id for tag in advertise_management.tags.all()]
    advertise_management_data['search_words'] = ';'.join(advertise_management.get_search_words)
    advertise_management_data['show_position'] = advertise_management.get_show_position
    if advertise_management.adver_type != ADVER_MANAGEMENT_TYPE.SERVICE:
        advertise_management_data['doctor_type'] = advertise_management.doctor.doctor_type
    return advertise_management_data


@bind_context(uri_pre + '/edit')
@transaction.atomic
def advertise_management_edit(ctx, advertise_management_id=None, advertise_management_info=None, urls=None):
    if advertise_management_info is None:
        return None

    advertise_management_info['service_id'] = advertise_management_info.pop('service') or None
    advertise_management_info['doctor_id'] = advertise_management_info.pop('doctor') or None
    advertise_management_info['extend_tip_id'] = advertise_management_info.pop('extend_tip')
    tags = advertise_management_info.pop('tags')
    advertise_management_info['show_position'] = ','.join(advertise_management_info.pop('show_position'))
    search_words = advertise_management_info.pop('search_words').split(';')
    while '' in search_words:
        search_words.remove('')
    advertise_management_info['search_words'] = json.dumps(search_words)

    if advertise_management_info['adver_type'] == ADVER_MANAGEMENT_TYPE.SERVICE:
        show_citys = Service.objects.get(id=advertise_management_info['service_id']).doctor.hospital.city_id
    elif advertise_management_info['adver_type'] == ADVER_MANAGEMENT_TYPE.DOCTOR:
        #show_citys = Doctor.objects.get(id=advertise_management_info['doctor_id']).hospital.city_id
        show_citys = advertise_management_info.pop('show_city')
    #citys.append(show_citys)
    if show_citys:
        citys = show_citys
    else:
        citys = []

    if advertise_management_id is None:
        try:
            advertise_management = AdvertiseManagement.objects.create(**advertise_management_info)
        except IntegrityError:
            raise RPCIntegrityError

    if citys:
        new_citys = set(City.objects.filter(id__in=citys))
        old_citys = set(advertise_management.show_city.all())
        advertise_management.show_city.add(*(new_citys - old_citys))
        advertise_management.show_city.remove(*(old_citys - new_citys))
        advertise_management.save()
    if tags:
        new_tags = set(Tag.objects.filter(id__in=tags))
        old_tags = set(advertise_management.tags.all())
        for tag in (new_tags - old_tags):
            TagRelationAd.objects.get_or_create(advertisemanagement = advertise_management, tag = tag)
        TagRelationAd.objects.filter(advertisemanagement = advertise_management,
                                     tag__in=(old_tags - new_tags)).delete()


    return advertise_management.id


@bind_context(uri_pre + '/list_update')
def advertise_management_update_onlines(ctx, items):
    for item in items:
        advertise_management = AdvertiseManagement.objects.get(id=item['key'])
        if item.get('ordering'):
            advertise_management.ordering = item['ordering']
        else:
            advertise_management.is_online = item['is_online']
        advertise_management.save()
    return items


@bind_context(uri_pre + '/add_extendtips')
def add_extendtips(ctx, tip_name):
    if tip_name:
        extendtip = ExtendTips(tip_name=tip_name)
        extendtip.save()
    return extendtip.id


@bind_context('hera/extend_tips/choices')
def extend_tips_choices(ctx, q='', page=1, num=30, initial=None):
    page = int(page)
    num = int(num)

    if initial is not None:
        if isinstance(initial, (list, tuple)):
            qry = Q(id__in=initial)
        else:
            qry = Q(id=initial)
    else:
        qry = Q(id__contains=q) | Q(tip_name__contains=q)
    query = ExtendTips.objects.using(settings.SLAVE_DB_NAME).filter(qry)
    total_count = 0
    start_pos = (page - 1) * num
    start_pos = start_pos if start_pos >= 0 else 0
    results = [
        {
            'id': obj.id,
            'text': u'{}:{}'.format(obj.id, obj.tip_name),
        } for obj in query[start_pos: start_pos+num]
    ]
    return {'total_count': total_count, 'results': results, 'page': page, 'num': num}


@bind_context(uri_pre + '/get_show_city')
def add_extendtips(ctx, adver_type, id):
    if adver_type == ADVER_MANAGEMENT_TYPE.SERVICE:
        doctor = Service.objects.get(id=id).doctor
    else:
        doctor = Doctor.objects.get(id=id)
    hospital = getattr(doctor, 'hospital', None)
    return hospital.city.name if hospital else ''

@bind_context(uri_pre + '/export_excel')
def advertise_management_export_excel(ctx, nos, adver_type):
    user = ctx.session.user
    dqobj = AdvertiseManagementDQ()
    if nos != 'selectall':
        advertise_management = AdvertiseManagement.objects.filter(id__in=nos)
    else:
        options = json.loads(req_data_cache.get(ctx.session.session_key + 'advertise_management'))
        options.pop('paging')
        options.pop('columns')
        advertise_management = dqobj.build_queryset(**options)
    export_advertisemanagement_excel.delay(queryset_dec(advertise_management), user.email, adver_type)
    return {'message': 'success'}


@bind("advertisemanagement/auto_create")
def advertise_management_create(data):
    try:
        #城市处理
        cities = data["cities"]
        provinces = data["provinces"]
        all_cities = set()
        for item in cities:
            all_cities.add(item['id'])
        for item in provinces:
            cities_ls = set(City.objects.filter(province_id=item["id"]).values_list("id", flat=True))
            all_cities ^= cities_ls
        service_id = data["service_id"]
        service = Service.objects.get(id=service_id)
        obj = AdvertiseManagement.objects.create(service_id=service_id, show_position=2, start_time=data['start_time'], end_time=data['end_time'], extend_tip_id=data['tip_id'],
                                                 doctor_id=service.doctor_id, ordering=data['position'])
        obj.show_city = all_cities
        #关联tag处理
        obj.tags = service.tags.all()
        obj.save()
        return {"result": "success"}
    except:
        logging_exception()
        return {"result": "fail"}
