<?php

namespace Tests\Feature\Controllers\Auth;

use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;

class ForgotPasswordTest extends TestCase
{
    use RefreshDatabase;

    protected function passwordRequestRoute()
    {
        return route('password.request');
    }

    protected function passwordEmailGetRoute()
    {
        return route('password.email');
    }

    protected function passwordEmailPostRoute()
    {
        return route('password.email');
    }

    /** @test */
    public function user_can_view_forgot_password()
    {
        $response = $this->get($this->passwordRequestRoute());

        $response->assertSuccessful();
        $response->assertViewIs('auth.passwords.email');
    }

    /** @test */
    public function user_receives_an_email_with_a_password_resetLink()
    {
        Notification::fake();
        $user = User::factory()->create([
            'email' => 'john@example.com',
        ]);

        $response = $this->post($this->passwordEmailPostRoute(), [
            'email' => 'john@example.com',
        ]);

        $this->assertNotNull($token = DB::table('password_resets')->first());
        Notification::assertSentTo(
            $user,
            ResetPassword::class,
            function ($notification, $channels) use ($token) {
                return Hash::check($notification->token, $token->token) === true;
            }
        );
    }

    /** @test */
    public function user_does_not_receive_email_when_not_registered()
    {
        Notification::fake();
        $response = $this->from($this->passwordEmailGetRoute())
            ->post($this->passwordEmailPostRoute(), [
                'email' => 'nobody@example.com',
            ]);

        $response->assertRedirect($this->passwordEmailGetRoute());
        $response->assertSessionHasErrors('email');
        Notification::assertNotSentTo(
            User::factory()->make(['email' => 'nobody@example.com']),
            ResetPassword::class
        );
    }

    /** @test */
    public function email_is_required()
    {
        $response = $this->from($this->passwordEmailGetRoute())
            ->post($this->passwordEmailPostRoute(), []);

        $response->assertRedirect($this->passwordEmailGetRoute());
        $response->assertSessionHasErrors('email');
    }

    /** @test */
    public function email_is_a_valid_email()
    {
        $response = $this->from($this->passwordEmailGetRoute())
            ->post($this->passwordEmailPostRoute(), [
                'email' => 'invalid-email',
            ]);

        $response->assertRedirect($this->passwordEmailGetRoute());
        $response->assertSessionHasErrors('email');
    }
}
