<?php

declare(strict_types=1);

use App\Models\AuditLog;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Support\Audit\AuditActionId;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

// --- T034: Comprehensive audit payload verification across all four scenarios ---

it('records workspace.auto_selected audit with single_membership reason', function (): void {
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspace->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    $this->actingAs($user)->get('/admin/_test/workspace-context');

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceAutoSelected->value)
        ->where('workspace_id', $workspace->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata)->toMatchArray([
        'method' => 'auto',
        'reason' => 'single_membership',
        'prev_workspace_id' => null,
    ]);
    expect($log->resource_type)->toBe('workspace');
    expect($log->resource_id)->toBe((string) $workspace->getKey());
    expect($log->actor_id)->toBe((int) $user->getKey());
});

it('records workspace.auto_selected audit with last_used reason', function (): void {
    $user = User::factory()->create();

    $workspaceA = Workspace::factory()->create();
    $workspaceB = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceA->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceB->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'operator',
    ]);

    // Set last_workspace_id to workspaceA.
    $user->forceFill(['last_workspace_id' => (int) $workspaceA->getKey()])->save();

    $this->actingAs($user)->get('/admin/_test/workspace-context');

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceAutoSelected->value)
        ->where('workspace_id', $workspaceA->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata)->toMatchArray([
        'method' => 'auto',
        'reason' => 'last_used',
        'prev_workspace_id' => null,
    ]);
    expect($log->resource_type)->toBe('workspace');
    expect($log->resource_id)->toBe((string) $workspaceA->getKey());
    expect($log->actor_id)->toBe((int) $user->getKey());
});

it('records workspace.selected audit with chooser reason on manual selection', function (): void {
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspace->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    Livewire::actingAs($user)
        ->test(\App\Filament\Pages\ChooseWorkspace::class)
        ->call('selectWorkspace', (int) $workspace->getKey());

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceSelected->value)
        ->where('workspace_id', $workspace->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata)->toMatchArray([
        'method' => 'manual',
        'reason' => 'chooser',
    ]);
    expect($log->resource_type)->toBe('workspace');
    expect($log->resource_id)->toBe((string) $workspace->getKey());
    expect($log->actor_id)->toBe((int) $user->getKey());
});

it('records workspace.selected audit with context_bar reason on switch-workspace POST', function (): void {
    $user = User::factory()->create();
    $workspace = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspace->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    $this->actingAs($user)
        ->post(route('admin.switch-workspace'), ['workspace_id' => (int) $workspace->getKey()]);

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceSelected->value)
        ->where('workspace_id', $workspace->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata)->toMatchArray([
        'method' => 'manual',
        'reason' => 'context_bar',
    ]);
    expect($log->resource_type)->toBe('workspace');
    expect($log->resource_id)->toBe((string) $workspace->getKey());
    expect($log->actor_id)->toBe((int) $user->getKey());
});

// --- T035: it_includes_prev_workspace_id_when_switching_from_active_workspace ---

it('includes prev_workspace_id when switching via chooser from active workspace', function (): void {
    $user = User::factory()->create();
    $workspaceA = Workspace::factory()->create();
    $workspaceB = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceA->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceB->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'operator',
    ]);

    // Simulate having workspaceA as the current workspace.
    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspaceA->getKey());

    Livewire::actingAs($user)
        ->test(\App\Filament\Pages\ChooseWorkspace::class)
        ->call('selectWorkspace', (int) $workspaceB->getKey());

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceSelected->value)
        ->where('workspace_id', $workspaceB->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata['prev_workspace_id'])->toBe((int) $workspaceA->getKey());
    expect($log->metadata['method'])->toBe('manual');
    expect($log->metadata['reason'])->toBe('chooser');
});

it('includes prev_workspace_id when switching via context bar from active workspace', function (): void {
    $user = User::factory()->create();
    $workspaceA = Workspace::factory()->create();
    $workspaceB = Workspace::factory()->create();

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceA->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'owner',
    ]);

    WorkspaceMembership::factory()->create([
        'workspace_id' => $workspaceB->getKey(),
        'user_id' => $user->getKey(),
        'role' => 'operator',
    ]);

    $this->actingAs($user)
        ->withSession([
            WorkspaceContext::SESSION_KEY => (int) $workspaceA->getKey(),
        ])
        ->post(route('admin.switch-workspace'), ['workspace_id' => (int) $workspaceB->getKey()]);

    $log = AuditLog::query()
        ->where('action', AuditActionId::WorkspaceSelected->value)
        ->where('workspace_id', $workspaceB->getKey())
        ->first();

    expect($log)->not->toBeNull();
    expect($log->metadata['prev_workspace_id'])->toBe((int) $workspaceA->getKey());
    expect($log->metadata['method'])->toBe('manual');
    expect($log->metadata['reason'])->toBe('context_bar');
});
