<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\SmsException;
use App\Models\AdminRole;
use App\Models\User;
use App\Services\SmsService;
use App\Services\TencentImAccountService;
use App\Transformers\UserTransformer;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;


class AuthorizationsController extends Controller
{
    protected $tencentImAccountService;

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

    /**
     * 手机号登录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     */
    public function loginByMobile(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'mobile' => ['required', 'regex:/^1[3456789]\d{9}$/'],
            'verifyKey' => 'bail|required|string',
            'smsCode' => 'bail|required',
        ], [
            'mobile.required'=>"手机号码必须",
            'mobile.regex'=>"手机号码格式错误",
            'verifyKey.required'=>"验证码必须",
            'smsCode.required'=>"短信验证码必须",
        ]);
        if ($validator->fails()) {
            return $this->response()->errorForbidden($validator->messages()->first());
        }

        try {
            //验证短信验证码
            SmsService::checkSmsCodeByVerifyKey($request->verifyKey, $request->smsCode);
        } catch (SmsException $e) {
            abort(403, $e->getMessage());
        } catch (\Exception $e) {
            abort(403, '短信校验失败');
        }

        $user = User::firstOrCreate([
            'mobile' => $request->input('mobile'),
        ]);

        if (!$user->ycode) {
            $user->ycode = $this->createCode();
        }

        if (!$user->tencent_im_user_id) {
            $user->tencent_im_user_id = $this->tencentImAccountService->accountImport($user);
        }
        $user->save();
        $token = Auth::guard('api')->fromUser($user);
        self::updateLastLogin($user, $token);

        $resdata['token'] = $token;
        $resdata['sex'] = $user->sex;
        return response()->json($resdata)->setStatusCode(201);
    }

    /**
     * 根据用户ID生成唯一邀请码
     * @param $user_id
     * @return string
     */
   public function createCode() {
       $code =  create_invite_code();
       if(User::where(['ycode'=>$code])->first()){
           $code =  create_invite_code();
       }
        return $code;
    }

    /**
     * 用户账号密码登录
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|void
     */
    public function loginByAccountPassword(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'mobile' => ['required', 'regex:/^1[3456789]\d{9}$/'],
            'password' => 'required|string',
        ],[
            'mobile.required'=>"手机号码必须",
            'mobile.regex'=>"手机号码格式错误",
            'password.required'=>"密码必须",
        ]);
        if ($validator->fails()) {
            return $this->response()->errorForbidden($validator->messages()->first());
        }
        if (!$user=User::where(['mobile' => $request->mobile])->first()) {
            return $this->response->errorNotFound('用户不存在!');
        }
        $credentials = $request->only('mobile', 'password');

        if (!$token = auth('api')->attempt($credentials)) {
            return $this->response->errorUnauthorized ('用户名或密码错误');
        }

        if (!$user->ycode) {
            $user->ycode = $this->createCode();
        }

        if (!$user->tencent_im_user_id) {
            $user->tencent_im_user_id = $this->tencentImAccountService->accountImport($user);
        }
        $user->save();
        self::updateLastLogin($user, $token);

        $resdata['token'] = $token;
        $resdata['sex'] = $user->sex;
        return response()->json($resdata)->setStatusCode(201);
    }

    /**
     * 注册账号
     */
    public function register(Request $request){
        $validator = Validator::make($request->all(), [
            'mobile' => ['required', 'regex:/^1[3456789]\d{9}$/'],
            'password' => 'bail|required',
        ],[
            'mobile.required'=>"手机号码必须",
            'mobile.regex'=>"手机号码格式错误",
            'password.required'=>"密码必须",
        ]);
        if ($validator->fails()){
            return $this->response()->errorForbidden($validator->messages()->first());
        }
        if(User::where(['mobile'=>$request->mobile])->first()){
            return $this->response->errorForbidden("该手机号码已使用");
        }

        $ins = array();

        $ins['mobile'] = $request->mobile;
        $ins['password'] = $request->password;
        if(User::create($ins)){
            return response()->json(['message'=>"注册成功"])->setStatusCode(201);
        }else{
            return $this->response->errorForbidden("注册失败");
        }
    }



    /**
     * 忘记密码
     */
    public function forgetPassword(Request $request){
        $validator = Validator::make($request->all(), [
            'mobile' => ['required', 'regex:/^1[3456789]\d{9}$/'],
            'verifyKey' => 'bail|required|string',
            'smsCode' => 'bail|required',
            'password' => 'bail|required',
        ],[
            'mobile.required'=>"手机号码必须",
            'mobile.regex'=>"手机号码格式错误",
            'verifyKey.required'=>"验证码必须",
            'smsCode.required'=>"短信验证码必须",
            'password.required'=>"密码必须",
        ]);
        if ($validator->fails()) {
            return $this->response()->errorForbidden($validator->messages()->first());
        }
        try {
            //验证短信验证码
            SmsService::checkSmsCodeByVerifyKey($request->verifyKey, $request->smsCode);
        } catch (SmsException $e) {
            abort(403, $e->getMessage());
        } catch (\Exception $e) {
            abort(403, '短信校验失败');
        }

        $user = User::where(['mobile'=>$request->mobile])->first();
        $user->password =$request->password;// Hash::make($request->password);
        if($user->save()){
            return $this->response->noContent()->setStatusCode(201);
        }
    }

    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        $user = auth('api')->user();
        return $this->response->item($user, new UserTransformer());
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth('api')->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }

    /**
     * Refresh a token.
     * 刷新token，如果开启黑名单，以前的token便会失效。
     * 值得注意的是用上面的getToken再获取一次Token并不算做刷新，两次获得的Token是并行的，即两个都可用。
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(Auth::guard('api')->refresh());
    }

    static public function updateLastLogin(User $user, string $jwtToken)
    {
        $user->remember_token = $jwtToken;
        $user->last_login_time = Carbon::now();
        $user->last_login_ip = request()->ip();
        $user->save();
    }

    /**
     * Get the token array structure.
     *
     * @param string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'Bearer',
            'expires_in' => Auth::guard('api')->factory()->getTTL() * 60
        ]);
    }
}
