<?php
/**
 * sqc @小T科技 2018.06.07
 *
 *
 */
namespace App\Logic;

use App\Models\ShopGoods;
use App\Models\ShopOrder;
use Illuminate\Support\Facades\DB;
use EasyWeChat\Factory;
use Carbon\Carbon;
use function EasyWeChat\Kernel\Support\generate_sign;

class Buy
{

    /**
     * 会员信息id
     * @var string
     */
    private $_user_id = '';

    /**
     * 下单数据
     * @var array
     */
    private $_order_data = array();

    /**
     * 下单地区数据
     * @var array
     */
    private $_address_data = array();

    /**
     * 表单数据
     * @var array
     */
    private $_post_data = array();

    public function __construct()
    {
    }


    /**
     * 执行购买
     * @param int $user_id // 购买者
     * @param array $buydata // 购买的商品
     * @param array $address //收货地址
     * @param object $request // 表单数据
     * @return array
     */
    public function buyStep($request, $buy_info, $address, $user_id)
    {
        $this->_user_id = $user_id;
        $this->_order_data = $buy_info;
        $this->_post_data = $request;
        $this->_address_data = $address;
        try {
            DB::beginTransaction();
            //第1步 执行下单
            $order_info = $this->_createOrderStep1();
            return $order_info;
        } catch (\Exception $e) {
            DB::rollBack();
            return ['error' => $e->getMessage()];
        }

    }


    /**
     * 生成订单
     * @param array $input
     * @throws Exception
     * @return array array(支付单sn,订单列表)
     */
    private function _createOrderStep1()
    {
        $paycode = $this->makePaySn($this->_user_id);
        //订单数据
        $order_insert = array();
        $order_insert['order_sn'] = $this->makeOrderSn($paycode); // 订单编号
        $order_insert['uid'] = $this->_user_id;
        $order_insert['pay_name'] = '微信支付';// 目前只有微信支付
        $order_insert['pay_id'] = 1;// 目前只有微信支付
        $order_insert['order_status'] = ShopOrder::STATUS_WAIT_PAY;// 待支付
        $order_insert['shipping_status'] = ShopOrder::SHIPING_STATUS_WAIT_SEND;// 待发货
        $order_insert['pay_status'] = ShopOrder::PAY_WAIT;// 待支付下单
        $order_insert['actual_price'] = $this->_order_data['actualPrice'];// 订单实际要支付的金额
        $order_insert['order_price'] = $this->_order_data['orderTotalPrice'];// 订单总价
        $order_insert['goods_price'] = $this->_order_data['goodsTotalPrice'];// 商品总价
        $order_insert['freight_price'] = $this->_order_data['freightPrice'];// 配送费用
        $order_insert['coupon_id'] = $this->_order_data['checkedCouponId'];// 使用的优惠券id
        $order_insert['coupon_price'] = $this->_order_data['couponPrice'];// 优惠金额
        $order_insert['add_time'] = Carbon::now();// 订单生成时间

        // 收货地址
        $order_insert['country'] = $this->_address_data['country_id'];// 国家id 1 中国
        $order_insert['province'] = $this->_address_data['province_id'];// 省市id
        $order_insert['city'] = $this->_address_data['city_id'];// 城市id
        $order_insert['district'] = $this->_address_data['district_id'];// 区县、街道id
        $order_insert['address'] = $this->_address_data['address'];// 详细地址
        $order_insert['consignee'] = $this->_address_data['user_name'];// 收件人
        $order_insert['mobile'] = $this->_address_data['mobile'];// 收件人手机号

        //用户留言
        $order_insert['postscript'] = empty($this->_post_data->remark) ? '用户无留言' : $this->_post_data->remark;

        $order_goods_insert = array(); // 订单附表的数据

        // 执行插入
        $order_model = ShopOrder::create($order_insert);
        if (!$order_model->id) {
            throw new \Exception('订单保存失败[未生成支付单]');
        }
        foreach ($this->_order_data['checkedGoodsList'] as $k => $va) {
            if ($va['number']) {
                $order_goods_insert[] = [
                    'order_id' => $order_model->id,
                    'goods_id' => $va['goods_id'],
                    'goods_name' => $va['goods_name'],
                    'retail_price' => $va['retail_price'],
                    'market_price' => $va['market_price'],
                    'list_pic_url' => $va['list_pic_url'] ? $va['list_pic_url'] : '',
                    'number' => $va['number'],
                ];
                $re1 = $this->addSaleNum($va['goods_id'], $va['number']);
                if (!$re1) {
                    throw new \Exception('订单保存失败[商品库存不足]');
                }
            }
        }
        $order_goods_model = DB::table('shop_order_goods')->insert($order_goods_insert);
        // 清除购物车商品
        $cartRe = CartLogic::clearCart($this->_user_id);
        if ($order_goods_model) {
            DB::commit();
            return $order_model->toArray();
        } else {
            $this->pay_log('order_goods_insert.error' . var_export($order_goods_insert, true));
            throw new \Exception('订单商品保存失败');
        }
    }

    public function addSaleNum($id, $num = 1)
    {
        $goods = ShopGoods::lockForUpdate()->find($id);
        if (empty($goods) || $goods->goods_number < $num) {
            return false;
        }
        $goods->sell_volume = $goods->sell_volume + $num;
        $goods->goods_number = $goods->goods_number - $num;
        return $goods->save();
    }

    /**
     * 生成支付单编号(两位随机 + 从2000-01-01 00:00:00 到现在的秒数+微秒+会员ID%1000)，该值会传给第三方支付接口
     * 长度 =2位 + 10位 + 3位 + 3位  = 18位
     * 1000个会员同一微秒提订单，重复机率为1/100
     * @return string
     */
    public function makePaySn($member_id)
    {
        return mt_rand(10, 99)
        . sprintf('%010d', time() - 946656000)
        . sprintf('%03d', (float)microtime() * 1000)
        . sprintf('%03d', (int)$member_id % 1000);
    }

    /**
     * 订单编号生成规则
     * 生成订单编号(年取1位 + $pay_id取13位 + 第N个子订单取2位)
     * 1000个会员同一微秒提订单，重复机率为1/100
     * @param $pay_sn
     * @return string
     */
    public function makeOrderSn($pay_sn)
    {
        //记录生成子订单的个数，如果生成多个子订单，该值会累加
        static $num;
        if (empty($num)) {
            $num = 1;
        } else {
            $num++;
        }
        return (date('y', time()) % 9 + 1) . sprintf('%013d', $pay_sn) . sprintf('%02d', $num);
    }


    // 支付第一步
    public function pay_step1($attributes, $openid)
    {
        $time = time();
        $app = Factory::payment(config('wechat.payment.default'));
        $result = $app->order->unify([
            'body' => '小T商城',
            'detail' => '小T商城的订单',
            'out_trade_no' => $attributes['order_sn'],
            'total_fee' => $attributes['actual_price'] * 100,
            'trade_type' => 'JSAPI',
            'openid' => $openid,
        ]);
        $this->pay_log('order:' . var_export($attributes, true) . '  result:' . var_export($result, true));
        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            // 如果成功生成统一下单的订单，那么进行二次签名 二次签名的参数必须与下面相同
            $params = [
                'appId' => config('wechat.payment.default.app_id'),
                'timeStamp' => time(),
                'nonceStr' => $result['nonce_str'],
                'package' => 'prepay_id=' . $result['prepay_id'],
                'signType' => 'MD5',
            ];
            $params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
            return $params;
        } else {
            // 返回错误信息
            $this->pay_log('json_prepare' . var_export($result, true));
            return false;
        }
    }

    /**
     * 记录日志
     */
    private function pay_log($msg)
    {
        $msg = date('H:i:s') . "|" . $msg . "\r\n";
        $msg .= '| GET:' . var_export($_GET, true) . "\r\n";
        file_put_contents('./log/pay' . date('Y-m-d') . ".log", $msg, FILE_APPEND);
    }


}
