<?php

use App\Livewire\Auth\VerifyEmail;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Notification;
use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailNotification;
use Livewire\Livewire;

uses(RefreshDatabase::class);

it('can render the verify email component', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    $component = Livewire::test(VerifyEmail::class);
    
    $component->assertStatus(200);
    $component->assertSeeText('Please verify your email address');
    $component->assertSeeText('Resend verification email');
    $component->assertSeeText('Log out');
});

it('sends verification email when requested', function () {
    Notification::fake();
    
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    Livewire::test(VerifyEmail::class)
        ->call('sendVerification');
    
    Notification::assertSentTo($user, VerifyEmailNotification::class);
});

it('calls sendEmailVerificationNotification on user', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    // Mock the user to verify the method is called
    $userMock = $this->partialMock(User::class);
    $userMock->shouldReceive('hasVerifiedEmail')->andReturn(false);
    $userMock->shouldReceive('sendEmailVerificationNotification')->once();
    
    auth()->setUser($userMock);
    
    Livewire::test(VerifyEmail::class)
        ->call('sendVerification');
});

it('redirects to dashboard if user is already verified', function () {
    $user = User::factory()->create(['email_verified_at' => now()]);
    
    $this->actingAs($user);
    
    Livewire::test(VerifyEmail::class)
        ->call('sendVerification')
        ->assertRedirect(route('dashboard'));
});

it('does not send email if user is already verified', function () {
    Notification::fake();
    
    $user = User::factory()->create(['email_verified_at' => now()]);
    
    $this->actingAs($user);
    
    Livewire::test(VerifyEmail::class)
        ->call('sendVerification');
    
    Notification::assertNotSentTo($user, VerifyEmailNotification::class);
});

it('logs out user when logout is called', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    // Ensure user is authenticated before logout
    expect(auth()->check())->toBe(true);
    expect(auth()->user()->id)->toBe($user->id);
    
    Livewire::test(VerifyEmail::class)
        ->call('logout')
        ->assertRedirect('/');
    
    // User should be logged out after the action
    expect(auth()->check())->toBe(false);
});

it('invalidates session when logging out', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    // Set some session data
    session(['test_key' => 'test_value']);
    expect(session('test_key'))->toBe('test_value');
    
    Livewire::test(VerifyEmail::class)
        ->call('logout');
    
    // Session should be invalidated
    expect(session('test_key'))->toBeNull();
});

it('displays verification prompt text correctly', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    $component = Livewire::test(VerifyEmail::class);
    
    $component->assertSeeText('Please verify your email address by clicking on the link we just emailed to you');
});

it('shows resend button for unverified users', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    $component = Livewire::test(VerifyEmail::class);
    
    $component->assertSeeText('Resend verification email');
});

it('shows logout link', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    $component = Livewire::test(VerifyEmail::class);
    
    $component->assertSeeText('Log out');
});

it('can send multiple verification emails', function () {
    Notification::fake();
    
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    $component = Livewire::test(VerifyEmail::class);
    
    // Send first verification email
    $component->call('sendVerification');
    
    // Send second verification email
    $component->call('sendVerification');
    
    // Should have sent 2 notifications
    Notification::assertSentToTimes($user, VerifyEmailNotification::class, 2);
});

it('displays success message when status session is set', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    // Manually set the session status and test the view
    session(['status' => 'verification-link-sent']);
    
    $component = Livewire::test(VerifyEmail::class);
    $component->assertSeeText('A new verification link has been sent');
});

it('works with different email formats', function () {
    Notification::fake();
    
    $emails = [
        'test@example.com',
        'user.name+tag@domain.co.uk',
        'test.email@sub.domain.com'
    ];
    
    foreach ($emails as $email) {
        $user = User::factory()->unverified()->create(['email' => $email]);
        
        $this->actingAs($user);
        
        Livewire::test(VerifyEmail::class)
            ->call('sendVerification');
        
        Notification::assertSentTo($user, VerifyEmailNotification::class);
        
        // Clean up for next iteration
        auth()->logout();
        Notification::fake();
    }
});

it('works for admin users who are unverified', function () {
    Notification::fake();
    
    $adminUser = User::factory()->unverified()->create(['is_admin' => true]);
    
    $this->actingAs($adminUser);
    
    $component = Livewire::test(VerifyEmail::class);
    
    $component->assertStatus(200);
    
    $component->call('sendVerification');
    
    Notification::assertSentTo($adminUser, VerifyEmailNotification::class);
});

it('handles already verified admin users correctly', function () {
    $verifiedAdmin = User::factory()->create([
        'is_admin' => true,
        'email_verified_at' => now()
    ]);
    
    $this->actingAs($verifiedAdmin);
    
    Livewire::test(VerifyEmail::class)
        ->call('sendVerification')
        ->assertRedirect(route('dashboard'));
});

it('handles session flash message display correctly', function () {
    $user = User::factory()->unverified()->create();
    
    $this->actingAs($user);
    
    // Test without flash message - should not show success text
    $component = Livewire::test(VerifyEmail::class);
    $component->assertDontSeeText('A new verification link has been sent');
    
    // Test with flash message - should show success text
    session()->flash('status', 'verification-link-sent');
    $component = Livewire::test(VerifyEmail::class);
    $component->assertSeeText('A new verification link has been sent');
});