# -*- encoding: utf-8 -*-
# -----------------------------------------------------------------------------
# @File Name  : order_service.py
# @Time       : 2020/11/18 下午3:35
# @Author     : X. Peng
# @Email      : acepengxiong@163.com
# @Software   : PyCharm
# -----------------------------------------------------------------------------
import time

from app.api.engine import tamp_pay_session, tamp_user_session
from app.config.errors import Errors
from app.controller.errorhandler import CustomFlaskErr
from app.model.account_balance import AccountBalance
from app.model.account_topup_order import AccountTopupOrder
from app.model.curriculum_order import OrderFlow
from app.model.tamp_user_models import CurriculumPrice, CurriculumColumn, CurriculumRes
from xml.etree import cElementTree as etree

from app.utils.alipay.alipayWap import prePay
from app.utils.apple_pay import apple_pay
from app.utils.wxpay.wx_app_pay import WXPay


class TopUpOrderService:
    """"""
    def __init__(self):
        pass

    def get_order(self, user_id):
        res = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.user_id == user_id).all()
        return [r.to_dict() for r in res]


    def create_order(self, args):
        args['order_no'] = time.strftime('%Y%m%d', time.localtime(time.time())) + str(int(time.time() * 100000))
        args['id'] = AccountTopupOrder.__tablename__ + str(int(time.time() * 100000))
        args['amount'] = args['amount'] * 100
        args['order_status'] = 0
        subject = '探普币充值'
        out_trade_no = args['order_no']
        notify_path = '/tamp_order/micro_shop/topUpOrderNotify'
        pay_params = None
        if args['pay_method'] == 2:
            # 微信支付
            wx_pay = WXPay(out_trade_no, subject, args['amount'], args['remote_addr'], notify_path=notify_path)
            params = wx_pay.getReturnParams()
            pay_params = params
        elif args['pay_method'] == 3:
            # 支付宝支付
            total_amount = args['amount'] / 100
            res = prePay(subject, out_trade_no, total_amount, notify_path=notify_path)
            pay_params = res
        elif args['pay_method'] == 4:
            # 苹果支付
            receipt_data = args.get('receipt_data', '')
            if not apple_pay(receipt_data):
                raise CustomFlaskErr(Errors.APPLE_VOCHER_INVALID)
            args['order_status'] = 1
            if not tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == args['user_id']).all():
                tamp_pay_session.add(AccountBalance(id=AccountBalance.__tablename__+str(int(time.time()*100000)), user_id=args['user_id'], apple_balance=args['amount']))
            else:
                tamp_pay_session.query(AccountBalance).filter(
                    AccountBalance.user_id == args['user_id']).update({
                    'apple_balance': AccountBalance.apple_balance + args['amount']
                })
        args.pop('remote_addr', '')
        args.pop('receipt_data', '')
        order_info = AccountTopupOrder(**args)
        tamp_pay_session.add(order_info)
        tamp_pay_session.commit()
        tamp_pay_session.close()
        return pay_params


class CurriculumOrderService:
    """"""
    def __init__(self):
        pass

    def get_order(self, user_id):
        """."""
        curriculum_column = tamp_user_session.query(CurriculumColumn).all()
        curriculum_res = tamp_user_session.query(CurriculumRes).all()
        res = tamp_user_session.query(OrderFlow).filter(OrderFlow.createby == user_id).all()
        curriculum_column = {r.id: r.to_dict() for r in curriculum_column}
        curriculum_res = {r.id: r.to_dict() for r in curriculum_res}
        orders = [r.to_dict() for r in res]
        for order in orders:
            prod_type = order.get('ab_si_type', '')
            prod_id = order.get('ab_proid', '')
            if prod_type == '1':
                order['prod_info'] = curriculum_column.get(prod_id, None)
            elif prod_type in ['3', '4', '5']:
                order['prod_info'] = curriculum_res.get(prod_id, None)
        return orders


    def create_order(self, args):
        """。"""
        args['ab_ordernum'] = time.strftime('%Y%m%d', time.localtime(time.time())) + str(int(time.time() * 100000))
        amount = tamp_user_session.query(CurriculumPrice.price).filter(CurriculumPrice.rel_id == args['ab_proid']).first()[0]
        args['id'] = OrderFlow.__tablename__ + str(int(time.time()*100000))
        args['ab_payment'] = amount * 100
        args['ab_status'] = 'WAIT'
        subject = args.get('prod_name', '')
        out_trade_no = args['ab_ordernum']
        notify_path = '/tamp_order/micro_shop/topUpOrderNotify'
        pay_params = None
        if args['ab_pay_mode'] == 4:
            # 探普币支付
            if args['env'] == 'ios':
                res = tamp_pay_session.query(AccountBalance.apple_balance).filter(AccountBalance.user_id == args['user_id']).first()
                if not res:
                    raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH)
                elif res[0] < args['ab_payment']:
                    raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH)
                else:
                    tamp_pay_session.query(AccountBalance.apple_balance).filter(AccountBalance.user_id == args['user_id']).update({
                        'apple_balance': AccountBalance.apple_balance - args['ab_payment']
                    })
                    args['ab_status'] = 'SUCCESS'
            elif args['env'] == 'android':
                res = tamp_pay_session.query(AccountBalance.android_balance).filter(
                    AccountBalance.user_id == args['user_id']).first()
                if not res:
                    raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH)
                elif res[0] < args['ab_payment']:
                    raise CustomFlaskErr(Errors.TANGPU_BALANCE_NOT_ENOUGH)
                else:
                    tamp_pay_session.query(AccountBalance.android_balance).filter(
                        AccountBalance.user_id == args['user_id']).update({
                        'android_balance': AccountBalance.android_balance - args['ab_payment']
                    })
                    args['ab_status'] = 'SUCCESS'
        elif args['ab_pay_mode'] == 5:
            # 微信支付
            wx_pay = WXPay(out_trade_no, subject, args['ab_payment'], args['remote_addr'], notify_path=notify_path)
            params = wx_pay.getReturnParams()
            pay_params = params
        elif args['ab_pay_mode'] == 6:
            # 支付宝支付
            total_amount = args['ab_payment'] / 100
            res = prePay(subject, out_trade_no, total_amount, notify_path=notify_path)
            pay_params = res
        args['createby'] = args.pop('user_id', '')
        args.pop('prod_name', '')
        args.pop('env', '')
        args.pop('remote_addr', '')
        order_info = OrderFlow(**args)
        tamp_user_session.add(order_info)
        tamp_user_session.commit()
        tamp_pay_session.commit()
        return pay_params


def topUpSuccessAction(order_no):
    """."""
    topup_order = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).first()
    # 幂等校验
    if topup_order.order_status == 1:
        return False
    tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).update({
        'order_status': 1
    })
    # 账户充值
    account_topup_order = tamp_pay_session.query(AccountTopupOrder).filter(AccountTopupOrder.order_no == order_no).first().to_dict()
    # 安卓支付宝,微信支付
    if not tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == account_topup_order.user_id).all():
        tamp_pay_session.add(AccountBalance(id=AccountBalance.__tablename__ + str(int(time.time()*10000)), user_id=account_topup_order.user_id, android_balance=account_topup_order.amount))
    else:
        tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == account_topup_order.user_id).update({
            'apple_balance': AccountBalance.android_balance + account_topup_order.amount
        })
    tamp_pay_session.commit()



def consumeSucessAction(order_no):
    """."""
    curriculum_order = tamp_pay_session.query(OrderFlow.ab_ordernum == order_no).all()
    # 幂等校验
    if curriculum_order.ab_status == 'SUCCESS':
        return False
    tamp_pay_session.query(OrderFlow).filter(OrderFlow.ab_ordernum == order_no).update({
        'ab_status': 'SUCCESS'
    })
    tamp_pay_session.commit()


def getAccountBalance(user_id):
    """查询探普币余额"""
    account_balance = tamp_pay_session.query(AccountBalance).filter(AccountBalance.user_id == user_id).first()
    if not account_balance:
        return {'user_id': user_id, 'android_balance': 0, 'apple_balance': 0}
    else:
        return account_balance.to_dict()


def xml2dict(content):
    """将从微信服务器接收到的xml转为dict."""
    raw = {}
    root = etree.fromstring(content)
    for child in root:
        raw[child.tag] = child.text
    return raw


def dict2xml(dict_):
    """将dict转为要发送到微信服务器的xml格式."""
    s = ""
    for k, v in dict_.items():
        s += "<{0}>{1}</{0}>".format(k, v)
    s = "<xml>{0}</xml>".format(s)
    return s.encode("utf-8")

def alipayWxPayCheck(res_info):
    """支付宝,微信支付异步通知"""
    success = False
    body = None
    header = {'Content-Type': 'application/text'}
    res = {}
    if 'trade_status' in res_info:
        # 支付宝支付
        res_info = res_info.split('&')
        for ss in res_info:
            key, value = ss.split('=')
            res[key] = value
        if res['trade_status'] == 'TRADE_SUCCESS':
            success = True
            body = 'success'.encode()
    else:
        # 微信支付
        res = xml2dict(res_info)
        if res['result_code'] == 'SUCCESS' and res['return_code'] == 'SUCCESS':
            success = True
            header = {'Content-Type': 'application/xml'}
            body = '<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>'

    return {'success': success, 'header': header, 'body': body, 'order_no': res['out_trade_no']}