<?php

namespace Tests\Feature;

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

class AuthTest extends TestCase
{
    use RefreshDatabase;

    public function test_register_cria_usuario_e_retorna_token(): void
    {
        $response = $this->postJson('/api/v1/auth/register', [
            'name'                  => 'Novo Usuário',
            'email'                 => 'novo@test.com',
            'password'              => 'senha123',
            'password_confirmation' => 'senha123',
            'user_type'             => 'turista',
        ]);

        $response->assertStatus(201)
            ->assertJsonStructure([
                'success',
                'data' => ['token', 'token_type', 'user' => ['id', 'name', 'email', 'role', 'user_type', 'locale']],
                'message',
                'errors',
            ])
            ->assertJson([
                'success' => true,
                'data'    => [
                    'token_type' => 'Bearer',
                    'user'       => [
                        'name'      => 'Novo Usuário',
                        'email'     => 'novo@test.com',
                        'role'      => 'usuario',
                        'user_type' => 'turista',
                        'locale'    => 'pt_BR',
                    ],
                ],
            ]);

        $this->assertDatabaseHas('users', ['email' => 'novo@test.com', 'role' => 'usuario']);
    }

    public function test_register_default_user_type_turista(): void
    {
        $response = $this->postJson('/api/v1/auth/register', [
            'name'                  => 'Sem Tipo',
            'email'                 => 'semtipo@test.com',
            'password'              => 'senha123',
            'password_confirmation' => 'senha123',
        ]);

        $response->assertStatus(201)
            ->assertJsonPath('data.user.user_type', 'turista');
    }

    public function test_register_valida_campos_obrigatorios(): void
    {
        $response = $this->postJson('/api/v1/auth/register', []);

        $response->assertStatus(422)
            ->assertJson(['success' => false])
            ->assertJsonValidationErrors(['name', 'email', 'password']);
    }

    public function test_register_rejeita_email_duplicado(): void
    {
        User::factory()->create(['email' => 'existente@test.com']);

        $response = $this->postJson('/api/v1/auth/register', [
            'name'                  => 'Dup',
            'email'                 => 'existente@test.com',
            'password'              => 'senha123',
            'password_confirmation' => 'senha123',
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['email']);
    }

    public function test_login_retorna_token(): void
    {
        User::factory()->create([
            'email'    => 'login@test.com',
            'password' => 'senha123',
        ]);

        $response = $this->postJson('/api/v1/auth/login', [
            'email'    => 'login@test.com',
            'password' => 'senha123',
        ]);

        $response->assertOk()
            ->assertJsonStructure(['data' => ['token', 'token_type', 'user']])
            ->assertJsonPath('success', true);
    }

    public function test_login_credenciais_invalidas(): void
    {
        User::factory()->create(['email' => 'user@test.com', 'password' => 'correta']);

        $response = $this->postJson('/api/v1/auth/login', [
            'email'    => 'user@test.com',
            'password' => 'errada',
        ]);

        $response->assertStatus(422)
            ->assertJson(['success' => false]);
    }

    public function test_logout_invalida_token(): void
    {
        $user  = User::factory()->create();
        $token = $user->createToken('auth_token')->plainTextToken;

        $response = $this->withHeader('Authorization', "Bearer $token")
            ->postJson('/api/v1/auth/logout');

        $response->assertOk()
            ->assertJson(['success' => true]);

        $this->assertCount(0, $user->fresh()->tokens);
    }

    public function test_refresh_gera_novo_token(): void
    {
        $user  = User::factory()->create();
        $token = $user->createToken('auth_token')->plainTextToken;

        $response = $this->withHeader('Authorization', "Bearer $token")
            ->postJson('/api/v1/auth/refresh');

        $response->assertOk()
            ->assertJsonStructure(['data' => ['token', 'token_type']])
            ->assertJsonPath('success', true);

        // Token antigo não deve mais funcionar
        $this->assertCount(1, $user->fresh()->tokens);
    }

    public function test_perfil_retorna_dados_do_usuario(): void
    {
        $user = User::factory()->create([
            'name'      => 'Fulano',
            'email'     => 'fulano@test.com',
            'role'      => 'usuario',
            'user_type' => 'turista',
        ]);

        $response = $this->actingAs($user)->getJson('/api/v1/auth/perfil');

        $response->assertOk()
            ->assertJson([
                'success' => true,
                'data'    => [
                    'name'      => 'Fulano',
                    'email'     => 'fulano@test.com',
                    'role'      => 'usuario',
                    'user_type' => 'turista',
                ],
            ]);
    }

    public function test_rotas_protegidas_retornam_401(): void
    {
        $this->postJson('/api/v1/auth/logout')->assertStatus(401);
        $this->postJson('/api/v1/auth/refresh')->assertStatus(401);
        $this->getJson('/api/v1/auth/perfil')->assertStatus(401);
    }
}
