<?php

namespace Tests\Feature\Auth;

use App\Domains\Auth\Models\ResetPasswordAttempt;
use App\Domains\Auth\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ValidateResetPasswordAttemptControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_it_validates_a_pending_four_digit_code(): void
    {
        $user = User::factory()->create(['email' => 'ada@example.com']);
        $attempt = $user->resetPasswordAttempts()->create([
            'codigo' => '0123',
        ]);

        $this->postJson('/api/password/reset-attempts/validate', [
            'email' => '  ADA@EXAMPLE.COM ',
            'codigo' => '0123',
        ])->assertOk()
            ->assertJsonPath('status', ResetPasswordAttempt::STATUS_VALIDATED);

        $this->assertSame(
            ResetPasswordAttempt::STATUS_VALIDATED,
            $attempt->fresh()->status,
        );
    }

    public function test_it_rejects_an_incorrect_code_without_consuming_the_attempt(): void
    {
        $user = User::factory()->create(['email' => 'ada@example.com']);
        $attempt = $user->resetPasswordAttempts()->create([
            'codigo' => '1234',
        ]);

        $this->postJson('/api/password/reset-attempts/validate', [
            'email' => 'ada@example.com',
            'codigo' => '9999',
        ])->assertUnprocessable()
            ->assertJsonValidationErrors('codigo');

        $this->assertSame(
            ResetPasswordAttempt::STATUS_PENDING,
            $attempt->fresh()->status,
        );
    }

    public function test_it_expires_an_attempt_and_returns_the_expired_code_message(): void
    {
        $user = User::factory()->create(['email' => 'ada@example.com']);
        $attempt = $user->resetPasswordAttempts()->create([
            'codigo' => '1234',
            'expires_at' => now()->subSecond(),
        ]);

        $this->postJson('/api/password/reset-attempts/validate', [
            'email' => 'ada@example.com',
            'codigo' => '1234',
        ])->assertUnprocessable()
            ->assertJsonValidationErrors('codigo')
            ->assertJsonPath('errors.codigo.0', __('api.auth.reset_code_expired'));

        $this->assertSame(
            ResetPasswordAttempt::STATUS_EXPIRED,
            $attempt->fresh()->status,
        );
    }

    public function test_it_rejects_an_expired_or_already_validated_attempt(): void
    {
        $user = User::factory()->create(['email' => 'ada@example.com']);

        foreach ([
            ResetPasswordAttempt::STATUS_EXPIRED,
            ResetPasswordAttempt::STATUS_VALIDATED,
        ] as $status) {
            $user->resetPasswordAttempts()->create([
                'codigo' => '1234',
                'status' => $status,
            ]);
        }

        $this->postJson('/api/password/reset-attempts/validate', [
            'email' => 'ada@example.com',
            'codigo' => '1234',
        ])->assertUnprocessable()
            ->assertJsonValidationErrors('codigo');
    }

    public function test_it_requires_exactly_four_numeric_digits(): void
    {
        foreach (['123', '12345', '12a4'] as $invalidCode) {
            $this->postJson('/api/password/reset-attempts/validate', [
                'email' => 'ada@example.com',
                'codigo' => $invalidCode,
            ])->assertUnprocessable()
                ->assertJsonValidationErrors('codigo');
        }
    }
}
