<?php

namespace App\Http\Controllers\WechatPay;

use App\Http\Controllers\Core\Auth;
use App\Http\Controllers\Fpdx\PairController;
use App\Http\Controllers\Miniprogram\Auth as MiniAuth;
use App\Models\OrderModel;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class Order extends Controller
{
    private $orderModel;

    public function __construct()
    {
        $this->orderModel = new OrderModel();
    }

    // 商品信息
    public const GOODS = array(
        5 => [
            'desc' => '抽卡',
            'jsk' => 0,
            'ck' => 1,
            'total_fee' => 660,
            'gold_flower' => 0,
            'red_flower' => 0,
            'body' => '卖室友充值'
        ],
        6 => [
            'desc' => '解锁卡充值',
            'jsk' => 1,
            'ck' => 0,
            'total_fee' => 500,
            'gold_flower' => 0,
            'red_flower' => 1,
            'body' => '卖室友充值'
        ],
        7 => [
            'desc' => '解锁卡充值',
            'jsk' => 2,
            'ck' => 0,
            'total_fee' => 900,
            'gold_flower' => 0,
            'red_flower' => 2,
            'body' => '卖室友充值'
        ],
        8 => [
            'desc' => '解锁卡充值',
            'jsk' => 5,
            'ck' => 0,
            'total_fee' => 2190,
            'gold_flower' => 0,
            'red_flower' => 5,
            'body' => '卖室友充值'
        ],
        11 => [
            'desc' => '解锁卡充值',
            'jsk' => 10,
            'ck' => 0,
            'total_fee' => 3990,
            'gold_flower' => 0,
            'red_flower' => 10,
            'body' => '卖室友充值'
        ],
        1 => [
            'desc' => '金fa充值',
            'jsk' => 0,
            'ck' => 0,
            'total_fee' => 100,
            'gold_flower' => 1,
            'red_flower' => 0,
            'body' => '卖室友充值'
        ],
        9 => [
            'desc' => '购买小fa充值',
            'jsk' => 0,
            'ck' => 0,
            'total_fee' => 900,
            'gold_flower' => 10,
            'red_flower' => 0,
            'body' => '卖室友充值'
        ],
        10 => [
            'desc' => '购买小fa充值',
            'jsk' => 0,
            'ck' => 0,
            'total_fee' => 8800,
            'gold_flower' => 100,
            'red_flower' => 0,
            'body' => '卖室友充值'
        ],
    );

    /**
     * 用户解锁卡下单
     * @param  int  $goods_type
     * @return array
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function unify(int $goods_type)
    {
        $uid = Auth::auth();
        if (!in_array($goods_type, [5, 6, 7, 8, 11, 9, 10])) {
            return array(
                'code' => 101,
                'message' => '商品类型不存在'
            );
        }
        $params = array(
            'uid' => $uid,
            'body' => self::GOODS[$goods_type]['body'],
            'total_fee' => self::GOODS[$goods_type]['total_fee'],
            'notify_url' => config('api.msy_url') . "/api/core/pay/notify"
        );
        $url = config('api.pay_url') . "/payments/unify";
        $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post();
        if (isset($result->code) && $result->code == 200) {
            $order = $this->orderModel->fill([
                'create_at' => time(),
                'flower' => self::GOODS[$goods_type]['gold_flower'],
                'out_trade_no' => $result->data->order_id,
                'total_fee' => self::GOODS[$goods_type]['total_fee'],
                'uid' => $uid,
                'type' => $goods_type
            ]);
            if ($order->save()) {
                return array(
                    'code' => 200,
                    'message' => 'ok',
                    'data' => [
                        'order_id' => $order->id
                    ],
                );
            } else {
                return array(
                    'code' => 505,
                    'message' => '数据库异常'
                );
            }
        } else {
            return array(
                'code' => $result->code ?? 505,
                'message' => $result->message ?? "系统异常"
            );
        }
    }

    /**
     * 用户小fa下单
     * @param  float  $gold_flower
     * @return array
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function unifyByFlower(float $gold_flower = 1.00)
    {
        $uid = Auth::auth();
        $params = array(
            'uid' => $uid,
            'body' => self::GOODS[1]['body'],
            'total_fee' => $gold_flower * 100,
            'notify_url' => config('api.msy_url') . "/api/core/pay/notify"
        );
        $url = config('api.pay_url') . "/payments/unify";
        $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post();
        if (isset($result->code) && $result->code == 200) {
            $order = $this->orderModel->fill([
                'create_at' => time(),
                'flower' => $gold_flower,
                'out_trade_no' => $result->data->order_id,
                'total_fee' => $gold_flower * 100,
                'uid' => $uid,
                'type' => 1
            ]);
            if ($order->save()) {
                return array(
                    'code' => 200,
                    'message' => 'ok',
                    'data' => [
                        'order_id' => $order->id
                    ],
                );
            } else {
                return array(
                    'code' => 505,
                    'message' => '数据库异常'
                );
            }
        } else {
            return array(
                'code' => $result->code ?? 505,
                'message' => $result->message ?? "系统异常"
            );
        }
    }

    /**
     * 分配对象下单
     * @param  int  $total_fee  费用
     * @param  array  $attach  附加数据包
     * @return array
     * @throws \ApiException
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function unifyByFpdx(int $total_fee, array $attach)
    {
        $uid = Auth::auth();
        $params = array(
            'uid' => $uid,
            'body' => "72小时恋爱体验报名",
            'total_fee' => $total_fee,
            'notify_url' => config('api.msy_url') . "/api/core/pay/notify/fpdx"
        );
        $order = $this->orderModel->where([
            ['uid', $uid],
            ['type', 3],
            'type_id' => $attach['stage_id'],
            ['create_at', '>', time() - 600]
        ])->first();
        if (!collect($order)->isEmpty()) {
            return $order->id;
        }
        $url = config('api.pay_url') . "/payments/unify";
        $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post();
        if (isset($result->code) && $result->code == 200) {
            $order = $this->orderModel->fill([
                'create_at' => time(),
                'flower' => 0,
                'out_trade_no' => $result->data->order_id,
                'total_fee' => $total_fee,
                'uid' => $uid,
                'type' => 3,
                'type_id' => $attach['stage_id'] ?? 0,
                'attach_data' => json_encode($attach)
            ]);
            if ($order->save()) {
                return $order->id;
            } else {
                throw new \ApiException("数据库异常", 505);
            }
        } else {
            throw new \ApiException($result->message ?? "系统异常", $result->code ?? 505);
        }
    }

    /**
     * 表白下单
     * @param  int  $total_fee  表白费用
     * @param  int  $confess_id  表白记录id
     * @return mixed
     * @throws \ApiException
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function unifyByConfess(int $total_fee, int $confess_id)
    {
        $uid = Auth::auth();
        $params = array(
            'uid' => $uid,
            'body' => '卖室友表白',
            'total_fee' => $total_fee,
            'notify_url' => config('api.msy_url') . "/api/core/pay/notify/confess"
        );
        $url = config('api.pay_url') . "/payments/unify";
        $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->withData($params)->asJsonResponse()->post();
        if (isset($result->code) && $result->code == 200) {
            $order = $this->orderModel->fill([
                'create_at' => time(),
                'flower' => 0,
                'out_trade_no' => $result->data->order_id,
                'total_fee' => $total_fee,
                'uid' => $uid,
                'type' => 2,
                'type_id' => $confess_id
            ]);
            if ($order->save()) {
                return $order->id;
            } else {
                throw new \ApiException("数据库异常", 505);
            }
        } else {
            throw new \ApiException($result->message ?? "系统异常", $result->code ?? 505);
        }
    }

    /**
     * 小程序支付jssdk
     * @param  int  $order_id
     * @return array
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function miniProgram(int $order_id)
    {
        $uid = MiniAuth::auth();
        $order = $this->orderModel->find($order_id);
        if (collect($order)->isEmpty()) {
            return array(
                'code' => 101,
                'message' => '订单号错误'
            );
        }
        if ($order->trade_state != 0) {
            return array(
                'code' => 102,
                'message' => '订单失效' . json_encode($order->toArray())
            );
        }
        if ($uid != $order->uid) {
            return array(
                'code' => 103,
                'message' => '用户标识不一致'
            );
        }
        $public_id = config('miniprogram.public_id');
        $url = config('api.pay_url') . "/payments/miniProgram/{$order->out_trade_no}";
        $result = \Curl::to($url)->withHeader("app:{$public_id}")->asJsonResponse()->get();
        if (isset($result->code) && $result->code == 200) {
            return array(
                'code' => 200,
                'message' => 'ok',
                'data' => $result->data,
            );
        } else {
            return array(
                'code' => $result->code ?? 505,
                'message' => $result->message ?? "系统异常"
            );
        }
    }

    /**
     * 公众号支付jssdk
     * @param  int  $order_id
     * @return array
     * @throws \Tymon\JWTAuth\Exceptions\JWTException
     */
    public function jssdk(int $order_id)
    {
        $uid = Auth::auth();
        $order = $this->orderModel->find($order_id);
        if (collect($order)->isEmpty()) {
            return array(
                'code' => 101,
                'message' => '订单号错误'
            );
        }
        if ($order->trade_state != 0) {
            return array(
                'code' => 102,
                'message' => '订单失效'
            );
        }
        if ($uid != $order->uid) {
            return array(
                'code' => 103,
                'message' => '用户标识不一致'
            );
        }
        $url = config('api.pay_url') . "/payments/jssdk/{$order->out_trade_no}";
        $result = \Curl::to($url)->asJsonResponse()->get();
        if (isset($result->code) && $result->code == 200) {
            return array(
                'code' => 200,
                'message' => 'ok',
                'data' => $result->data,
            );
        } else {
            return array(
                'code' => $result->code ?? 505,
                'message' => $result->message ?? "系统异常"
            );
        }
    }

    /**
     * 订单退款
     * @param  int  $order_id
     * @param  int  $refund_fee  退款金额:分
     * @param  string  $refund_desc
     * @param  bool  $all
     * @return array|bool
     * @throws \ApiException
     */
    public function refund(int $order_id, int $refund_fee, $refund_desc = "", $all = false)
    {
        $order = $this->orderModel->find($order_id);
        if (collect($order)->isEmpty()) {
            throw new \ApiException('订单号错误', 101);
        }
        if (0 == $order->order_state) {
            throw new \ApiException('订单失效', 102);
        }
        if ($all && $order->create_at < 1533114000) {
            throw new \ApiException("过期订单,请联系小向导微信:fpdxkf", 103);
            $url = config('api.pay_url') . "/payments/transfer";
            $data = array(
                'uid' => $order->uid,
                'amount' => $refund_fee,
                'app_order_id' => "fpdx_refund_" . uniqid(),
                'desc' => $refund_desc
            );
        } else {
            $url = config('api.pay_url') . "/payments/order/{$order->out_trade_no}/refund";
            $data = array(
                'refund_fee' => $refund_fee,
                'refund_desc' => $refund_desc
            );
        }
        $result = \Curl::to($url)->withContentType("application/x-www-form-urlencoded")->asJsonResponse()->withData($data)->post();
        if (isset($result->code) && $result->code == 200) {
            return true;
        } else {
            throw new \ApiException($result->message, $result->code);
        }
    }

    /**
     * 支付结果核销处理
     * @param  Request  $request
     * @param  array  $callback
     * @return string
     */
    private function handlePaidNotify(Request $request, array $callback)
    {
        $orderModel = new OrderModel();
        $order = $orderModel->where('out_trade_no', $request->input('order_id'))->first();
        if (collect($order)->isEmpty()) {
            return "fail";
        }
        if ($order->order_state != 0) {
            return "success";
        } else {
            $order->cash_fee = $request->input('cash_fee');
            if ($request->input('trade_state') == 'SUCCESS') {
                $order->order_state = 1;
            }
            if ($order->save()) {
                call_user_func($callback, $order);
                return "success";
            } else {
                return "fail";
            }
        }
    }

    /**
     * 普通支付成功业务处理
     * @param  OrderModel  $order
     * @return bool
     * @throws \Exception
     */
    protected function payment(OrderModel $order)
    {
        \DB::beginTransaction();
        try {
            // 增加抽卡次数
            \DB::table('kdgx_partner_charge_user')->where('uid', $order->uid)->increment(
                'ck_count',
                self::GOODS[$order->type]['ck']
            );
            // 增加解锁卡
            $ticketController = new Ticket();
            for ($i = 0; $i < self::GOODS[$order->type]['jsk']; $i++) {
                $ticketController->create(5, $order->uid);
            }
            // 增加花
            \DB::table('kdgx_partner_charge_user')->where('uid', $order->uid)->increment(
                'red_flower',
                self::GOODS[$order->type]['red_flower']
            );
            \DB::table('kdgx_partner_charge_user')->where('uid', $order->uid)->increment('gold_flower', $order->flower);
            // 日志
            \DB::table('kdgx_partner_charge_pay_logs')->insert([
                'uid' => $order->uid,
                'create_at' => time(),
                'type' => 3,
                'gold_flower' => $order->flower,
                'red_flower' => self::GOODS[$order->type]['red_flower'],
                'jsk' => self::GOODS[$order->type]['jsk'],
                'type_id' => $order->total_fee,
                'remark' => "微信充值 {$order->total_fee}"
            ]);
            \DB::commit();
            return true;
        } catch (\Exception $e) {
            \DB::rollBack();
            return false;
        }
    }

    /**
     * 普通支付结果通知
     * @param  Request  $request
     * @return string
     * @throws \Exception
     */
    public function notify(Request $request)
    {
        return $this->handlePaidNotify($request, [$this, 'payment']);
    }

    /**
     * 表白支付结果通知
     * @param  Request  $request
     * @return string
     */
    public function notifyByconfess(Request $request)
    {
        $confess = new Confess();
        return $this->handlePaidNotify($request, [$confess, 'payment']);
    }

    /**
     * 分配对象报名支付结果通知
     * @param  Request  $request
     * @return string
     */
    public function notifyByfpdx(Request $request)
    {
        $pairObj = new PairController();
        return $this->handlePaidNotify($request, [$pairObj, 'payment']);
    }

    public function requestRefund(int $order_id)
    {
        $order = $this->orderModel->find($order_id);
        $this->refund($order_id, $order->cash_fee, '测试退款');
    }
}
