<?php

namespace Tests\Feature;

use App\Models\Role;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Laravel\Sanctum\PersonalAccessToken;
use Tests\TestCase;

class AuthenticationTest extends TestCase
{
    use RefreshDatabase;

    public function test_a_user_can_register_with_a_hashed_password_and_token(): void
    {
        Role::create(['name' => 'student']);

        $response = $this->postJson('/api/auth/register', [
            'full_name' => 'Ada Geologist',
            'email' => 'ada@example.com',
            'password' => 'correct-horse-battery',
            'password_confirmation' => 'correct-horse-battery',
        ]);

        $response->assertCreated()->assertJsonPath('data.user.email', 'ada@example.com');
        $this->assertDatabaseHas('users', ['email' => 'ada@example.com']);
        $this->assertTrue(Hash::check('correct-horse-battery', User::where('email', 'ada@example.com')->value('password')));
        $this->assertNotSame('correct-horse-battery', User::where('email', 'ada@example.com')->value('password'));
        $this->assertNotEmpty($response->json('data.token'));
    }

    public function test_duplicate_email_is_rejected(): void
    {
        Role::create(['name' => 'student']);
        User::factory()->create(['email' => 'ada@example.com']);

        $this->postJson('/api/auth/register', [
            'full_name' => 'Another Ada',
            'email' => 'ada@example.com',
            'password' => 'correct-horse-battery',
            'password_confirmation' => 'correct-horse-battery',
        ])->assertUnprocessable()->assertJsonValidationErrors('email');
    }

    public function test_active_user_can_login_and_logout_revokes_the_current_token(): void
    {
        $role = Role::create(['name' => 'student']);
        $user = User::factory()->create([
            'email' => 'ada@example.com',
            'password' => 'correct-horse-battery',
            'role_id' => $role->id,
            'status' => 'active',
        ]);

        $login = $this->postJson('/api/auth/login', [
            'email' => 'ada@example.com',
            'password' => 'correct-horse-battery',
        ])->assertOk();

        $token = $login->json('data.token');
        $this->assertNotEmpty($token);
        $this->withToken($token)->getJson('/api/auth/me')->assertOk()->assertJsonPath('data.email', 'ada@example.com');
        $this->withToken($token)->postJson('/api/auth/logout')->assertOk();
        $this->assertDatabaseMissing('personal_access_tokens', ['tokenable_id' => $user->id]);
        $this->assertCount(0, PersonalAccessToken::where('tokenable_id', $user->id)->get());
    }

    public function test_suspended_user_cannot_login(): void
    {
        $role = Role::create(['name' => 'student']);
        User::factory()->create([
            'email' => 'suspended@example.com',
            'password' => 'correct-horse-battery',
            'role_id' => $role->id,
            'status' => 'suspended',
        ]);

        $this->postJson('/api/auth/login', [
            'email' => 'suspended@example.com',
            'password' => 'correct-horse-battery',
        ])->assertUnauthorized();
    }
}