<?php
namespace App\Services;

use App\Contracts\AuthServiceInterface;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Requests\Auth\RegisterUserRequest;
use App\Models\User;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Auth\Events\Registered;
use Illuminate\Validation\ValidationException;


class AuthService implements AuthServiceInterface
{

  public function authenticate(LoginRequest $request): User
  {
    $request->authenticate();
    $user = $request->user();
    return $user;
  }

  public function logout(Request $request)
  {
    $request->user()->currentAccessToken()->delete();
  }

  public function checkIfVerified(Request $request): bool
  {
    return $request->user()->hasVerifiedEmail();
  }

  public function sendVerificationEmail(Request $request)
  {
    $request->sendVerificationEmail($request);
  }

  public function resetPassword(Request $request)
  {
    // Here we will attempt to reset the user's password. If it is successful we
    // will update the password on an actual user model and persist it to the
    // database. Otherwise we will parse the error and return the response.
    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function ($user) use ($request) {
            $user->forceFill([
                'password' => Hash::make($request->string('password')),
                'remember_token' => Str::random(60),
            ])->save();

            event(new PasswordReset($user));
        }
    );

    if ($status != Password::PASSWORD_RESET) {
        throw ValidationException::withMessages([
            'email' => [__($status)],
        ]);
    }

    return $status;
  }

  public function resetPasswordLink(Request $request)
  {
    // We will send the password reset link to this user. Once we have attempted
    // to send the link, we will examine the response then see the message we
    // need to show to the user. Finally, we'll send out a proper response.
    $status = Password::sendResetLink(
        $request->only('email')
    );

    if ($status != Password::RESET_LINK_SENT) {
        throw ValidationException::withMessages([
            'email' => [__($status)],
        ]);
    }

    return $status;
  }

  // User Registration
  public function registerUser(RegisterUserRequest $request): User
  {
    $user =  $this->createUser($request);
    $this->sendRegisteredEvent($user);
    return $user;
  }

  private function createUser(RegisterUserRequest $request): User
  {
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->string('password')),
    ]);
    return $user;
  }

  private function sendRegisteredEvent(User $user)
  {
    event(new Registered($user));
  }

  public function createStringAuthToken(User $user): string
  {
    return $user->createToken('auth-token' . $user->email)->plainTextToken;
  }

  // ['pending', 'active', 'rejected', 'blocked']
  public function approveUser(User $user):bool
  {
    try{
      $user->status = 'active';
      $user->save();
      return true;
    }catch (Exception $e){
      return false;
    }
  }

  public function rejectUser(User $user): bool
  {
    try{
      $user->status = 'rejected';
      $user->save();
      return true;
    }catch (Exception $e){
      return false;
    }  
  }

  public function blockUser(User $user): bool
  {
    try{
      $user->status = 'blocked';
      $user->save();
      return true;
    }catch (Exception $e){
      return false;
    }  
  }

}