<?php

use App\Models\Service;
use App\Models\User;
use Laravel\Socialite\Facades\Socialite;
use Laravel\Socialite\Two\User as SocialiteUser;

it('redirects unauthenticated users to login', function () {
    $response = $this->get('/');

    $response->assertRedirect('/login');
});

it('shows login page with OAuth button', function () {
    $response = $this->get('/login');

    $response->assertStatus(200);
    $response->assertInertia(
        fn ($page) => $page
            ->component('Auth/Login')
    );
});

it('login page has no email or password inputs', function () {
    $response = $this->get('/login');

    $response->assertStatus(200);
    // The Login.vue should NOT contain email/password form fields
    // This is verified by checking the component renders correctly
    $response->assertInertia(
        fn ($page) => $page
            ->component('Auth/Login')
    );
});

it('redirects to ChurchTools OAuth on auth initiation', function () {
    $providerMock = Mockery::mock(\Laravel\Socialite\Two\AbstractProvider::class);
    $providerMock->shouldReceive('redirect')
        ->once()
        ->andReturn(redirect('https://churchtools.example.com/oauth/authorize'));

    Socialite::shouldReceive('driver')
        ->with('churchtools')
        ->once()
        ->andReturn($providerMock);

    $response = $this->get('/auth/churchtools');

    $response->assertRedirect();
    $response->assertRedirectContains('churchtools.example.com/oauth/authorize');
});

it('creates a new user from OAuth callback', function () {
    $service = Service::factory()->create(['date' => now()->addDays(7)]);

    $socialiteUser = new SocialiteUser();
    $socialiteUser->map([
        'id' => '42',
        'name' => 'Max Mustermann',
        'email' => 'max@example.com',
        'avatar' => 'https://churchtools.example.com/avatar/42.jpg',
    ]);
    $socialiteUser->user = [
        'id' => 42,
        'firstName' => 'Max',
        'lastName' => 'Mustermann',
        'displayName' => 'Max Mustermann',
        'email' => 'max@example.com',
        'imageUrl' => 'https://churchtools.example.com/avatar/42.jpg',
        'groups' => [['id' => 1, 'name' => 'Worship']],
        'roles' => [['id' => 2, 'name' => 'Admin']],
    ];

    $providerMock = Mockery::mock(\Laravel\Socialite\Two\AbstractProvider::class);
    $providerMock->shouldReceive('user')
        ->once()
        ->andReturn($socialiteUser);

    Socialite::shouldReceive('driver')
        ->with('churchtools')
        ->once()
        ->andReturn($providerMock);

    $response = $this->get('/auth/churchtools/callback');

    $response->assertRedirect(route('services.edit', $service->id));

    $this->assertDatabaseHas('users', [
        'email' => 'max@example.com',
        'name' => 'Max Mustermann',
        'churchtools_id' => 42,
        'avatar' => 'https://churchtools.example.com/avatar/42.jpg',
    ]);

    $user = User::where('email', 'max@example.com')->first();
    expect($user)->not->toBeNull();
    expect((int) $user->churchtools_id)->toBe(42);
    expect($user->churchtools_groups)->toBe([['id' => 1, 'name' => 'Worship']]);
    expect($user->churchtools_roles)->toBe([['id' => 2, 'name' => 'Admin']]);
    $this->assertAuthenticatedAs($user);
});

it('updates existing user on OAuth callback', function () {
    $service = Service::factory()->create(['date' => now()->addDays(7)]);

    $existingUser = User::factory()->create([
        'email' => 'max@example.com',
        'name' => 'Old Name',
        'churchtools_id' => 42,
    ]);

    $socialiteUser = new SocialiteUser();
    $socialiteUser->map([
        'id' => '42',
        'name' => 'Max Mustermann',
        'email' => 'max@example.com',
        'avatar' => 'https://churchtools.example.com/avatar/42.jpg',
    ]);
    $socialiteUser->user = [
        'id' => 42,
        'firstName' => 'Max',
        'lastName' => 'Mustermann',
        'displayName' => 'Max Mustermann',
        'email' => 'max@example.com',
        'imageUrl' => 'https://churchtools.example.com/avatar/42.jpg',
        'groups' => [['id' => 1, 'name' => 'Worship']],
        'roles' => [['id' => 2, 'name' => 'Admin']],
    ];

    $providerMock = Mockery::mock(\Laravel\Socialite\Two\AbstractProvider::class);
    $providerMock->shouldReceive('user')
        ->once()
        ->andReturn($socialiteUser);

    Socialite::shouldReceive('driver')
        ->with('churchtools')
        ->once()
        ->andReturn($providerMock);

    $response = $this->get('/auth/churchtools/callback');

    $response->assertRedirect(route('services.edit', $service->id));

    $existingUser->refresh();
    expect($existingUser->name)->toBe('Max Mustermann');
    expect($existingUser->avatar)->toBe('https://churchtools.example.com/avatar/42.jpg');
    expect(User::count())->toBe(1);
    $this->assertAuthenticatedAs($existingUser);
});

it('logs out user and redirects to login', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)->post('/logout');

    $response->assertRedirect('/login');
    $this->assertGuest();
});

it('does not have register routes', function () {
    $response = $this->get('/register');

    $response->assertStatus(404);
});

it('authenticated user can access dashboard', function () {
    $user = User::factory()->create();

    $response = $this->actingAs($user)->get('/dashboard');

    $response->assertStatus(200);
});
