<?php

namespace App\Http\Controllers\Xchengxu\Oauth;

use App\Modules\User\Services\UserService;
use App\Modules\Xcx\Services\XcxSendOrderService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Modules\User\Models\User;
use App\Modules\User\Models\Xcxuser;
use Log;
use JWTAuth;
use GuzzleHttp\Client;

class UsersController extends Controller
{


    /**
     * @apiDefine Login 登录
     */


    /**
     * @apiVersion 1.0.0
     * @apiDescription 登录
     * @api {post} login 登录
     * @apiParam  {String}  js_code js_code
     * @apiParam  {Int}     distribution_channel_id distribution_channel_id
     * @apiParam  {String}  sign    签名
     * @apiGroup Login
     * @apiName index
     * @apiSuccess {int}         code 状态码
     * @apiSuccess {String}      msg  信息
     * @apiSuccess {object}      data 结果集
     * @apiSuccess {String}      data.token token
     * @apiSuccess {Int}         data.time 过期时间
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *       code: 0,
     *       msg: "",
     *       data:  {
     *            token:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
     *            time:123455
     *           }
     *       }
     */
    public function index(Request $request)
    {
        Log::info($request->all());
        //$distribution_channel_id = $request->input('distribution_channel_id', '');
        //海报推广的参数
        $scene = $request->input('scene', '');
        $js_code = $request->input('js_code');
        $sign = $request->input('sign');
        $encryptedData = $request->input('encryptedData');
        $iv = $request->input('iv');
        //参数推广的参数
        $channel_key = $request->input('channel_key',0);
        $sign = 1;
        if (empty($js_code)  || empty($sign)) {
            return response()->error('PARAM_ERROR');
        }
        $distribution_channel_id = 14;
        $uid = 0;
        $u = 0;
        //解析海报推广的参数
        if($scene){
            $scene_arr = explode('_',$scene);
            $distribution_channel_id = (int)$scene_arr[0];
            $uid = $scene_arr[1];
            $u = $scene_arr[2];
        }
        //解析参数推广的参数
        if($channel_key){
            $channel_key =(int)$channel_key;
            $channel_info = XcxSendOrderService::getChannelIdBySendOrderId($channel_key);
            if($channel_info){
                $distribution_channel_id = $channel_info->distribution_channel_id;
                $u = $channel_key;
            }
        }
        if ($sign !== _sign(compact('openid', 'distribution_channel_id', 'unionid'), 'Uv%vkPI5K8Opqoww')) {
            //return response()->error('PARAM_ERROR');
        }
        $login_info = $this->getUserWeixinInfo($js_code);
        $appid = 'wxa0c8331eba3b34d5';
        $status = $this->decryptData($appid,$login_info['session_key'],$encryptedData,$iv,$user_info);

        if($status != ErrorCode::$OK){
            return response()->error('PARAM_ERROR');
        }

        if (!$user_info) response()->error('PARAM_ERROR');
        $user_info = json_decode($user_info,1);
        if (!isset($user_info['openId']) || !isset($user_info['unionId'])) {
            return response()->error('PARAM_ERROR');
        }
        $openid = $user_info['openId'];
        $unionid = $user_info['unionId'];
        $user = $this->createUser(compact('openid', 'distribution_channel_id', 'unionid','uid','u'),$user_info);
        if ($user) {
            $uid = $user->id;
            $time = time() + 7200;
            $token = JWTAuth::fromUser($user);
            return response()->success(compact('token', 'time','uid'));
        } else {
            return response()->error('PARAM_ERROR');
        }
    }

    /**
     * 授权用户信息
     * @param $data
     * @return bool
     */
    protected function createUser($data,$user_info)
    {
        //compact('openid', 'distribution_channel_id', 'unionid','uid','u')
        //用户已经是小程序用户了
        $xcx_user = Xcxuser::where('unionid',$data['unionid'])
            ->where('distribution_channel_id',$data['distribution_channel_id'])
            ->select('uid')
            ->first();
        if($xcx_user){
            return User::find($xcx_user->uid);
        }
        $info = [];
        if(isset($user_info['city']) && !empty($user_info['city'])) {$info['city'] = $user_info['city'];}
        if(isset($user_info['province']) && !empty($user_info['province'])){ $info['province'] = $user_info['province'];}
        if(isset($user_info['country']) && !empty($user_info['country'])){ $info['country'] = $user_info['country'];}
        if(isset($user_info['gender']) && !empty($user_info['gender'])) {$info['sex'] = $user_info['gender'];}
        if(isset($user_info['nickName']) && !empty($user_info['nickName'])) {$info['nickname'] = $user_info['nickName'];}
        if(isset($user_info['avatarUrl']) && !empty($user_info['avatarUrl'])) {$info['head_img'] = $user_info['avatarUrl'];}
        //从推广进来的一般会有uid
        if($data['uid']){
            Xcxuser::create([
                'uid'=>$data['uid'],
                'openid'=>$data['openid'],
                'unionid'=>$data['unionid'],
                'distribution_channel_id'=>$data['distribution_channel_id'],
                'u'=>$data['u']
            ]);

            if($info){
                UserService::updateInfo($data['uid'],$info);
            }
            return User::find($data['uid']);
        }else{
            //直接进入的
            $info['openid'] =$data['openid'];
            $info['unionid'] =$data['openid'];
            $info['distribution_channel_id'] =$data['distribution_channel_id'];
            $info['send_order_id'] =$data['u'];
            $user =  User::addUser($info);

            Xcxuser::create([
                'uid'=>$user->id,
                'openid'=>$data['openid'],
                'unionid'=>$data['unionid'],
                'distribution_channel_id'=>$user->distribution_channel_id,
                'u'=>$data['u']
            ]);
            return $user;
        }
    }

    /**
     * @apiVersion 1.0.0
     * @apiDescription 刷新token
     * @api {get} RefreshToken 刷新token
     * @apiParam {String}  [token]  token
     * @apiHeader {String} [Authorization]  token 两个token任选其一
     * @apiGroup Login
     * @apiName RefreshToken
     * @apiSuccess {int}         code 状态码
     * @apiSuccess {String}      msg  信息
     * @apiSuccess {object}      data 结果集
     * @apiSuccess {String}      data.token token
     * @apiSuccess {Int}         data.time 过期时间
     * @apiSuccessExample {json} Success-Response:
     *     HTTP/1.1 200 OK
     *     {
     *       code: 0,
     *       msg: "",
     *       data:  {
     *            token:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
     *            time:123455
     *           }
     *       }
     */
    public function RefreshToken()
    {
        try{
            $old_token = JWTAuth::getToken();
            $token = JWTAuth::refresh($old_token);
            $time = time() + 7200;
            return response()->success(compact('token', 'time'));
        }catch (\Exception $e){

        }
        return response()->error('XCX_NOT_LOGIN');
    }


    private function getUserWeixinInfo($js_code)
    {
        if (empty($js_code)) {
            return false;
        }
        $url = 'https://api.weixin.qq.com/sns/jscode2session?';
        $client = new Client([
            'timeout' => 2.0,
        ]);
        $appid = 'wxa0c8331eba3b34d5';
        $secret = '17c01c26dd7873e557710601436774c7';
        $grant_type = 'authorization_code';
        try {
            $res = $client->get($url . http_build_query(compact('js_code', 'appid', 'secret', 'grant_type')))->getBody()->getContents();
            Log::info('code 换取 session_key is :');
            Log::info($res);
            $res = json_decode($res, true);
            if (isset($res['errcode'])) {
                return false;
            }
            return $res;
        } catch (\Exception $e) {
            Log::info($e);
            return false;
        }
    }


    /**
     * 检验数据的真实性，并且获取解密后的明文.
     * @param $encryptedData string 加密的用户数据
     * @param $iv string 与用户数据一同返回的初始向量
     * @param $data string 解密后的原文
     *
     * @return int 成功0，失败返回对应的错误码
     */
    private function decryptData($appid, $sessionKey,$encryptedData, $iv, &$data )
    {
        if (strlen($sessionKey) != 24) {
            return ErrorCode::$IllegalAesKey;
        }
        $aesKey=base64_decode($sessionKey);


        if (strlen($iv) != 24) {
            return ErrorCode::$IllegalIv;
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj=json_decode( $result );
        if( $dataObj  == NULL )
        {
            return ErrorCode::$IllegalBuffer;
        }
        if( $dataObj->watermark->appid !=$appid )
        {
            return ErrorCode::$IllegalBuffer;
        }
        $data = $result;
        return ErrorCode::$OK;
    }



}
class ErrorCode
{
    public static $OK = 0;
    public static $IllegalAesKey = -41001;
    public static $IllegalIv = -41002;
    public static $IllegalBuffer = -41003;
    public static $DecodeBase64Error = -41004;
}