# coding=utf-8

from django.db import transaction
from hera.queries.singlerecord import SingleRecordDQ
from hera.queries.tickets import TicketsDQ
from hera.queries.ticketsresult import TicketsResultDQ
from rpc.decorators import bind_context
from api.models import SingleRecord, Service, Order
from api.models.tickets import Tickets, TicketsResult, TicketsresultRecord, TicketsResultDetail
from django.db import IntegrityError
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.log_tool import info_logger
from rpc.tool.dict_mixin import to_dict
from rpc.cache import req_data_cache
from hera.actions.order import OrderAction
from gm_types.gaia import TICKETS_STATUS
import json
import datetime
from rpc.tool.queryset_tool import queryset_dec
from api.tasks.export_excel_task import export_budan_support_excel

from django.db.models import Q
from hera.utils import check_business, reset_username, get_business_team
from hera.queries.budan import BuDanDQ

uri_pre = 'hera/singlerecord'


@bind_context(uri_pre + '/edit')
def singlerecord_edit(ctx, singlerecord_id=None, singlerecord_info=None, urls=None, is_createtickes=False):
    user = ctx.session.user
    if singlerecord_info is None:
        return None
    singlerecord_info['doctor_id'] = singlerecord_info.pop('doctor')
    singlerecord_info['service_id'] = singlerecord_info.pop('service')
    singlerecord_info['user_id'] = singlerecord_info.pop('user')
    singlerecord_info['order_id'] = singlerecord_info.pop('order') or None
    singlerecord_info['tickets_time'] = singlerecord_info['tickets_time'] or None
    if singlerecord_info['service_id']:
        service = Service.objects.get(id=singlerecord_info['service_id'])
        if service.doctor_id != singlerecord_info['doctor_id']:
            return {
                'error': 1,
                'msg': '医生与美购不关联'
            }

    if singlerecord_info['order_id']:
        order = Order.objects.get(id=singlerecord_info['order_id'])
        if str(order.user_id) != str(singlerecord_info['user_id']):
            return {
                'error': 1,
                'msg': '订单与用户不关联'
            }
        if order.service.doctor_id != singlerecord_info['doctor_id']:
            return {
                'error': 1,
                'msg': '订单与医生不关联'
            }
        if singlerecord_info['service_id']:
            service = Service.objects.get(id=singlerecord_info['service_id'])
            if order.service_id != service.id:
                return {
                    'error': 1,
                    'msg': '订单与美购不关联'
                }

    if is_createtickes and not singlerecord_info['tickets_time']:
        return {
            'error': 1,
            'msg': '生成罚单时，开罚单时间不能为空'
        }
    tickets = None
    if is_createtickes:
        tickets, _ = Tickets.objects.get_or_create(tickets_time=singlerecord_info['tickets_time'],
                                                   doctor_id=singlerecord_info['doctor_id'])
        if tickets.is_valid and tickets.status != TICKETS_STATUS.DEFAULT:
            return {
                'error': 1,
                'msg': '罚单已开始处罚，不可再加入飞单'
            }

    if singlerecord_id is None:
        try:
            singlerecord = SingleRecord.objects.create(**singlerecord_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            singlerecord = SingleRecord.objects.get(id=singlerecord_id)
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException

        if singlerecord.tickets and singlerecord.tickets.status != TICKETS_STATUS.DEFAULT:
            return {
                'error': 1,
                'msg': '改罚单已开始处罚，不可再加入飞单'
            }

        for k, v in singlerecord_info.iteritems():
            setattr(singlerecord, k, v)
    if tickets:
        singlerecord.tickets_id = tickets.id
        tickets.is_valid = True
        tickets.save()
        result = getattr(tickets.doctor, 'ticketsresult', None)
        if result:
            edit_ticketresult(tickets, user, True)

    if not singlerecord.create_user:
        singlerecord.create_user = user
    singlerecord.save()

    return {
        'error': 0,
        'singlerecord_id': singlerecord.id,
        'msg': '罚单已生成，可前往罚单列表查看' if is_createtickes else '飞单保存成功'
    }


@bind_context(uri_pre + '/get')
def singlerecord_get(ctx, singlerecord_id):
    """
    获取飞单根据id
    """
    if singlerecord_id is None:
        return None
    try:
        singlerecord = SingleRecord.objects.get(id=singlerecord_id)
    except IntegrityError:
        raise RPCIntegrityError
    singlerecord_data = to_dict(singlerecord)
    singlerecord_data['single_date'] = singlerecord_data['single_date'].split()[0]
    singlerecord_data['tickets_time'] = singlerecord_data['tickets_time'].split()[0] if singlerecord.tickets_time else None
    if singlerecord.tickets_time and (datetime.datetime.now() - singlerecord.tickets_time).days <= 5:
        singlerecord_data['is_stale'] = False
    else:
        singlerecord_data['is_stale'] = True
    return singlerecord_data


@bind_context(uri_pre + '/update_revote')
def single_update_revote(ctx, singlerecord_id):
    """
    撤销时判断是否相应罚单有效，判断对应罚单是否在处罚中，如果是，更改处罚天数
    """
    user = ctx.session.user
    singlerecord = SingleRecord.objects.get(id=singlerecord_id)
    singlerecord.is_revoke = True
    singlerecord.save()
    tickets = singlerecord.tickets
    tickets.change_valid()
    edit_ticketresult(tickets, user, True)
    return singlerecord.id


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


@bind_context(uri_pre + '/tickets_get')
def tickets_get(ctx, tickets_id=None):
    if tickets_id is None:
        return None
    tickets = Tickets.objects.get(id=tickets_id)
    tickets_data = to_dict(tickets)
    tickets_data['tickets_time'] = tickets_data['tickets_time'].split()[0]
    tickets_data['doctor'] = tickets.doctor.name
    tickets_data['hosptial'] = tickets.doctor.hospital.name if tickets.doctor.hospital_id else u''
    tickets_data['singlerecords'] = list(tickets.singlerecord.filter(is_revoke=False).values_list('id', flat=True))
    tickets_data['status_data'] = TICKETS_STATUS.getDesc(tickets.status)
    return tickets_data


@bind_context(uri_pre + '/tickets_status')
def tickets_update_status(ctx, tickets_id=None, status=None):
    user = ctx.session.user
    if tickets_id is None or status is None or status == TICKETS_STATUS.DEFAULT:
        return None
    tickets = Tickets.objects.get(id=tickets_id)
    if datetime.datetime.now().date() < tickets.tickets_time.date():
        return {
            'msg': u'操作时间不能小于开罚单时间！',
            'tickets_id': None
        }
    tickets.status = status
    tickets.save()
    edit_ticketresult(tickets, user)
    return {
        'msg': u'操作成功！',
        'tickets_id': tickets.id
    }


@bind_context(uri_pre + '/result_query')
def tickets_query(ctx, options):
    dqobj = TicketsResultDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/result_get')
def tickets_get(ctx, result_id=None):
    if result_id is None:
        return None
    result = TicketsResult.objects.get(id=result_id)
    result_date = to_dict(result)
    result_date['doctor'] = result.doctor.name
    result_date['hospital'] = result.doctor.hospital.name if result.doctor.hospital_id else u''
    result_date['start_sink'] = str(result.start_sink).split()[0]
    result_date['end_sink'] = str(result.end_sink).split()[0]
    result_date['sink_services'] = list(result.service_set.values_list('id', flat=True))
    result_date['connect_tickets'] = list(result.tickets_set.values_list('id', flat=True))
    result_date['result_record'] = [
        {
            'start_sink': str(record.start_sink).split()[0],
            'end_sink':str(record.end_sink).split()[0]
        }
        for record in TicketsresultRecord.objects.filter(tickets_result=result).order_by('-end_sink')]
    return result_date


def edit_ticketresult(tickets, user=None, update_single=False):
    with transaction.atomic():
        now = datetime.datetime.now().date()
        result = getattr(tickets.doctor, 'ticketsresult', None)
        if update_single:
            start_sink = result.start_sink
        else:
            start_sink = now + datetime.timedelta(days=1)
            if result:
                if start_sink <= result.end_sink.date():
                    start_sink = result.start_sink
                else:
                    if result.sink_days != 0:
                        TicketsresultRecord.objects.create(tickets_result=result, start_sink=result.start_sink,
                                                           end_sink=result.end_sink)
                    result.tickets_set.update(tickets_result_id=None)
            else:
                result = TicketsResult.objects.create(doctor=tickets.doctor)
            tickets.tickets_result_id = result.id
            tickets.save()

        tickets_list = list(Tickets.objects.filter(is_valid=True, doctor=tickets.doctor).order_by('tickets_time'))
        result_tickets = result.tickets_set.all()
        sink_days = 0
        for obj in result_tickets:
            tickets_num = tickets_list.index(obj) + 1
            single_num = obj.single_num
            if obj.status == TICKETS_STATUS.EXPIRED:
                obj_sink_days = 30 * tickets_num + 20 * (single_num - 1)
            else:
                obj_sink_days = 15 * tickets_num + 10 * (single_num - 1)
            sink_days += obj_sink_days
        end_sink = start_sink + datetime.timedelta(days=sink_days)

        if update_single:
            if end_sink.date() <= now <= result.end_sink.date():
                sink_days = (now - start_sink.date()).days
                end_sink = now
            elif end_sink.date() >= now:
                end_sink = end_sink
                sink_days = sink_days
            else:
                end_sink = result.end_sink
                sink_days = result.sink_days

        result.start_sink = start_sink
        result.end_sink = end_sink
        result.sink_days = sink_days
        result.save()

        old_service = set(result.service_set.all())
        new_service = []
        for obj in result.tickets_set.all():
            new_service += obj.sink_services
        new_service = set(new_service)
        for del_service in old_service - new_service:
            del_service.tickets_result_id = None
            del_service.save()

        for add_service in new_service - old_service:
            add_service.tickets_result_id = result.id
            add_service.save()

        # 操作记录
        try:
            tickets_list = list(result.tickets_set.values_list('id', flat=True))
            service_list = list(result.service_set.values_list('id', flat=True))
            result_detail_date = {
                'tickets_result_id': result.id,
                'start_sink': result.start_sink,
                'end_sink': result.end_sink,
                'sink_days': result.sink_days,
                'user': user,
                'tickets_list': map(str, tickets_list),
                'service_list': map(str, service_list)
            }
            TicketsResultDetail.objects.create(**result_detail_date)
        except:
            pass

@bind_context(uri_pre + '/budan_query')
def budan_query(ctx, options):
    init_q = None
    _in, businessman_list, team_groups = get_business_team(ctx)
    if _in:
        init_q = Q(doctor__business_partener__in=businessman_list) | Q(doctor__business_group__in=team_groups)
    req_data_cache.set(ctx.session.session_key + 'budan', json.dumps(options))
    dqobj = BuDanDQ(init_q=init_q)
    return dqobj.process(**options)

@bind_context(uri_pre + '/budan_export_excel')
def budan_export_excel(ctx):
    """
    补单导出
    :param ctx:
    :return:
    """
    init_q = Q()
    _in, businessman_list, team_groups = get_business_team(ctx)
    if _in:
        init_q = Q(doctor__business_partener__in=businessman_list) | Q(doctor__business_group__in=team_groups)
    dqobj = BuDanDQ(init_q=init_q)
    options = json.loads(req_data_cache.get(ctx.session.session_key + 'budan'))
    options.pop('paging')
    options.pop('columns')
    datas = dqobj.build_queryset(**options)
    export_budan_support_excel.delay(queryset_dec(datas, need_instant_data=True), ctx.session.user)
