<?php

namespace App\Http\Controllers\V1;

use App\Models\Job;
use App\Models\User;
use App\Models\UserBlacklistModel;
use App\Models\UserExtra;
use App\Models\UserInfoModel;
use App\Models\UserInviteLog;
use App\Models\UserLookModel;
use App\Models\UserVipLimit;
use App\Models\EmailCode;
use App\Services\Api\UserService;
use App\Services\JPushService;
use App\Services\SmsServer;
use App\Services\TencentImAccountService;
use App\Traits\TencentIm;
use Cache;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Validator;
use Laravel\Socialite\Facades\Socialite;
use PHPUnit\Util\Exception;


class AuthController extends Controller
{
    use TencentIm;
    protected $tencentImAccountService;

    public function __construct(TencentImAccountService $tencentImAccountService)
    {
        $this->tencentImAccountService = $tencentImAccountService;
    }

    //手机（注册/登录）
    public function interByMobile(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'mobile' => 'required',
                'smsCode' => 'required',
                //'verifyKey' => 'required',
            ], [
                'mobile.required' => trans('api.PLEASE_ENTER_MOBILE_PHONE_NUMBER'),
                'mobile.regex' => trans('api.MOBILE_PHONE_NUMBER_FORMAT_ERROR'),
                'smsCode.required' => trans('api.VERIFICATION_CODE_NOT_NULL'),
                //'verifyKey.required'=> trans('api.KEY_NOT_NULL'),
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->messages()->first());
            }
            //手机验证码验证
            //SmsServer::checkSmsCodeByVerifyKey($request->verifyKey, $request->smsCode);

            //如果登录类型和 openid 不为空
            $type = $request->type;
            if (isset($type) && !empty($type)) {
                if (!$user = User::where(['mobile' => $request->mobile])->whereNull('deleted_at')->first()) {
                    throw new Exception(trans('api.NOT_EXIST'));
                }
                if ($type == 'weixin') {
                    if ($user->wx_openid != '') {
                        throw new Exception(trans('api.HAD_BIND'));
                    }
                    $user->wx_openid = $request->openid;
                    $user->save();
                } elseif ($type == 'facebook') {
                    if ($user->fb_openid != '') {
                        throw new Exception(trans('api.HAD_BIND'));
                    }
                    $user->fb_openid = $request->openid;
                    $user->save();
                } elseif ($type == 'apple') {
                    if ($user->apple_openid != '') {
                        throw new Exception(trans('api.HAD_BIND'));
                    }
                    $user->apple_openid = $request->openid;
                    $user->save();
                }
            }

            $data = self::doLogin($request->mobile, 'mobile', $request->post('jpush_reg_id', null));

        } catch (\Exception $exception) {
            return $this->error($exception->getMessage());
        }

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

    //登录操作
    public function doLogin($account, $type = null, $jpush_reg_id = null)
    {
        if (!$user = self::isUserExist($account, $type)) { //新用户注册
            $user = self::addNewUser($account, $type);
            $is_have_pwd = 0;
            $is_have_email = 0;
        } else {
            //老用户登录
            $is_have_pwd = $user->password ? 1 : 0;
            $is_have_email = $user->password ? 1 : 0;
        }
        if (!$user->tencent_im_user_id) {
            $user->tencent_im_user_id = $this->tencentImAccountService->accountImport($user);
        }
        if (!empty($jpush_reg_id)) {
            //清除登陆过本设备的账号设备id
            User::query()->where('jpush_reg_id', $jpush_reg_id)->update(['jpush_reg_id' => '']);
            //当前登录用户绑定设备
            $user->jpush_reg_id = $jpush_reg_id;
            //清除别名
            JPushService::deleteAlias('user_id_' . $user->id);
            //设置极光推送别名
            JPushService::updateAlias($user->jpush_reg_id, 'user_id_' . $user->id);
        }
        if ($name = Redis::get($account)) {
            $user->name = $name;
        }
        $user->online = 1;
        $user->jpush_voice = $user->jpush_voice ?: 'chat_auto.caf';
        $user->last_login_time = date("Y-m-d H:i:s");
        $user->last_login_ip = request()->ip();
        if (!$user->save()) {
            return $this->error(trans('api.DATA_SAVE_FALSE'));
        }
        $token = Auth::guard('api')->fromUser($user);
        $user_info = UserService::getUserInfo($user->id);
        $userSig = $this->getUserSig($user->tencent_im_user_id);

        return [
            'is_have_pwd' => $is_have_pwd, //0没密码，1有密码
            'is_have_email' => $is_have_email, //0没密码，1有密码
            'user_info' => $user_info,
            'token' => "Bearer " . $token,
            'userSig' => $userSig,
        ];
    }

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

    //新增用户
    public function addNewUser($account, $type)
    {
        $user = App::make('getUserInstance');

        switch ($type) {
            case 'mobile';
                $user->mobile = $account;
                break;
            case 'email';
                $user->email = $account;
                break;
            case 'wx_openid';
                $user->wx_openid = $account;
                break;
            case 'fb_openid';
                $user->fb_openid = $account;
                break;
            case 'apple_openid';
                $user->apple_openid = $account;
                break;
        }
        //给新用户进行基本信息初始化
        $user->name = 'Euser' . mb_substr($account, 0, 6);
        $user->avatar = 'https://easygolf.oss-ap-southeast-6.aliyuncs.com/golf/2022-03/18/b92858ba88d3cee76590.png';
        $user->password = $account;
        $user->jpush_voice = 'chat_auto.caf';
        $user->register_ip = request()->ip();
        DB::beginTransaction();
        try {
            if (!$user->save() || !self::addUserExtrasRecord($user->id)) {
                return false;
            }
            DB::commit();
        } catch (Exception $exception) {
            DB::rollBack();
            return $this->error($exception->getMessage());
        }
        return User::where([$type => $account])->first();
    }

    //邮箱 (注册/登录)
    public function interByEmail(Request $request)
    {
        try {
            $params = $request->all();
            $validator = Validator::make($params, [
                'email' => 'bail|required|email',
                'code' => 'required',
            ], [
                'email.required' => trans('api.PLEASE_ENTER_EMAIL'),
                'email.email' => trans('api.MAILBOX_FORMAT_ERROR'),
                'code.required' => trans('api.VERIFICATION_CODE_NOT_NULL'),
            ]);
            if ($validator->fails()) {
                throw new Exception($validator->messages()->first());
            }
            if (!self::isEmailCodeRight($request->email, $request->code)) {
                return $this->error(trans('api.VERIFICATION_CODE_ERROR'));
            }

            //如果登录类型和 openid 不为空
            $type = $request->type;
            if (isset($type) && !empty($type)) {
                if (!$user = User::where(['email' => $request->email])->whereNull('deleted_at')->first()) {
                    throw new Exception(trans('api.NOT_EXIST'));
                }
                if ($type == 'weixin') {
                    if ($user->wx_openid != '') {
                        throw new Exception(trans('api.HAS_BIND_WEIXIN'));
                    }
                    $user->wx_openid = $request->openid;
                    $user->save();
                } elseif ($type == 'facebook') {
                    if ($user->fb_openid != '') {
                        throw new Exception(trans('api.HAS_BIND_FACEBOOK'));
                    }
                    $user->fb_openid = $request->openid;
                    $user->save();
                }
            }
            $data = $this->doLogin($request->email, 'email', $request->post('jpush_reg_id', null));
        } catch (\Exception $exception) {
            return $this->error($exception->getMessage());
        }

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

    //判断邮箱验证码
    protected function isEmailCodeRight($email, $code)
    {
        $result = EmailCode::where('channel', 'email')
            ->where('account', $email)
            ->where('code', $code)
            ->where('state', 0)
            ->orderBy('id', 'desc')
            ->first();
        if (!$result) {
            return false;
        }
        $verify = EmailCode::find($result->id);
        $verify->state = 1; //验证通过就失效
        $verify->save();

        return true;
    }

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

            if (!$user = User::where(['mobile' => $account])->orWhere(['email' => $account])->whereNull('deleted_at')->first()) {
                throw new Exception(trans('api.NOT_EXIST'));
            }
            if (!$user->password) {
                throw new Exception(trans('api.PASSWORD_NOT_SET'));
            }
            $credentials1 = ['mobile' => $account, 'password' => $password];
            $credentials2 = ['email' => $account, 'password' => $password];

            if (!auth('api')->attempt($credentials1) && !auth('api')->attempt($credentials2)) {
                throw new Exception(trans('api.ACCOUNT_OR_PASSWORD_ERROR'));
            }
            $type = strpos($account, '@') ? 'email' : 'mobile';
            $data = $this->doLogin($account, $type, $request->post('jpush_reg_id', null));
        } catch (\Exception $exception) {
            return $this->error($exception->getMessage());
        }
        return $this->success($data);
    }

    //短信验证码登录
    public function loginByCode(Request $request)
    {
        try {
            if (!$user = User::query()->where(['mobile' => $request->mobile])->whereNull('deleted_at')->first()) {
                throw new Exception(trans('api.NOT_EXIST'));
            }
            //手机验证码验证
            SmsServer::checkSmsCodeByVerifyKey($request->verifyKey, $request->smsCode);
            //如果登录类型和 openid 不为空
            $type = $request->type;
            if (isset($type) && !empty($type)) {
                if ($type == 'weixin') {
                    if ($user->wx_openid != '') {
                        throw new Exception(trans('api.HAS_BIND_WEIXIN'));
                    }
                    $user->wx_openid = $request->openid;
                    $user->save();
                } elseif ($type == 'facebook') {
                    if ($user->fb_openid != '') {
                        throw new Exception(trans('api.HAS_BIND_FACEBOOK'));
                    }
                    $user->fb_openid = $request->openid;
                    $user->save();
                }
            }
            $data = $this->doLogin($request->mobile, 'mobile', $request->post('jpush_reg_id', null));
        } catch (\Exception $exception) {
            return $this->error($exception);
        }
        return $this->success($data);
    }

    //第三方授权跳转
    public function authRedirect(Request $request)
    {
        $type = $request->get('type', 'weixin');
        return Socialite::driver($type)->redirect();
    }

    //微信授权登录
    public function authLogin(Request $request)
    {
        try {
            $github_user = Socialite::driver('weixin')->stateless()->user();
            $account = $github_user->getId();
            $data = $this->doLogin($account, 'wx_openid', $request->post('jpush_reg_id', null));
            $data['need_binding'] = 0;
        } catch (\Exception $exception) {
            Log::error('微信 登录出错~' . $exception->getMessage() . '---' . $exception->getFile() . '---' . $exception->getLine());
            //return $this->error(trans('api.NETWORK_ERROR'));
        }
        return $this->success($data);
    }

    //facebook授权登录
    public function facebookLogin(Request $request)
    {
        try {
            $token = $request->input('token');
            $result = Http::get('https://graph.facebook.com/me', ['access_token' => $token])->throw()->json();
            $data = $this->doLogin($result['id'], 'fb_openid', $request->post('jpush_reg_id', null));
            $data['need_binding'] = 0;
            Redis::setex($result['id'], 15, $result['name']); //把名字缓存
        } catch (\Exception $exception) {
            Log::error('facebook 登录出错~' . $exception->getMessage() . '---' . $exception->getFile() . '---' . $exception->getLine());
            //return $this->error(trans('api.NETWORK_ERROR'));
        }

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

    //苹果授权登录
    public function appleLogin(Request $request)
    {
        try {
            $appleOpenId = $request->apple_openid;
            $data = $this->doLogin($appleOpenId, 'apple_openid', $request->post('jpush_reg_id', null));
            $data['need_binding'] = 0;
        } catch (\Exception $exception) {
            Log::error('苹果登录出错~' . $exception->getMessage() . '---' . $exception->getFile() . '---' . $exception->getLine());
            //return $this->error(trans('api.NETWORK_ERROR'));
        }
        return $this->success($data);
    }

    //忘记密码
    public function forgetPassword(Request $request)
    {
        try {
            $account = $request->account;
            if ($request->password != $request->confirm_password) {
                throw new Exception(trans('api.TWO_PASSWORD_IS_NOT_SAME'));
            }
            if (strpos($account, '@')) { //邮箱
                if (!self::isEmailCodeRight($account, $request->code)) {
                    throw new Exception(trans('api.VERIFY_CODE_FALSE'));
                }
                $type = 'email';
            } else { //短信
                SmsServer::checkSmsCodeByVerifyKey($request->verifyKey, $request->code);
                $type = 'mobile';
            }
            $user = User::query()->where('mobile', $account)->orWhere('email', $account)->whereNull('deleted_at')->first();
            $user->password = $request->password;
            if (!$user->save()) {
                throw new Exception(trans('api.DATA_SAVE_FALSE'));
            }

            $data = $this->doLogin($account, $type, $request->post('jpush_reg_id', null));

        } catch (\Exception $exception) {
            return $this->error($exception->getMessage());
        }
        return $this->success($data);
    }

    //退出
    public function logout()
    {
        $user = auth('api')->user();

        //清空极光别名
        JPushService::updateAlias($user->jpush_reg_id, '');
        $user->online = 0;
        $user->save();

        auth('api')->logout();
        return $this->success();
    }

    //在user_extras 新增一条用户记录
    public static function addUserExtrasRecord($user_id)
    {
        $userExtras = App::make('getUserExtraInstance');
        $userExtras->user_id = $user_id;
        if (!$userExtras->save()) {
            return false;
        }
        return true;
    }
}
