<?php

namespace App\Http\Controllers\V1;

use App\libs\helpers\Response;
use App\libs\wechat\auth\WeChat;
use App\Models\Config;
use App\Models\Share;
use App\Models\User;
use App\Services\Api\ErrorMsgServive;
use App\Services\Api\UserService;
use App\Services\JPushService;
use App\Services\SmsServer;
use EasyWeChat\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
use PHPUnit\Util\Exception;

class AuthController extends Controller
{
    public function __construct()
    {
        $this->wxConfig = [
            'app_id'        => env('WECHAT_MINI_PROGRAM_APPID'),
            'secret'        => env('WECHAT_MINI_PROGRAM_SECRET'),
            'response_type' => 'array',
        ];
    }

    // 注册
    public function register(Request $request)
    {
        $mobile   = $request->input('mobile', '');
        $password = $request->input('password', '');

        $validator = \Validator::make($request->all(), [
            'mobile'   => 'required',
            'password' => 'required|min:6',
        ]);
        if ($validator->fails()) {
            return $this->error($validator->errors()->first());
        }
        if (UserService::checkUserByMobile($mobile)) {
            return $this->error('手机号已被占用');
        }

        try { // 手机验证码验证
            SmsServer::checkSmsCodeByVerifyKey($request->verifyKey, $request->code);
        } catch (Exception $exception) {
            return $this->error($exception->getMessage());
        }

        $user              = App::make('getUserInstance'); // 在 app/Providers/AppServiceProvider.php 里面可以创一个单例模式
        $user->name        = 'User' . mb_substr($mobile, 0, 6);
        $user->avatar      = '';
        $user->mobile      = $mobile;
        $user->password    = $password; // 这个不是直接存密码，User模型中使用了修改器
        $user->register_ip = request()->ip();

        return $this->success('创建成功！');
    }

    // 账号密码登录
    public function login(Request $request)
    {
        $account      = $request->input('account');
        $password     = $request->input('password');
        $jpush_reg_id = $request->input('jpush_reg_id');

        if (!$user = User::query()->where(['mobile' => $account])->orWhere(['email' => $account])->first()) {
            return $this->error('账号不存在');
        }
        $credentials1 = ['mobile' => $account, 'password' => $password];
        $credentials2 = ['email' => $account, 'password' => $password];
        if (!auth('api')->attempt($credentials1) && !auth('api')->attempt($credentials2)) {
            return $this->error('密码错误！');
        }
        $data = $this->doLogin($user, $jpush_reg_id);

        return $this->success($data);
    }

    // APP第三方授权登录(微信)
    public function authLogin(Request $request)
    {
        try {
            $socialite = Socialite::driver('weixin')->stateless()->user();
            $user      = User::query()->where('open_id', $socialite->getId())->first();
            if (!$user) {
                $data['open_id'] = $socialite->getId();
                $data['user']    = [];
            } else {
                $account = $user->mobile ?: $user->email;
                $data    = $this->doLogin($account, $request->post('jpush_reg_id', ''));
            }
        } catch (Exception $exception) {
            ErrorMsgServive::write($exception, requst()->url());

            return $this->error('微信授权登录出错~');
        }

        return $this->success($data);
    }

    // 微信小程序登录(微信)
    public function miniProgram(Request $request)
    {
        try {
            $helpId  = $request->input('helpId', 0);
            $info = WeChat::mini()->code2Openid($request->input('code'));
            $openId        = $info['openid'];
            // $openId        = 'ocU_x5RN8huhJSIVtn9X3TQ8Zq4s1';
            $user          = User::query()->where('open_id', $openId)->first();
            if (!$user) {
                $data['open_id'] = $openId;
                $data['user']    = [];
                $user            = User::query()->create([
                    'open_id'         => $openId,
                    'online'          => 1,
                    'last_login_time' => date('Y-m-d H:i:s'),
                    'last_login_ip'   => request()->ip(),
                    'sessionKey'      => $info['session_key'] ?? '',
                    'share_pid'       => $helpId,
                    'share_date'      => date('Y-m-d H:i:s'),
                ]);
                $user = User::query()->find($user->id);
                if ($helpId > 0  && $helpId != $user->id) {
                    $helpUserData = User::query()->find($helpId);
                    if (!$helpUserData->is_share) {
                        $this->diamond($helpId, $user->id);
                    }
                }
            } else {
                $user->online          = 1;
                $user->last_login_time = date('Y-m-d H:i:s');
                $user->last_login_ip   = request()->ip();
                $user->sessionKey   = $info['session_key'] ?? '';
                if (!$user->save()) {
                    return $this->error('数据保存失败');
                }
            }
            $token    = Auth::guard('api')->fromUser($user);
            $userInfo = UserService::getUserInfoById($user->id);
            $data     = [
                'token'     => 'Bearer ' . $token,
                'user_info' => $userInfo,
            ];

            return Response::success($data);
        } catch (Exception $exception) {
            ErrorMsgServive::write($exception, requst()->url());

            return $this->error('微信授权登录出错~');
        }

        return $this->success($data);
    }

    private function extend($helpId = 0)
    {
    }

    /**
     * 通过邀请获得钻石.
     *
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    private function diamond($helpId = 0, $pid = 0)
    {
        (int) $diamond = Config::query()->where('key', 'help_diamond')->value('value');
        $invite = User::query()->where('share_pid',$helpId)->count();
        if ($invite == $diamond){
            $share         = Share::query()->create([
                'user_id' => $helpId,
                'pid'     => $pid,
                'diamond' => $diamond,
                'desc'      => '通过邀请'.$diamondCount.'人获得'.$diamond.'次数'
            ]);
            User::query()->where('id', $helpId)->increment('diamond', $diamond);
        }
        return $share ?? [];
    }

    // 微信小程序获取手机号
    public function decryptPhone(Request $request)
    {
        $user = auth('api')->user();

        try {
            $mini    = Factory::miniProgram($this->wxConfig);
            $newMini = $mini->auth->session($request->input('code'));

            $iv            = $request->input('iv');
            $encryptData   = $request->input('encryptData');
            $decryptedData = $mini->encryptor->decryptData($newMini['session_key'], $iv, $encryptData);

            $user         = User::query()->where('id', $user->id)->first();
            $user->mobile = $decryptedData['purePhoneNumber'];
            $user->save();
        } catch (\Exception $exception) {
            ErrorMsgServive::write($exception, requst()->url());

            return $this->error('获取手机号出错~');
        }

        return $this->success();
    }

    // H5 应用进行微信授权登录
    public function h5Oauth()
    {
    }

    // 微信小程序 code
    public function miniCode()
    {
    }

    public function wechat(Request $request): JsonResponse
    {
        try {
            $code = $request->input('code');

            $app = $this->getUniFactory(3)->mini();
            $res = $app->auth->session($code);

            return $this->doLogin($res['openid'], '', 3, $res['session_key']);
        } catch (\Exception $e) {
            ErrorMsgServive::write($e, \request()->url());

            return $this->error('微信授权登陆出错');
        }
    }

    // 字节跳动登陆 code
    public function bytedance(Request $request): JsonResponse
    {
        try {
            $code = $request->input('code');
            $app  = $this->getUniFactory();
            $res  = $app->login($code);

            return $this->doLogin($res['openid'], $res['unionid'], 1, $res['session_key']);
        } catch (\Exception $e) {
            ErrorMsgServive::write($e, \request()->url());

            return $this->error('字节授权登陆出错');
        }
    }

    // 快手登陆 code
    public function kuaishou(Request $request): JsonResponse
    {
        try {
            $code = $request->input('code');
            $app  = $this->getUniFactory(2);
            $res  = $app->login($code);

            return $this->doLogin($res['open_id'], '', 2, $res['session_key']);
        } catch (\Exception $e) {
            ErrorMsgServive::write($e, \request()->url());

            return $this->error('快手授权登陆出错');
        }
    }

    /**
     * 执行登录.
     *
     * @return JsonResponse
     */
    private function doLogin($openid, $sessionKey)
    {
        $user = User::where('open_id', $openid)->first();
        if (!$user) {
            $user             = new User();
            $user->open_id    = $openid;
            $user->sessionKey = $sessionKey;
            $user->save();
            $user = User::where('id', $user->id)->first();
        } else {
            $user->sessionKey      = $sessionKey;
            $user->last_login_ip   = \request()->ip();
            $user->last_login_time = time();
            $user->save();
        }
        $token = Auth::guard('api')->fromUser($user);
        $user  = User::query()->where('id', $user->id)->first();

        return $this->success([
            'token'     => 'Bearer ' . $token,
            'user_info' => $user,
        ]);
    }

    // 执行登录
    public function doLogin1($user, $jpush_reg_id = null)
    {
        $user->online          = 1;
        $user->last_login_time = date('Y-m-d H:i:s');
        $user->last_login_ip   = request()->ip();
        if (!$user->save()) {
            return $this->error('数据保存失败');
        }
        $token    = Auth::guard('api')->fromUser($user);
        $userInfo = UserService::getUserInfoById($user->id);
        $data     = [
            'token'     => 'Bearer ' . $token,
            'user_info' => $userInfo,
        ];

        return $data;
    }

    // 用户是否存在
    public function isUserExist($account)
    {
        $user = User::where(['mobile' => $account])
            ->orWhere(['email' => $account])
            ->first();
        if (!$user) {
            return false;
        }

        return $user;
    }

    // 忘记密码
    public function forgetPassword(Request $request)
    {
        if ($request->new_password != $request->confirm_password) {
            return $this->error('两次密码不一致');
        }

        try {
            SmsServer::checkSmsCodeByVerifyKey($request->verifyKey, $request->code);
        } catch (Exception $exception) {
            return $this->error($exception->getMessage());
        }
        $user->password = $request->new_password;
        $user->save();

        return $this->success();
    }

    // 退出
    public function logout()
    {
        $user = auth('api')->user();
        // 清空极光别名
        JPushService::updateAlias($user->jpush_reg_id, '');
        $user->online = 0;
        $user->save();
        auth('api')->logout();

        return $this->success();
    }
}
