<?php

namespace App\Models;

use App\Command\Log;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\DB;
use App\Models\Good as GoodModel;
use App\Models\GoodSku;

class Pay
{

    private static function getConfig()
    {
        return   $config = [
            // 必要配置
            'app_id'             => env('WX_XCX_APPID'),
            'mch_id'             => env('WX_XCX_MCH_ID'),
            'key'                => env('WX_XCX_MCH_KEY'),   // API v2 密钥 (注意: 是v2密钥 是v2密钥 是v2密钥)

            // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'          => public_path() . '/cert/apiclient_cert.pem', // XXX: 绝对路径!!!!
            'key_path'           => public_path() . '/cert/apiclient_key.pem',      // XXX: 绝对路径!!!!

            'notify_url'         => '/',     // 你也可以在下单时单独设置来想覆盖它
        ];
    }


    public static function pay($body, $order_sn, $order_price, $openid)
    {
        $orderPrice = intval(strval($order_price * 100));
        $app = Factory::payment(self::getConfig());
        $jssdk = $app->jssdk;
        $result = $app->order->unify([
            'body' => $body,
            'out_trade_no' => $order_sn,
            //            'total_fee' => $order_price*100,
            'total_fee' => $orderPrice,
            //            'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
            //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
            'openid' => $openid,
            'notify_url' => env('API_URL') . '/pay-notify',
        ]);
        Log::add('订单支付_', $result);
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            $prepayId = $result['prepay_id'];
            $config = $jssdk->sdkConfig($prepayId);
            return $config;
        }
        if ($result['return_code'] == 'FAIL' && array_key_exists('return_msg', $result)) {
            throw new \Exception($result['return_msg']);
        }
        throw new \Exception($result['err_code_des']);
    }

    public static  function payNotify($fields = [])
    {
        $app =  Factory::payment(self::getConfig());
        $response = $app->handlePaidNotify(function ($message, $fail) {
            Log::add('--支付回调--', $message);
            $orderObj = OrderInfo::where(['order_sn' => $message['out_trade_no']])->first();
            if (!$orderObj) {
                $fail('订单不存在');
            }
            //支付完成后的业务逻辑[result_code] => SUCCESS
            if ($orderObj->pay_status == 1) {
                return true;
            }
            if ($message['result_code'] == "SUCCESS") {
                DB::beginTransaction();
                try {
                    //更新订单
                    if ($orderObj->pay_status == 0) {
                        $orderObj->order_status = 1;
                        $orderObj->pay_status = 1;
                        if ($orderObj->save()) {
                            //更新商品销量、库存
                            $goodsList = OrderGoods::where("order_id", $orderObj->id)->get();
                            foreach ($goodsList as $item) {
                                //Log::add('--订单商品对象--', $item);
                                $gid = $item->goods_id;
                                $attr_id = $item->attr_id;
                                $mer_id = $item->merchant_id;
                                $goods_number = $item->goods_number;
                                //更新此商品支付状态
                                $item->is_pay = 1;
                                $item->save();

                                $goodsObj = GoodModel::find($gid);
                                //更新商品规格库存
                                $attrObj = GoodSku::find($attr_id);
                                $attr_stock = ($attrObj->stock - $goods_number) >= 0 ? $attrObj->stock - $goods_number : 0;
                                $attrObj->stock = $attr_stock;
                                $attrObj->save();
                                //更新商品sku
                                $skuArr = json_decode($goodsObj->sku, true);
                                if ($skuArr['sku']) {
                                    foreach ($skuArr['sku'] as $kk => $vv) {
                                        if (isset($vv['attr_sn']) && $vv['attr_sn'] == $attrObj->attr_sn) {
                                            $skuArr['sku'][$kk]['stock'] = $attr_stock;
                                        }
                                    }
                                    $goodsObj->sku = json_encode($skuArr, JSON_UNESCAPED_UNICODE);
                                    $goodsObj->save();
                                }
                                //商户规格库存
                                $mgsObj = MerchantGoodSku::where(['goods_id' => $gid, 'attr_id' => $attr_id, 'merchant_id' => $mer_id])->first();
                                if ($mer_id && $mgsObj) {
                                    $changeStock = ($mgsObj->stock >= $goods_number) ? $mgsObj->stock - $goods_number : 0;
                                    $mgsObj->stock = $changeStock;
                                    $mgsObj->save();
                                }
                            }
                        }
                    }
                    //支付记录
                    $pay_cord = new PaymentRecord();
                    $cordLog = $pay_cord->where(['order_sn' => $message['out_trade_no']])->first();
                    if (!$cordLog) {
                        $total_fee = $message['total_fee'];
                        $pay_money = round($total_fee / 100, 2);
                        $pay_cord->order_sn = $message['out_trade_no'];
                        $pay_cord->other_order = $message['transaction_id'];
                        $pay_cord->money = $pay_money;
                        $pay_cord->uid = $orderObj->user_id;
                        $pay_cord->save();
                    }
                    DB::commit();
                    //return  true;
                } catch (\Exception $e) {
                    Log::add('付款回调失败', $e);
                    DB::rollBack();
                    return false;
                }
            }
            return  true;
        });
        //Log::add('响应结果', $response);
        //Log::add('响应结果内容', $response->getContent());
        $response->send();
        return $response;
    }


    public static function refund($wxOrder_no, $orderPrice, $refundPrice)
    {
        $app =  Factory::payment(self::getConfig());
        $refund_no = date('YmdHis') . rand(100000, 999999);
        $orderPrice = intval(strval($orderPrice * 100));
        $refundPrice = intval(strval($refundPrice * 100));
        $result = $app->refund->byTransactionId($wxOrder_no, $refund_no, $orderPrice, $refundPrice, [
            // 可在此处传入其他参数,详细参数见微信支付文档
            'refund_desc' => '订单退款',
            'notify_url' => env('API_URL') . '/refund-notify',
        ]);
        //            echo '<pre>';
        //            print_r($result);
        Log::add('订单退款', $result);

        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            //退款成功的操作
            return $result;
        }
        if ($result['return_code'] == 'FAIL' && array_key_exists('return_msg', $result)) {
            throw new \Exception($result['return_msg']);
        }
        throw new \Exception($result['err_code_des']);
    }

    public static function refundNotify($fields)
    {
        $app =  Factory::payment(self::getConfig());
        $response = $app->handleRefundedNotify(function ($message, $fail) use ($fields) {
            return  true;
        });
        return $response;
    }


    //提现
    public static function toBalance($openid, $amount, $desc)
    {
        $out_batch_no = 'tx' . date('Ymd') . mt_rand(1000, 9999);
        $partner_trade_no = date('YmdHis') . rand(1000, 9999);
        $pay_v3 = new PayV3();

        $res = $pay_v3->transfer($out_batch_no, $partner_trade_no, $amount, $openid, $desc);
        Log::add('提现微信返回值', $res);
        if (isset($res['batch_id'])) {
            return [$partner_trade_no, $out_batch_no, $res['batch_id'], $res['batch_status']];
        }

        throw new \Exception('提现失败');
    }
}