<?php

declare(strict_types=1);

use App\Filament\Pages\Monitoring\AuditLog as AuditLogPage;
use App\Models\AuditLog as AuditLogModel;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\DB;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;

function auditLogPageTestComponent(User $user, ?ManagedEnvironment $tenant = null): Testable
{
    test()->actingAs($user);
    Filament::setTenant($tenant, true);

    return Livewire::withHeaders(['referer' => route('admin.monitoring.audit-log')])
        ->actingAs($user)
        ->test(AuditLogPage::class);
}

function auditLogPageTestRecord(?ManagedEnvironment $tenant, array $attributes = []): AuditLogModel
{
    $workspaceId = array_key_exists('workspace_id', $attributes)
        ? (int) $attributes['workspace_id']
        : (int) ($tenant?->workspace_id ?? Workspace::factory()->create()->getKey());

    return AuditLogModel::query()->create(array_merge([
        'workspace_id' => $workspaceId,
        'managed_environment_id' => $tenant?->getKey(),
        'actor_email' => 'auditor@example.com',
        'actor_name' => 'Audit Operator',
        'action' => 'operation.completed',
        'status' => 'success',
        'resource_type' => 'operation_run',
        'resource_id' => '1',
        'summary' => 'Operation completed',
        'metadata' => [],
        'recorded_at' => now(),
    ], $attributes));
}

it('renders the canonical audit route as a summary-first monitoring surface', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(route('admin.monitoring.audit-log'))
        ->assertOk()
        ->assertSee('Summary-first audit history')
        ->assertSee('Review governance, operational, and workspace-admin events in reverse chronological order');
});

it('keeps preselected audit detail subordinate to the summary-first route', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $audit = auditLogPageTestRecord($tenant, [
        'summary' => 'Preselected audit detail',
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(route('admin.monitoring.audit-log', ['event' => (int) $audit->getKey()]))
        ->assertOk()
        ->assertSee('Summary-first audit history')
        ->assertSee('Preselected audit detail')
        ->assertDontSee('Focused review lane');
});

it('loads the audit page with populated filter options', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    auditLogPageTestRecord($tenant, [
        'action' => 'verification.completed',
        'actor_name' => 'Ahmed Darrazi',
        'resource_type' => 'tenant',
        'resource_id' => (string) $tenant->getKey(),
        'summary' => 'Verification completed',
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(route('admin.monitoring.audit-log'))
        ->assertOk()
        ->assertSee('Event type')
        ->assertSee('Actor')
        ->assertSee('Target type');
});

it('renders derived labels for audit rows that are missing evolved snapshot columns', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    DB::table('audit_logs')->insert([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'actor_id' => null,
        'actor_email' => 'spo_admin@yptw2.onmicrosoft.com',
        'actor_name' => 'Ahmed Darrazi',
        'action' => 'baseline.capture.started',
        'resource_type' => 'baseline_profile',
        'resource_id' => '2',
        'status' => 'success',
        'metadata' => json_encode([
            'baseline_profile_id' => 2,
            'baseline_profile_name' => 'Device Compliance',
        ], JSON_THROW_ON_ERROR),
        'recorded_at' => now(),
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(route('admin.monitoring.audit-log'))
        ->assertOk()
        ->assertSee('Baseline capture started for Baseline profile #2')
        ->assertSee('Ahmed Darrazi')
        ->assertSee('Baseline profile #2')
        ->assertSee('Success');
});

it('renders workspace setting targets with readable labels', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    auditLogPageTestRecord($tenant, [
        'action' => 'workspace_setting.updated',
        'summary' => 'Workspace setting updated for backup.retention_keep_last_default',
        'resource_type' => 'workspace_setting',
        'resource_id' => 'backup.retention_keep_last_default',
        'target_label' => 'backup.retention_keep_last_default',
    ]);

    $this->actingAs($user)
        ->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
        ->get(route('admin.monitoring.audit-log'))
        ->assertOk()
        ->assertSee('Workspace setting updated for Backup Retention Keep Last Default')
        ->assertSee('Backup Retention Keep Last Default');
});

it('shows reverse-chronological audit rows and supports summary search', function (): void {
    [$user, $tenantA] = createUserWithTenant(role: 'owner');

    $tenantB = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
    ]);

    createUserWithTenant($tenantB, $user, role: 'owner');

    $oldest = auditLogPageTestRecord($tenantA, [
        'resource_id' => '101',
        'summary' => 'Older baseline capture completed',
        'action' => 'baseline.capture.completed',
        'recorded_at' => now()->subMinutes(15),
    ]);

    $middle = auditLogPageTestRecord($tenantB, [
        'resource_id' => '102',
        'summary' => 'Rotate backup schedule credentials',
        'action' => 'backup.updated',
        'recorded_at' => now()->subMinutes(5),
    ]);

    $newest = auditLogPageTestRecord($tenantA, [
        'resource_id' => '103',
        'summary' => 'Newest restore failed',
        'action' => 'restore.failed',
        'status' => 'failed',
        'recorded_at' => now()->subMinute(),
    ]);

    auditLogPageTestComponent($user)
        ->assertOk()
        ->assertCanSeeTableRecords([$newest, $middle, $oldest], inOrder: true)
        ->searchTable('Rotate')
        ->assertCanSeeTableRecords([$middle])
        ->assertCanNotSeeTableRecords([$newest, $oldest]);
});

it('keeps the audit log unfiltered when an active tenant context exists', function (): void {
    [$user, $tenantA] = createUserWithTenant(role: 'owner');

    $tenantB = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
    ]);

    createUserWithTenant($tenantB, $user, role: 'owner');

    $tenantARecord = auditLogPageTestRecord($tenantA, [
        'resource_id' => '201',
        'summary' => 'ManagedEnvironment A verification completed',
        'action' => 'verification.completed',
    ]);

    $tenantBRecord = auditLogPageTestRecord($tenantB, [
        'resource_id' => '202',
        'summary' => 'ManagedEnvironment B verification completed',
        'action' => 'verification.completed',
    ]);

    auditLogPageTestComponent($user, $tenantA)
        ->assertSet('tableFilters.managed_environment_id.value', null)
        ->assertCanSeeTableRecords([$tenantARecord, $tenantBRecord]);
});

it('keeps the audit log unfiltered when only a remembered environment context exists', function (): void {
    $tenantA = ManagedEnvironment::factory()->create([
        'name' => 'Phoenicon',
        'environment' => 'dev',
    ]);
    [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner');

    $tenantB = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
        'name' => 'YPTW2',
        'environment' => 'dev',
    ]);

    createUserWithTenant($tenantB, $user, role: 'owner');

    $tenantARecord = auditLogPageTestRecord($tenantA, [
        'resource_id' => '301',
        'summary' => 'Phoenicon verification completed',
        'action' => 'verification.completed',
    ]);

    $tenantBRecord = auditLogPageTestRecord($tenantB, [
        'resource_id' => '302',
        'summary' => 'YPTW2 verification completed',
        'action' => 'verification.completed',
    ]);

    $this->actingAs($user);
    Filament::setTenant(null, true);

    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenantA->workspace_id);
    session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
        (string) $tenantA->workspace_id => (int) $tenantA->getKey(),
    ]);

    Livewire::withHeaders(['referer' => route('admin.monitoring.audit-log')])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertSet('tableFilters.managed_environment_id.value', null)
        ->assertCanSeeTableRecords([$tenantARecord, $tenantBRecord]);
});

it('clears a stale persisted audit tenant filter when the workspace shell is tenantless', function (): void {
    $tenantA = ManagedEnvironment::factory()->create([
        'name' => 'YPTW2',
        'environment' => 'dev',
    ]);
    [$user, $tenantA] = createUserWithTenant(tenant: $tenantA, role: 'owner');

    $tenantB = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $tenantA->workspace_id,
        'name' => 'Phoenicon',
        'environment' => 'dev',
    ]);

    createUserWithTenant($tenantB, $user, role: 'owner');

    $tenantARecord = auditLogPageTestRecord($tenantA, [
        'resource_id' => '401',
        'summary' => 'YPTW2 verification completed',
    ]);

    $tenantBRecord = auditLogPageTestRecord($tenantB, [
        'resource_id' => '402',
        'summary' => 'Phoenicon verification completed',
    ]);

    $this->actingAs($user);
    Filament::setTenant(null, true);

    $workspaceId = (int) $tenantA->workspace_id;

    session()->put(WorkspaceContext::SESSION_KEY, $workspaceId);
    session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
        (string) $workspaceId => (int) $tenantA->getKey(),
    ]);

    $component = Livewire::withHeaders(['referer' => route('admin.monitoring.audit-log')])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertSet('tableFilters.managed_environment_id.value', null)
        ->assertCanSeeTableRecords([$tenantARecord, $tenantBRecord]);

    expect(data_get(session()->get($component->instance()->getTableFiltersSessionKey()), 'managed_environment_id.value'))
        ->toBeNull();

    session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [
        (string) $workspaceId => (int) $tenantB->getKey(),
    ]);

    Livewire::withHeaders(['referer' => route('admin.monitoring.audit-log')])
        ->actingAs($user)
        ->test(AuditLogPage::class)
        ->assertSet('tableFilters.managed_environment_id.value', null)
        ->assertCanSeeTableRecords([$tenantARecord, $tenantBRecord]);
});

it('shows a clear-filters empty state when no audit rows match the current view', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $record = auditLogPageTestRecord($tenant, [
        'summary' => 'Baseline compare completed',
        'action' => 'baseline.compare.completed',
    ]);

    auditLogPageTestComponent($user)
        ->assertTableEmptyStateActionsExistInOrder(['clear_filters'])
        ->searchTable('no-such-audit-event')
        ->assertCountTableRecords(0)
        ->assertSee('No audit events match this view')
        ->assertSee('Clear filters')
        ->searchTable(null)
        ->assertCanSeeTableRecords([$record]);
});
