<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Laravel\Socialite\Facades\Socialite;
use Laravel\Socialite\Two\User as SocialiteUser;
use Mockery;
use Tests\TestCase;

class AuthFlowTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_register_logout_and_login_again(): void
    {
        $this->post('/register', [
            'name' => 'Login Flow User',
            'email' => 'LoginFlow@example.com',
            'role' => 'Inspector',
            'password' => 'password123',
            'password_confirmation' => 'password123',
            'terms' => 'on',
        ])->assertRedirect('/dashboard');

        $this->post('/logout')->assertRedirect('/login');

        $this->post('/login', [
            'email' => ' loginflow@example.com ',
            'password' => 'password123',
        ])->assertRedirect('/dashboard');

        $this->assertAuthenticated();
    }

    public function test_user_can_login_with_google(): void
    {
        $this->mockGoogleUser([
            'id' => 'google-123',
            'name' => 'Google Inspector',
            'email' => 'GoogleUser@example.com',
            'avatar' => 'https://example.com/avatar.jpg',
        ]);

        $this->get('/auth/google/callback')->assertRedirect('/dashboard');

        $this->assertAuthenticated();
        $this->assertDatabaseHas('users', [
            'email' => 'googleuser@example.com',
            'name' => 'Google Inspector',
            'role' => 'Inspector',
            'google_id' => 'google-123',
            'avatar_url' => 'https://example.com/avatar.jpg',
        ]);
    }

    public function test_google_login_links_existing_email_without_creating_duplicate_user(): void
    {
        $existing = User::factory()->create([
            'email' => 'owner@example.com',
            'google_id' => null,
            'avatar_url' => null,
        ]);

        $this->mockGoogleUser([
            'id' => 'google-owner',
            'name' => 'Owner From Google',
            'email' => 'owner@example.com',
            'avatar' => 'https://example.com/owner.jpg',
        ]);

        $this->get('/auth/google/callback')->assertRedirect('/dashboard');

        $this->assertAuthenticatedAs($existing->fresh());
        $this->assertDatabaseCount('users', 1);
        $this->assertDatabaseHas('users', [
            'id' => $existing->id,
            'email' => 'owner@example.com',
            'google_id' => 'google-owner',
            'avatar_url' => 'https://example.com/owner.jpg',
        ]);
    }

    private function mockGoogleUser(array $attributes): void
    {
        $socialiteUser = (new SocialiteUser())->map([
            'id' => $attributes['id'],
            'name' => $attributes['name'],
            'email' => $attributes['email'],
            'avatar' => $attributes['avatar'],
        ]);

        $provider = Mockery::mock();
        $provider->shouldReceive('user')->once()->andReturn($socialiteUser);

        Socialite::shouldReceive('driver')->once()->with('google')->andReturn($provider);
    }
}
