<?php

namespace App\Http\Controllers\Api;

use App\Http\Requests\UserRegister;
use App\Http\Services\UserService;
use App\Mail\SendCode;
use App\Models\UserModel;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Validator;

class AuthApiController extends Controller
{

    use RegistersUsers;

    public function register(UserRegister $request)
    {
        $email = $request->input('email');
        if (UserModel::where('email', $email)->exists()) {
            return $this->setError('Email has been taken');
        }

        //判断邮箱验证码
        $redisKey = 'sem_email_code_register_' . $email;
        $cachedEmailCode = Redis::get($redisKey);
        if ($cachedEmailCode != $request->input('email_code')) {
            return $this->setError('Email code invalid');
        }
        $userId = UserService::createUser($request->all());
        Redis::del($redisKey);
        \Auth::loginUsingId($userId);
        return $this->setSuccess('Register success');
    }


    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|string|email|max:255',
            'password' => 'required|string|min:8|max:50',
        ], [
            'password.min' => 'Password must be at least 8 characters long.'
        ]);

        if ($validator->fails()) {
            return $this->setError($validator->errors()->first());
        }

        $userExists = UserModel::where('email', $request->email)->exists();
        if (!$userExists) {
            return $this->setError('User dose not exist');
        }

        if ($this->attemptLogin($request)) {
            $request->session()->regenerate();
            $cookie = Cookie::make('sem_email', Auth::user()->email, config('session.lifetime'));
            Cookie::queue($cookie);
            $userIdCookie = Cookie::make('sem_user_id', Auth::user()->id, config('session.lifetime'), null, null, false,
                false);
            Cookie::queue($userIdCookie);
            return $this->setSuccess('Login success');
        }


        return $this->setError('The account or password is incorrect');
    }

    public function logout(Request $request)
    {
        $cookie = Cookie::forget('sem_email');
        Cookie::queue($cookie);
        Auth::logout();
        return $this->setSuccess('Logout success');
    }

    public function resetPassword(Request $request)
    {

        $validator = Validator::make($request->all(), [
            'old_password' => 'required|min:8|max:50',
            'password' => ['required', 'string', 'min:8', 'max:50', 'confirmed'],
        ], [
            'old_password.min' => 'Password must be at least 8 characters long.',
            'password.min' => 'Password must be at least 8 characters long.',
            'password.confirmed' => 'Passwords do not match!',
        ]);

        if ($validator->fails()) {
            return $this->setError($validator->errors()->first());
        }
        $password = $request->get('password');
        $oldPassword = $request->get('old_password');
        $userId = Auth::user()->id;
        $hashedPassword = UserModel::where('id', $userId)->value('password');
        if (!Hash::check($oldPassword, $hashedPassword)) {
            return $this->setError('Wrong Password!');
        }

        if (Hash::check($password, $hashedPassword)) {
            return $this->setError('The new password cannot be the same as the old password!');
        }

        $user = UserModel::find($userId);
        $user->password = Hash::make($password);
        $user->update_time = time();
        $result = $user->save();
        if (!$result) {
            return $this->setError('Reset password failed');
        }

        return $this->setSuccess('Reset password success');
    }

    public function forgetPassword(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'email_code' => 'required'
        ], []);
        if ($validator->fails()) {
            return $this->setError($validator->errors()->first());
        }
        $email = $request->input('email');
        $emailCode = $request->input('email_code');
        $redisKey = 'sem_email_code_forget_password' . '_' . $email;
        $cachedEmailCode = Redis::get($redisKey);
        if ($cachedEmailCode != $emailCode) {
            return $this->setError('Email code invalid');
        }
        return $this->setSuccess('Verify email code success');
    }

    //忘记密码以后的设置密码
    public function setForgetPassword(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'password' => ['required', 'string', 'min:8', 'max:50', 'confirmed'],
            'email_code' => 'required',
            'email' => 'required|email'
        ], []);
        $password = $request->input('password');
        $emailCode = $request->input('email_code');
        $email = $request->input('email');
        if ($validator->fails()) {
            return $this->setError($validator->errors()->first());
        }
        $redisKey = 'sem_email_code_forget_password' . '_' . $email;
        $cachedEmailCode = Redis::get($redisKey);
        if (!$cachedEmailCode) {
            return $this->setError('Email code expired');
        }
        if ($cachedEmailCode != $emailCode) {
            return $this->setError('Email code invalid');
        }

        $hashedPassword = UserModel::where('email', $email)->value('password');
        if (Hash::check($password, $hashedPassword)) {
            return $this->setError('The new password cannot be the same as the old password!');
        }

        $user = UserModel::where('email', $email)->first();
        $user->password = Hash::make($password);
        $user->update_time = time();
        $result = $user->save();
        if (!$result) {
            return $this->setError('Reset password failed');
        }
        Redis::del($redisKey);
        Auth::logout();
        return $this->setSuccess('Reset password success');
    }

    //发送邮箱验证码
    public function sendEmailCode(Request $request)
    {
        $email = $request->input('email');
        $type = $request->input('type', 'register');

        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
        ]);
        if ($validator->fails()) {
            return $this->setError($validator->errors()->first());
        }
        $info = UserModel::where('email', $email)->first();
        $msg = '';
        switch ($type) {
            case 'register':
                if ($info) {
                    return $this->setError('This email had been registered');
                }
                $msg = 'You are registering an account with us.';
                break;
            case 'forget_password' :
                $msg = 'You are trying to reset your password.';
                $existEmail = UserModel::where('email', $email)->exists();
                if (!$existEmail) {
                    return $this->setError('This email is not registered');
                }
                break;
            case 'update_email':
                $existEmail = UserModel::where('email', $email)->exists();
                if (!$existEmail) {
                    return $this->setError('This email is not registered');
                }
                $msg = 'You are modifying your email address.';
                break;
        }


        //发送验证码
        $code = mt_rand(1000, 9999);
        $redisKey = 'sem_email_code_' . $type . '_' . $email;
        if (Redis::get($redisKey)) {
            return $this->setError('A verification code has been sent. Please enter the code below to continue.' . (config('app.debug') ? Redis::get($redisKey) : ''));
        }
        Redis::set($redisKey, $code);
        Redis::expire($redisKey, 120);
        // return $this->setSuccessData($code);
        Mail::to($email)->send(new SendCode($code, $msg));
        //错误处理
        if (count(Mail::failures())) {
            return $this->setError('Email code send failed');
        }

        return $this->setSuccess('A verification code has been sent. Please enter the code below to continue. ' . (config('app.debug') ? $code : ''));
    }

}