<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;

uses(RefreshDatabase::class);

it('completes happy path registration onboarding flow', function () {
    $register = $this->post('/register', [
        'email' => 'flow-user@example.com',
    ]);

    $register->assertRedirect('/setup/password');

    $user = User::query()->where('email', 'flow-user@example.com')->firstOrFail();
    expect($user->onboarding_step)->toBe('verified');
    expect($user->email_verified_at)->toBeNull();
    $this->assertAuthenticatedAs($user);

    $this->actingAs($user)
        ->post('/setup/password', [
            'password' => 'StrongPass1!',
            'password_confirmation' => 'StrongPass1!',
        ])->assertRedirect('/setup/username');

    $this->actingAs($user)
        ->post('/setup/username', [
            'username' => 'flow_user_final',
        ])->assertRedirect('/@flow_user_final');

    $user->refresh();
    expect($user->onboarding_step)->toBe('complete');
    expect($user->username)->toBe('flow_user_final');
});

it('rejects invalid verification token', function () {
    $response = $this->from('/login')->get('/verify/not-a-real-token');

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

it('rejects expired verification token', function () {
    $user = User::factory()->create([
        'email_verified_at' => null,
        'onboarding_step' => 'email',
        'is_active' => false,
    ]);

    $column = \Illuminate\Support\Facades\Schema::hasColumn('user_verification_tokens', 'token_hash') ? 'token_hash' : 'token';
    DB::table('user_verification_tokens')->insert([
        'user_id' => $user->id,
        $column => hash('sha256', 'expired-checklist-token'),
        'expires_at' => now()->subHour(),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    $response = $this->from('/login')->get('/verify/expired-checklist-token');

    $response->assertRedirect('/login');
    $response->assertSessionHasErrors('email');
    expect($user->fresh()->email_verified_at)->toBeNull();
});

it('rejects duplicate email at registration', function () {
    User::factory()->create([
        'email' => 'duplicate-check@example.com',
        'email_verified_at' => now(),
        'onboarding_step' => 'complete',
        'is_active' => true,
    ]);

    $response = $this->from('/register')->post('/register', [
        'email' => 'duplicate-check@example.com',
    ]);

    $response->assertRedirect('/register');
    $response->assertSessionHasErrors('email');
});

it('rejects username conflict during username setup', function () {
    User::factory()->create([
        'username' => 'taken_username',
        'onboarding_step' => 'complete',
    ]);

    $user = User::factory()->create([
        'username' => 'candidate_username',
        'onboarding_step' => 'password',
    ]);

    $this->actingAs($user)
        ->from('/setup/username')
        ->post('/setup/username', [
            'username' => 'taken_username',
        ])
        ->assertRedirect('/setup/username')
        ->assertSessionHasErrors('username');

    expect($user->fresh()->onboarding_step)->toBe('password');
});

it('resumes onboarding by redirecting user to current required step', function () {
    $user = User::factory()->create([
        'onboarding_step' => 'verified',
    ]);

    $this->actingAs($user)
        ->get('/profile')
        ->assertRedirect('/setup/password');

    $user->forceFill(['onboarding_step' => 'password'])->save();

    $this->actingAs($user)
        ->get('/upload')
        ->assertRedirect('/setup/username');
});
