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

import xmltodict
from django.conf import settings
from django.db import transaction
from django.http import JsonResponse
from django.shortcuts import HttpResponse
from logit import logit
from TimeConvert import TimeConvert as tc
from wechatpy import WeChatPay, WeChatPayException

from account.models import LensmanIncomeExpensesInfo, LensmanInfo, UserIncomeExpensesInfo, UserInfo
from group.models import GroupPhotoInfo, GroupPhotoOrderInfo
from pay.models import OrderInfo
from photo.models import PhotosInfo
from utils.error.errno_utils import GroupPhotoStatusCode, OrderStatusCode
from utils.error.response_utils import response
from utils.page_utils import pagination
from utils.redis.rkeys import LENSMAN_PHOTO_PRICE
from utils.redis.rorder import set_lensman_order_record


r = settings.REDIS_CACHE
WECHAT = settings.WECHAT


@logit
@transaction.atomic
def wx_order_create_api(request):
    """
    订单创建
    :param request:
    :return:
    """
    group_id = request.POST.get('group_id', '')
    user_id = request.POST.get('user_id', '')
    photo_id = request.POST.get('photo_id', '')
    photo_type = request.POST.get('photo_type', 'nomark')  # nomark for 去除水印, origin for 获取高清图

    # 群组照片校验
    try:
        group_photo = GroupPhotoInfo.objects.get(pk=photo_id)
    except GroupPhotoInfo.DoesNotExist:
        return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND)

    body = request.POST.get('body', '')  # 商品描述
    total_fee = int(request.POST.get('total_fee', 0))  # 总金额，单位分

    # 金额校验
    # if int(r.get(LENSMAN_PHOTO_PRICE % (user_id, photo_id, photo_type)) or 0) != total_fee:
    #     return response(OrderStatusCode.FEE_CHECK_FAIL)

    # 获取 from_uid, to_lid, to_uid
    from_uid = user_id
    to_lid = group_photo.lensman_id
    to_uid = '' if group_photo.lensman_id else group_photo.user_id

    # JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付，统一下单接口trade_type的传参可参考这里
    trade_type = request.POST.get('trade_type', '')

    # 根据 trade_type 获取 wechat 配置
    wechat = WECHAT.get(trade_type, {})
    # WeChatPay 初始化
    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))

    # 生成订单
    order = OrderInfo.objects.create(
        group_id=group_id,
        photo_id=photo_id,
        lensman_photo_id=group_photo.lensman_photo_id,
        photo_type=1 if photo_type == 'origin' else 0,
        from_uid=from_uid,
        to_lid=to_lid,
        to_uid=to_uid,
        total_fee=total_fee,
        trade_type=trade_type,
    )

    try:
        prepay_data = wxpay.order.create(
            body=body,
            notify_url=settings.API_DOMAIN + '/wx/notify_url',
            out_trade_no=order.order_id,
            total_fee=total_fee,
            trade_type=trade_type,
            # user_id=None,  # 可选，用户在商户appid下的唯一标识。trade_type=JSAPI，此参数必传
        )
    except WeChatPayException:
        return response(OrderStatusCode.WX_UNIFIED_ORDER_FAIL)

    prepay_id = prepay_data.get('prepay_id', '')
    if trade_type == 'JSAPI':
        wxpay_params = wxpay.jsapi.get_jsapi_params(prepay_id)
    elif trade_type == 'APP':
        wxpay_params = wxpay.order.get_appapi_params(prepay_id)

    return JsonResponse({
        'status': 200,
        'message': 'Order Create Success',
        'description': u'订单创建成功',
        'data': {
            'order_id': order.order_id,
            'prepay_id': prepay_id,
            'wxpay_params': wxpay_params,
        }
    })


def order_paid_success(order):
    if order.pay_status == OrderInfo.PAID:
        return

    order.pay_status = OrderInfo.PAID
    order.paid_at = tc.utc_datetime()
    order.save()

    porder, created = GroupPhotoOrderInfo.objects.get_or_create(
        group_id=order.group_id,
        user_id=order.from_uid,
        photo_id=order.photo_id,
    )
    photo = PhotosInfo.objects.get(
        photo_id=order.lensman_photo_id,
    )
    if order.photo_type == OrderInfo.NOMARK:
        porder.m_photo_path = photo.m_photo_path
    elif order.photo_type == OrderInfo.ORIGIN:
        porder.r_photo_path = photo.r_photo_path
    porder.save()

    set_lensman_order_record(porder)

    if order.to_lid:
        try:
            lensman = LensmanInfo.objects.select_for_update().filter(lensman_id=order.to_lid)[0]
        except IndexError:
            return

        lensman.balance += order.total_fee
        lensman.save()

        LensmanIncomeExpensesInfo.objects.create(
            lensman_id=order.to_lid,
            photo_id=order.photo_id,
            type=LensmanIncomeExpensesInfo.INCOME,
            amount=order.total_fee,
            balance=lensman.balance,
            remark=u'图片购买',
        )
    elif order.to_uid:
        try:
            user = UserInfo.objects.select_for_update().filter(user_id=order.to_uid)[0]
        except IndexError:
            return

        user.balance += order.total_fee
        user.save()

        UserIncomeExpensesInfo.objects.create(
            user_id=order.user_id,
            photo_id=order.photo_id,
            type=UserIncomeExpensesInfo.INCOME,
            amount=order.total_fee,
            balance=user.balance,
            remark=u'图片购买',
        )


def order_paid_fail(order):
    if order.pay_status == OrderInfo.FAIL:
        return

    order.pay_status = OrderInfo.FAIL
    order.save()


@logit
@transaction.atomic
def wx_order_query_api(request):
    """
    订单查询
    :param request:
    :return:
    """
    order_id = request.POST.get('order_id', '')
    transaction_id = request.POST.get('transaction_id', '')

    try:
        order = OrderInfo.objects.get(order_id=order_id)
    except OrderInfo.DoesNotExist:
        return response(OrderStatusCode.WX_ORDER_NOT_FOUND)

    if order.pay_status == OrderInfo.PAID:
        return JsonResponse({
            'status': 200,
            'message': 'Order Pay Success',
            'description': u'订单支付成功',
            'data': {

            }
        })
    elif order.pay_status == OrderInfo.FAIL:
        return response(OrderStatusCode.WX_ORDER_PAY_FAIL)

    # 根据 trade_type 获取 wechat 配置
    wechat = WECHAT.get(order.trade_type, {})
    # WeChatPay 初始化
    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))

    # 订单查询
    query_data = wxpay.order.query(transaction_id, order_id)
    # 签名校验
    if not wxpay.check_signature(query_data):
        return response(OrderStatusCode.SIGN_CHECK_FAIL)

    # 交易状态
    trade_state = query_data.get('trade_state')
    # 订单状态判断更新
    if trade_state == 'SUCCESS':  # 订单支付成功
        order_paid_success(order)
        return JsonResponse({
            'status': 200,
            'message': 'Order Pay Success',
            'description': u'订单支付成功',
            'data': {

            }
        })
    elif trade_state == 'NOTPAY':  # 订单未支付
        return response(OrderStatusCode.WX_ORDER_NOT_PAY)
    elif trade_state == 'USERPAYING':  # 订单支付中
        return response(OrderStatusCode.WX_ORDER_PAYING)
    else:  # 订单支付失败
        order_paid_fail(order)
        return response(OrderStatusCode.WX_ORDER_PAY_FAIL)


@logit
@transaction.atomic
def wx_order_list_api(request):
    """
    订单列表
    :param request:
    :return:
    """
    user_id = request.POST.get('user_id', '')
    page = int(request.POST.get('page', 1))
    num = int(request.POST.get('num', settings.ORDER_NUM_PER_PAGE))

    orders = OrderInfo.objects.filter(from_uid=user_id, pay_status=OrderInfo.PAID, status=True).order_by('-pk')
    orders, left = pagination(orders, page, num)
    orders = [order.data(user_id) for order in orders]

    return JsonResponse({
        'status': 200,
        'message': u'获取订单列表成功',
        'data': {
            'orders': orders,
            'left': left,
        },
    })


@logit
@transaction.atomic
def wx_order_detail_api(request):
    """
    订单详情
    :param request:
    :return:
    """
    user_id = request.POST.get('user_id', '')
    order_id = request.POST.get('order_id', '')

    try:
        order = OrderInfo.objects.get(order_id=order_id)
    except OrderInfo.DoesNotExist:
        return response(OrderStatusCode.WX_ORDER_NOT_FOUND)

    if user_id not in [order.from_uid, order.to_lid, order.to_uid]:
        return response(OrderStatusCode.NO_DETAIL_PERMISSION)

    return JsonResponse({
        'status': 200,
        'message': u'获取订单详情成功',
        'data': {
            'order': order.data(user_id),
        },
    })


@logit
@transaction.atomic
def wx_notify_url_api(request):
    """
    支付异步通知回调地址
    :param request:
    :return:
    """
    try:
        data = xmltodict.parse(request.body)['xml']
    except xmltodict.ParsingInterrupted:
        # 解析 XML 失败
        return HttpResponse(settings.WXPAY_NOTIFY_FAIL)

    trade_type = data.get('trade_type', '')

    # 根据 trade_type 获取 wechat 配置
    wechat = WECHAT.get(trade_type, {})
    # WeChatPay 初始化
    wxpay = WeChatPay(wechat.get('appID'), wechat.get('apiKey'), wechat.get('mchID'))

    # 签名校验
    if not wxpay.check_signature(data):
        return response(OrderStatusCode.SIGN_CHECK_FAIL)

    out_trade_no = data.get('out_trade_no', '')
    return_code = data.get('return_code', '')
    result_code = data.get('result_code', '')

    if return_code != 'SUCCESS' or result_code != 'SUCCESS':
        return HttpResponse(settings.WXPAY_NOTIFY_FAIL)

    try:
        order = OrderInfo.objects.get(order_id=out_trade_no)
    except OrderInfo.DoesNotExist:
        return response(OrderStatusCode.WX_ORDER_NOT_FOUND)

    order_paid_success(order)

    return HttpResponse(settings.WXPAY_NOTIFY_SUCCESS)
