<?php

use App\Livewire\Forms\UserProfile;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;

uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);

test('component mounts with user data', function () {
    $user = User::factory()->create([
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'preferred_username' => 'johndoe',
        'avatar' => 'avatar.jpg',
        'auto_approve_apps' => true,
    ]);

    $this->actingAs($user);

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

    expect($component->get('name'))->toBe('John Doe');
    expect($component->get('email'))->toBe('john@example.com');
    expect($component->get('preferred_username'))->toBe('johndoe');
    expect($component->get('avatar'))->toBe('avatar.jpg');
    expect($component->get('auto_approve_apps'))->toBe(true);
});

test('profile information can be updated', function () {
    $user = User::factory()->create([
        'name' => 'Old Name',
        'email' => 'old@example.com',
        'preferred_username' => 'olduser',
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'New Name')
        ->set('email', 'new@example.com')
        ->set('preferred_username', 'newuser')
        ->set('auto_approve_apps', true)
        ->call('updateProfileInformation');

    $component->assertHasNoErrors();
    $component->assertDispatched('profile-updated', name: 'New Name');

    $user->refresh();
    expect($user->name)->toBe('New Name');
    expect($user->email)->toBe('new@example.com');
    expect($user->preferred_username)->toBe('newuser');
    expect($user->auto_approve_apps)->toBe(true);
});

test('profile information validation works', function () {
    $user = User::factory()->create(['auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', '')
        ->set('email', 'invalid-email')
        ->call('updateProfileInformation');

    $component->assertHasErrors(['name', 'email']);
});

test('email must be unique when updating profile', function () {
    $existingUser = User::factory()->create(['email' => 'existing@example.com', 'auto_approve_apps' => false]);
    $user = User::factory()->create(['email' => 'user@example.com', 'auto_approve_apps' => false]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('email', 'existing@example.com')
        ->call('updateProfileInformation');

    $component->assertHasErrors(['email']);
});

test('user can keep same email when updating other fields', function () {
    $user = User::factory()->create(['email' => 'user@example.com', 'auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'Updated Name')
        ->set('email', 'user@example.com')
        ->set('preferred_username', 'testuser')
        ->call('updateProfileInformation');

    $component->assertHasNoErrors();
});

test('avatar can be uploaded', function () {
    Storage::fake('avatars');
    
    $user = User::factory()->create(['auto_approve_apps' => false]);
    $this->actingAs($user);

    $file = UploadedFile::fake()->create('avatar.jpg', 1000, 'image/jpeg');

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'Test User')
        ->set('email', 'test@example.com')
        ->set('preferred_username', 'testuser')
        ->set('avatarUpload', $file)
        ->call('updateProfileInformation');

    $component->assertHasNoErrors();
    
    $user->refresh();
    expect($user->avatar)->not->toBeNull();
    Storage::disk('avatars')->assertExists($user->avatar);
});

test('old avatar is deleted when new one is uploaded', function () {
    Storage::fake('avatars');
    
    $oldAvatarPath = 'old-avatar.jpg';
    Storage::disk('avatars')->put($oldAvatarPath, 'fake content');
    
    $user = User::factory()->create(['avatar' => $oldAvatarPath, 'auto_approve_apps' => false]);
    $this->actingAs($user);

    $newFile = UploadedFile::fake()->create('new-avatar.jpg', 1000, 'image/jpeg');

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'Test User')
        ->set('email', 'test@example.com')
        ->set('preferred_username', 'testuser')
        ->set('avatarUpload', $newFile)
        ->call('updateProfileInformation');

    $component->assertHasNoErrors();
    
    Storage::disk('avatars')->assertMissing($oldAvatarPath);
    $user->refresh();
    Storage::disk('avatars')->assertExists($user->avatar);
});

test('avatar upload validation works', function () {
    $user = User::factory()->create(['auto_approve_apps' => false]);
    $this->actingAs($user);

    $file = UploadedFile::fake()->create('document.pdf', 15000); // Too large

    $component = Livewire::test(UserProfile::class)
        ->set('avatarUpload', $file);

    $component->assertHasErrors(['avatarUpload']);
});

test('password can be updated', function () {
    $user = User::factory()->create([
        'password' => Hash::make('current-password'),
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('current_password', 'current-password')
        ->set('password', 'new-password')
        ->set('password_confirmation', 'new-password')
        ->call('updatePassword');

    $component->assertHasNoErrors();
    $component->assertDispatched('password-updated');

    expect(Hash::check('new-password', $user->refresh()->password))->toBeTrue();
});

test('current password must be correct to update password', function () {
    $user = User::factory()->create([
        'password' => Hash::make('current-password'),
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('current_password', 'wrong-password')
        ->set('password', 'new-password')
        ->set('password_confirmation', 'new-password')
        ->call('updatePassword');

    $component->assertHasErrors(['current_password']);
});

test('new password must be confirmed', function () {
    $user = User::factory()->create([
        'password' => Hash::make('current-password'),
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('current_password', 'current-password')
        ->set('password', 'new-password')
        ->set('password_confirmation', 'different-password')
        ->call('updatePassword');

    $component->assertHasErrors(['password']);
});

test('password fields are reset after validation error', function () {
    $user = User::factory()->create([
        'password' => Hash::make('current-password'),
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('current_password', 'wrong-password')
        ->set('password', 'new-password')
        ->set('password_confirmation', 'new-password')
        ->call('updatePassword');

    expect($component->get('current_password'))->toBe('');
    expect($component->get('password'))->toBe('');
    expect($component->get('password_confirmation'))->toBe('');
});

test('password fields are reset after successful update', function () {
    $user = User::factory()->create([
        'password' => Hash::make('current-password'),
        'auto_approve_apps' => false,
    ]);

    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('current_password', 'current-password')
        ->set('password', 'new-password')
        ->set('password_confirmation', 'new-password')
        ->call('updatePassword');

    expect($component->get('current_password'))->toBe('');
    expect($component->get('password'))->toBe('');
    expect($component->get('password_confirmation'))->toBe('');
});

test('component renders correctly', function () {
    $user = User::factory()->create(['auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class);
    
    $component->assertViewIs('livewire.forms.user-profile');
});

test('profile information form validation requires all required fields', function () {
    $user = User::factory()->create(['auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', '')
        ->set('email', '')
        ->call('updateProfileInformation');

    $component->assertHasErrors(['name', 'email']);
});

test('email validation requires lowercase', function () {
    $user = User::factory()->create(['email' => 'original@example.com', 'auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'Test User')
        ->set('email', 'UPPERCASE@EXAMPLE.COM')
        ->set('preferred_username', 'testuser')
        ->call('updateProfileInformation');

    $component->assertHasErrors(['email']);
});

test('preferred username can be null', function () {
    $user = User::factory()->create(['preferred_username' => 'oldusername', 'auto_approve_apps' => false]);
    $this->actingAs($user);

    $component = Livewire::test(UserProfile::class)
        ->set('name', 'Test User')
        ->set('email', 'test@example.com')
        ->set('preferred_username', '')
        ->call('updateProfileInformation');

    $component->assertHasNoErrors();
    
    $user->refresh();
    expect($user->preferred_username)->toBe('');
    expect($user->name)->toBe('Test User');
    expect($user->email)->toBe('test@example.com');
});