<?php

use App\Models\User;
use App\Models\UserTrustedDevice;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;

test('guest without 2fa session is redirected to login', function () {
    $this->get('/2fa')->assertRedirect(route('login', absolute: false));
});

test('2fa view renders when 2fa session is set', function () {
    $user = User::factory()->create();

    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '654321');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->get('/2fa')->assertOk()->assertViewIs('auth.two-factor');
});

test('verify with correct code logs the user in', function () {
    $user = User::factory()->create();

    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '111222');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->post('/2fa', ['code' => '111222'])
        ->assertRedirect(route('dashboard', absolute: false));

    $this->assertAuthenticatedAs($user);
});

test('verify with wrong code keeps user logged out', function () {
    $user = User::factory()->create();
    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '111222');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->post('/2fa', ['code' => '999999'])
        ->assertSessionHas('error');

    $this->assertGuest();
});

test('verify with expired code redirects to login', function () {
    $user = User::factory()->create();
    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '111222');
    Session::put('auth.2fa_expires_at', now()->subSecond()->timestamp);

    $this->post('/2fa', ['code' => '111222'])
        ->assertRedirect(route('login', absolute: false))
        ->assertSessionHas('error');

    $this->assertGuest();
});

test('verify rejects code with wrong length', function () {
    $user = User::factory()->create();
    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '111222');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->post('/2fa', ['code' => '12345'])->assertSessionHasErrors('code');
    $this->assertGuest();
});

test('trust device option persists a trusted device row', function () {
    $user = User::factory()->create();
    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '888888');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->post('/2fa', ['code' => '888888', 'trust_device' => '1']);

    expect(UserTrustedDevice::where('user_id', $user->id)->count())->toBe(1);
});

test('trust device defaults to no row when option is unset', function () {
    $user = User::factory()->create();
    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '777777');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->post('/2fa', ['code' => '777777']);

    expect(UserTrustedDevice::where('user_id', $user->id)->count())->toBe(0);
});

test('trusted device cookie skips 2fa view and auto-logs-in', function () {
    $user = User::factory()->create();
    $deviceId = (string) Str::uuid();
    $secret = Str::random(64);

    UserTrustedDevice::create([
        'user_id' => $user->id,
        'device_id' => $deviceId,
        'token' => hash('sha256', $secret),
        'expires_at' => now()->addDays(30),
    ]);

    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '000000');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->withCookie('2fa_trust_device', $deviceId.'|'.$secret)
        ->get('/2fa')
        ->assertRedirect(route('dashboard', absolute: false));

    $this->assertAuthenticatedAs($user);
});

test('trusted device cookie with wrong secret does not auto-login', function () {
    $user = User::factory()->create();
    $deviceId = (string) Str::uuid();
    $realSecret = Str::random(64);

    UserTrustedDevice::create([
        'user_id' => $user->id,
        'device_id' => $deviceId,
        'token' => hash('sha256', $realSecret),
        'expires_at' => now()->addDays(30),
    ]);

    Session::put('auth.2fa_user_id', $user->id);
    Session::put('auth.2fa_code', '000000');
    Session::put('auth.2fa_expires_at', now()->addMinutes(10)->timestamp);

    $this->withCookie('2fa_trust_device', $deviceId.'|wrong-secret')
        ->get('/2fa')
        ->assertOk();

    $this->assertGuest();
});
