<?php

use App\Models\Permission;
use App\Models\User;

function makeSessionManager(): User
{
    $user = User::factory()->create(['is_active' => true]);
    foreach (['view active sessions', 'manage active sessions'] as $name) {
        $perm = Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
        $user->givePermissionTo($perm);
    }

    return $user;
}

function makeSessionViewer(): User
{
    $user = User::factory()->create(['is_active' => true]);
    $perm = Permission::firstOrCreate(['name' => 'view active sessions', 'guard_name' => 'web']);
    $user->givePermissionTo($perm);

    return $user;
}

// ── Access control ────────────────────────────────────────────────────────────

test('guest cannot access session manager', function () {
    $this->get('/session-manager')->assertRedirect('/login');
});

test('user without permission is forbidden from session manager', function () {
    $user = User::factory()->create();

    $this->actingAs($user)->get('/session-manager')->assertForbidden();
});

test('user with view permission can access session manager', function () {
    $user = makeSessionViewer();

    $this->actingAs($user)->get('/session-manager')->assertOk();
});

test('guest cannot access session stats endpoint', function () {
    // JSON requests return 401 Unauthorized (not a redirect) for unauthenticated requests
    $this->getJson('/session-manager/stats')->assertUnauthorized();
});

test('user with view permission can access session stats', function () {
    $user = makeSessionViewer();

    $this->actingAs($user)->getJson('/session-manager/stats')
        ->assertOk()
        ->assertJsonStructure(['total', 'active']);
});

// ── Stats structure ────────────────────────────────────────────────────────────

test('stats endpoint returns valid json with total key', function () {
    $user = makeSessionViewer();

    $this->actingAs($user)
        ->getJson('/session-manager/stats')
        ->assertOk()
        ->assertJsonStructure(['total', 'active']);
});

// ── Terminate session ─────────────────────────────────────────────────────────

test('user without manage permission cannot terminate a session', function () {
    $viewer = makeSessionViewer();

    $this->actingAs($viewer)
        ->deleteJson('/session-manager/some-session-id')
        ->assertForbidden();
});

test('manager cannot terminate their own current session', function () {
    // The controller's destroy() checks: if ($id === session()->getId()) → 403.
    // We invoke it directly, bypassing HTTP, so the session ID is stable.
    $manager = makeSessionManager();
    $this->actingAs($manager);

    $controller = app(\App\Http\Controllers\SystemSettings\SessionManagerController::class);
    $currentId  = session()->getId();

    $response = $controller->destroy(request(), $currentId);

    expect($response->getStatusCode())->toBe(403);
    expect(json_decode($response->getContent(), true)['success'])->toBeFalse();
});

test('manager can terminate a different session id', function () {
    // With array/redis driver the controller returns success when no row is found to delete.
    $manager = makeSessionManager();

    $this->actingAs($manager)
        ->deleteJson('/session-manager/some-other-session-id')
        ->assertOk()
        ->assertJsonPath('success', true);
});

test('guest cannot terminate sessions', function () {
    // JSON requests return 401 (not a redirect) for unauthenticated requests
    $this->deleteJson('/session-manager/any-id')->assertUnauthorized();
});
