# -*- coding: utf-8 -*-

from __future__ import unicode_literals

from django.db.models import Q, Sum, Count, FloatField, F
from django.db.models.functions import Coalesce
from gm_types.gaia import ORDER_STATUS, SERVICE_SELL_TYPE, DOCTOR_TYPE
from gm_types.trade import STATEMENT_OPERATION_TYPE, STATEMENT_STATUS
import tablib

from api.models import DoctorAccount, Order, Doctor
from api.tool.user_tool import get_doctor_from_context
from pay.models.operation import StatementOperation
from pay.models.statement import Statement, StatementAccount
from rpc.decorators import bind_context
from rpc.exceptions import RPCNotFoundException
from rpc.tool.dict_mixin import to_dict
from rpc.tool.time_tool import get_timestamp_epoch
from rpc.tool.error_code import CODES, gen


@bind_context('doctor/statement/detail')
def statement_detail(ctx, statement_id):
    """对账单详情, 收款方信息,结算总金额信息"""
    doctor = get_doctor_from_context(ctx)
    try:
        statement = Statement.objects.get(id=statement_id, doctor=doctor)
    except:
        raise RPCNotFoundException

    statement_data = {
        'id': statement.id,
        'statement_date': statement.statement_date,
        'feededuction_sum': statement.feededuction_sum,
        'settle_price': statement.settle_price,
        'poundage': statement.poundage,
        'pre_payment_price': statement.original_amount,
        'pos_back': statement.pos_back,
        'status': STATEMENT_STATUS.getDesc(statement.status),
        'button_visible': True if statement.status == STATEMENT_STATUS.AUDITED else False,
    }

    # 处理遗留的对账单问题，直接取对账单的account
    account, _ = StatementAccount.objects.get_or_create(statement_id=statement_id)
    statement_data.update(to_dict(account, excludes=['id']))

    return statement_data


@bind_context('doctor/statement/deduction')
def feededuction(ctx, statement_id):
    """补扣款详情"""
    doctor = get_doctor_from_context(ctx)
    try:
        statement = Statement.objects.get(id=statement_id, doctor=doctor)
    except:
        raise RPCNotFoundException
    replenishments = [to_dict(obj) for obj in statement.fee_deduction.filter(value__lt=0)]
    for replenishment in replenishments:
        replenishment['value'] = abs(replenishment['value'])
    return {
        'deductions': [to_dict(obj) for obj in statement.fee_deduction.filter(value__gt=0)],
        'replenishment': replenishments,
        'total': statement.feededuction_sum,
    }


@bind_context('doctor/statement/query')
def statement_list(ctx, start_num=0, count=10, query={}, global_field=[], global_key='', order_by=[]):
    """美购对账单, 首页的列表,
    add: 增加返回is_officer字段表示是否是机构管理者"""
    q = Q(**query)
    doctor = get_doctor_from_context(ctx)
    q &= Q(doctor=doctor)
    if global_key:
        global_q = Q()
        for field in global_field:
            global_q |= Q(**{field: global_key})
        q &= global_q

    statements = Statement.history_objects.filter(q)

    if 'totalprice' in order_by or '-totalprice' in order_by:
        statements = statements.annotate(totalprice=Sum(u'orders__servicesnapshot__gengmei_price'))
    if 'settleprice' in order_by or '-settleprice' in order_by:
        statements = statements.annotate(
            settleprice=(Coalesce(F(u'original_amount'), 0) - Coalesce(Sum(
                u'fee_deduction__value', output_field=FloatField()), 0)) * (100 - Coalesce(F(u'poundage_rate'), 0)))
    if 'settlednum' in order_by or '-settlednum' in order_by:
        statements = statements.annotate(settlednum=Count(u'orders'))

    statements = statements.order_by(*order_by)

    total = statements.count()
    statements = statements[start_num: start_num + count]
    return {
        'total': total,
        'statements': [statement.data() for statement in statements],
    }


@bind_context('doctor/statement/operation')
def operation_list(ctx, start_num=0, count=10, query={}, global_field=[], global_key='', order_by=[]):
    q = Q(**query)
    doctor = get_doctor_from_context(ctx)
    q &= Q(statement__doctor=doctor)
    if global_key:
        global_q = Q()
        for field in global_field:
            global_q |= Q(**{field: global_key})
        q &= global_q

    operations = StatementOperation.objects.filter(q)
    operations = operations.order_by(*order_by)
    total = operations.count()
    operations = operations[start_num: start_num + count]

    def operation_data(operation):
        operator = '系统'
        if operation.operator.user == get_doctor_from_context(ctx).user:
            operator = operation.operator.user.last_name
        return {
            'id': operation.id,
            'operator': operator,
            'optype': STATEMENT_OPERATION_TYPE.getDesc(operation.optype),
            'operate_time': get_timestamp_epoch(operation.operate_at),
        }

    return {
        'total': total,
        'operations': [operation_data(operation) for operation in operations],
    }


@bind_context('doctor/statement/merchant_doctor_list')
def merchant_doctor_list(ctx, statement_id, start_num=0, count=10, order_by=None):
    """对账单详情, 机构看到列表"""
    if order_by is None:
        order_by = []
    doctor = get_doctor_from_context(ctx)
    if doctor is None or not doctor.is_merchant:
        return gen(CODES.NO_PERMISSION)
    f = Order.objects.filter(
        statement__id=statement_id,
    ).values('operate_user__doctor__name', 'operate_user__doctor')
    orders = f.annotate(
        settleprice=(Coalesce(Sum('servicesnapshot__pre_payment_price'), 0.0)
                     - Coalesce(Sum('discount'), 0.0)
                     - Coalesce(Sum('servicesnapshot__coupon_doctor_value'), 0.0)),
    )
    orders = orders.order_by(*order_by)
    total = orders.count()

    orders = orders[start_num: start_num + count]

    for order in orders:
        order['doctor_name'] = order.pop('operate_user__doctor__name')
        order['doctor_id'] = order.pop('operate_user__doctor')
    return {
        'total': total,
        'orders': list(orders),
    }


@bind_context('doctor/statement/order_query')
def order_list_query(ctx, doctor_id=None, start_num=0, count=10, query={}, global_field=[], global_key='', order_by=[]):
    """get doctor from ctx or from doctor_id
    医生订单列表
    1. 非机构商户对账单详情页列表的订单列表
    2. 机构商户点击对账单详情页列表的医生, 看到的订单列表
    """
    if doctor_id is None:
        doctor = get_doctor_from_context(ctx)
        if not doctor:
            return gen(CODES.NO_PERMISSIO)
    else:
        try:
            doctor = Doctor.objects.get(id=doctor_id)
        except Doctor.DoesNotExist:
            return gen(CODES.DOCTOR_NOT_FOUND)
    q = Q(**query)
    q = q & Q(operate_user=doctor.user)
    if global_key:
        global_q = Q()
        for field in global_field:
            global_q |= Q(**{field: global_key})
        q &= global_q
    orders = Order.objects.filter(q)

    if 'settleprice' in order_by or '-settleprice' in order_by:
        orders = orders.annotate(settleprice=F('servicesnapshot__pre_payment_price') - F('discount'))

    orders = orders.order_by(*order_by)
    total = orders.count()

    orders = orders[start_num: start_num + count]

    def obj_data(obj):
        settle_price = obj.settle_data()['settle_payment']

        return {
            'id': obj.id,
            'status': obj.status,
            'name': obj.servicesnapshot.name,
            'item': obj.order_multiattribute,
            'gengmei_price': obj.servicesnapshot.gengmei_price,
            'service_price': obj.service_price,
            'service_type': obj.servicesnapshot.service_type,
            'pre_payment_price': obj.servicesnapshot.pre_payment_price,
            'hospital_payment': obj.hospital_payment,
            'created_time': get_timestamp_epoch(obj.created_time),
            'validate_time': get_timestamp_epoch(obj.validate_time),
            'user_id': obj.user.id,
            'user_name': obj.user.last_name,
            'settle_price': settle_price,
            'renmai': obj.orderstatementrelationship.installment,
        }

    return {
        'total': total,
        'orders': [obj_data(order) for order in orders],
    }


@bind_context('doctor/statement/order_detail', login_required=True)
def statement_order_detail(ctx, order_id):
    """订单详情"""
    doctor = get_doctor_from_context(ctx)
    try:
        order = Order.objects.get(id=order_id)
    except Order.DoesNotExist:
        return gen(CODES.ORDER_NOT_FOUND)

    if not doctor.is_merchant and doctor.allow_hospital_agent:
        officer = Doctor.objects.get(hospital=doctor.hospital, doctor_type=DOCTOR_TYPE.OFFICER, is_merchant=True)
    else:
        officer = doctor
    if doctor != order.service.doctor and doctor != officer:
        return gen(CODES.NO_PERMISSION)

    data = order.settle_data()
    data['coupon_data'] = order.order_coupon_data()
    data['service_type'] = order.servicesnapshot.service_type
    return data


@bind_context('doctor/statement/export_excel')
def export_excel(ctx, statement_id):
    def obj_data(obj):
        settle_price = obj.settle_data()['settle_payment']

        return {
            'id': obj.id,
            'status': obj.status,
            'doctor_name': obj.servicesnapshot.doctor.name,
            'user_phone': obj.phone,
            'name': obj.servicesnapshot.name,
            'item': obj.order_multiattribute,
            'gengmei_price': obj.servicesnapshot.gengmei_price,
            'is_fenxiao': obj.servicesnapshot.service_type == SERVICE_SELL_TYPE.FENGXIANGGOU,
            'service_price': obj.service_price,
            'pre_payment_price': obj.servicesnapshot.pre_payment_price,
            'validate_time': str(obj.validate_time),
            'settle_price': settle_price,
        }

    doctor = get_doctor_from_context(ctx)
    if doctor is None:
        return gen(CODES.DOCTOR_NOT_FOUND)

    dataset = tablib.Dataset()
    dataset.headers = (u'订单号', u'美购名称', u'所属医生', u'客户手机号', u'多属性', u'是否特殊分销',
                       u'订单总价', u'预付款金额', u'应结预付款金额', u'验证时间')
    statement = Statement.objects.get(id=statement_id)
    for order in statement.orders.all():
        item = obj_data(order)
        dataset.append((
            item['id'],
            item['name'],
            item['doctor_name'],
            item['user_phone'],
            item['item'],
            item['is_fenxiao'],
            item['service_price'],
            item['pre_payment_price'],
            item['settle_price'],
            item['validate_time'],
        ))
    content = dataset.xlsx
    filename = "{}.xlsx".format(statement_id).encode('utf8')
    from gm_upload.utils.qiniu_tool import QiniuTool
    bucket_name = "gengmei-private"
    try:
        key = QiniuTool.upload(content, filename, bucket_name)['file']
    except:
        # 可能文件内容有更改,就会报错, 那么就删掉重新来一个
        QiniuTool.delete(filename, bucket_name)
        key = QiniuTool.upload(content, filename, bucket_name)['file']
    private_url = QiniuTool.get_private_url('priv.igengmei.com', key, time=300)
    return private_url
