<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Tests\Feature\Concerns\BuildsFeatureData;
use Tests\TestCase;

class PasswordFeatureTest extends TestCase
{
    use BuildsFeatureData;
    use DatabaseTransactions;

    public function test_forgot_password_form_can_be_opened(): void
    {
        $this->get(route('password.forgot.form'))->assertOk();
    }

    public function test_send_reset_link_with_unknown_email_shows_generic_success_message(): void
    {
        $response = $this->from(route('password.forgot.form'))
            ->post(route('password.forgot'), [
                'email' => 'unknown@example.com',
            ]);

        $response->assertRedirect(route('password.forgot.form'));
        $response->assertSessionHas('success');
    }

    public function test_send_reset_link_for_registered_email_creates_reset_token(): void
    {
        Mail::fake();

        $applicant = $this->createApplicant([
            'email' => 'reset.known@example.com',
        ]);

        $response = $this->from(route('password.forgot.form'))
            ->post(route('password.forgot'), [
                'email' => $applicant->email,
            ]);

        $response->assertRedirect(route('password.forgot.form'));
        $response->assertSessionHas('success');
        $this->assertDatabaseHas('applicant_password_resets', [
            'email' => $applicant->email,
        ]);
    }

    public function test_reset_form_without_required_query_redirects_to_login(): void
    {
        $this->get(route('password.reset'))->assertRedirect(route('login'));
    }

    public function test_reset_form_with_token_and_email_is_accessible(): void
    {
        $this->get(route('password.reset', [
            'token' => 'token123',
            'email' => 'user@example.com',
        ]))->assertOk();
    }

    public function test_reset_password_with_valid_token_updates_password(): void
    {
        $applicant = $this->createApplicant([
            'email' => 'token.valid@example.com',
            'password' => 'oldpassword',
        ]);

        $plainToken = 'valid-reset-token';

        DB::table('applicant_password_resets')->insert([
            'email' => $applicant->email,
            'token' => Hash::make($plainToken),
            'created_at' => now(),
        ]);

        $response = $this->post(route('password.reset.submit'), [
            'email' => $applicant->email,
            'token' => $plainToken,
            'password' => 'newpassword123',
            'password_confirmation' => 'newpassword123',
        ]);

        $response->assertRedirect(route('login'));

        $applicant->refresh();
        $this->assertTrue(Hash::check('newpassword123', $applicant->password));
        $this->assertDatabaseMissing('applicant_password_resets', [
            'email' => $applicant->email,
        ]);
    }

    public function test_change_password_requires_login(): void
    {
        $response = $this->post(route('password.change'), [
            'current_password' => 'anything',
            'password' => 'newpassword123',
            'password_confirmation' => 'newpassword123',
        ]);

        $response->assertRedirect(route('login'));
    }

    public function test_logged_in_applicant_can_change_password(): void
    {
        $applicant = $this->createApplicant([
            'password' => 'oldpassword123',
        ]);

        $response = $this->withSession([
            'applicant_id' => $applicant->id,
        ])->post(route('password.change'), [
            'current_password' => 'oldpassword123',
            'password' => 'newpassword123',
            'password_confirmation' => 'newpassword123',
        ]);

        $response->assertRedirect(route('dashboard'));

        $applicant->refresh();
        $this->assertTrue(Hash::check('newpassword123', $applicant->password));
    }
}
