<?php

namespace Tests\Feature\Livewire\Auth;

use App\Livewire\Auth\Register;
use App\Models\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Hash;
use Livewire\Livewire;
use Tests\TestCase;

class RegisterTest extends TestCase
{
    /** @test */
    public function it_renders_the_register_component(): void
    {
        $component = Livewire::test(Register::class);

        $component->assertStatus(200);
        $component->assertSee('Name');
        $component->assertSee('Email');
        $component->assertSee('Password');
    }

    /** @test */
    public function it_validates_required_name_field(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('email', 'test@example.com')
            ->set('password', 'password')
            ->set('password_confirmation', 'password')
            ->call('register')
            ->assertHasErrors(['name' => 'required']);
    }

    /** @test */
    public function it_validates_required_email_field(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('password', 'password')
            ->set('password_confirmation', 'password')
            ->call('register')
            ->assertHasErrors(['email' => 'required']);
    }

    /** @test */
    public function it_validates_email_format(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'invalid-email')
            ->set('password', 'password')
            ->set('password_confirmation', 'password')
            ->call('register')
            ->assertHasErrors(['email' => 'email']);
    }

    /** @test */
    public function it_validates_required_password_field(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@example.com')
            ->set('password_confirmation', 'password')
            ->call('register')
            ->assertHasErrors(['password' => 'required']);
    }

    /** @test */
    public function it_validates_password_confirmation(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@example.com')
            ->set('password', 'password')
            ->set('password_confirmation', 'different-password')
            ->call('register')
            ->assertHasErrors(['password' => 'confirmed']);
    }

    /** @test */
    public function it_creates_user_with_valid_data(): void
    {
        Event::fake();

        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com') // Use gmail to pass indisposable validation
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register');

        $this->assertDatabaseHas('users', [
            'name' => 'Test User',
            'email' => 'test@gmail.com',
        ]);

        $this->assertAuthenticatedAs(User::query()->where('email', 'test@gmail.com')->first());
        Event::assertDispatched(Registered::class);
    }

    /** @test */
    public function it_hashes_password_before_storing(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com') // Use gmail to pass indisposable validation
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register');

        $user = User::query()->where('email', 'test@gmail.com')->first();
        $this->assertTrue(Hash::check('Password123!', $user->password));
    }

    /** @test */
    public function it_prevents_duplicate_email_registration(): void
    {
        // Create existing user
        User::factory()->create(['email' => 'test@gmail.com']);

        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com')
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register')
            ->assertHasErrors(['email']);
    }

    /** @test */
    public function it_redirects_after_successful_registration(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com')
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register');

        $this->assertAuthenticated();
    }

    /** @test */
    public function it_logs_in_user_after_registration(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com')
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register');

        $this->assertTrue(Auth::check());
        $this->assertEquals('test@gmail.com', Auth::user()->email);
    }

    /** @test */
    public function it_handles_maximum_name_length(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', str_repeat('a', 256)) // Too long
            ->set('email', 'test@gmail.com')
            ->set('password', 'Password123!')
            ->set('password_confirmation', 'Password123!')
            ->call('register')
            ->assertHasErrors(['name' => 'max']);
    }

    /** @test */
    public function it_handles_password_validation(): void
    {
        $component = Livewire::test(Register::class);

        $component
            ->set('name', 'Test User')
            ->set('email', 'test@gmail.com')
            ->set('password', '123') // Too short and weak
            ->set('password_confirmation', '123')
            ->call('register')
            ->assertHasErrors(['password']);
    }
}
