<?php

declare(strict_types=1);

use App\Filament\Resources\StoredReportResource;
use App\Filament\Resources\StoredReportResource\Pages\ListStoredReports;
use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Services\Auth\RoleCapabilityMap;
use App\Support\Auth\Capabilities;
use App\Support\TenantRole;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Livewire\Livewire;

uses(RefreshDatabase::class);

function storedReportEntitlementPermissionReport(ManagedEnvironment $tenant): StoredReport
{
    return StoredReport::factory()
        ->permissionPosture()
        ->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'workspace_id' => (int) $tenant->workspace_id,
            'fingerprint' => 'permission-entitlement',
        ]);
}

function storedReportEntitlementEntraReport(ManagedEnvironment $tenant): StoredReport
{
    return StoredReport::factory()
        ->entraAdminRoles()
        ->create([
            'managed_environment_id' => (int) $tenant->getKey(),
            'workspace_id' => (int) $tenant->workspace_id,
            'fingerprint' => 'entra-entitlement',
        ]);
}

it('registers the bounded permission posture read capability for read-only tenant roles', function (): void {
    expect(Capabilities::PERMISSION_POSTURE_VIEW)->toBe('permission_posture.view')
        ->and(Capabilities::all())->toContain(Capabilities::PERMISSION_POSTURE_VIEW)
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Owner, Capabilities::PERMISSION_POSTURE_VIEW))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Manager, Capabilities::PERMISSION_POSTURE_VIEW))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Operator, Capabilities::PERMISSION_POSTURE_VIEW))->toBeTrue()
        ->and(RoleCapabilityMap::hasCapability(TenantRole::Readonly, Capabilities::PERMISSION_POSTURE_VIEW))->toBeTrue();
});

it('returns 404 for non-members on stored-report collection and direct detail routes', function (): void {
    $user = \App\Models\User::factory()->create();
    $tenant = ManagedEnvironment::factory()->create();
    $report = storedReportEntitlementPermissionReport($tenant);

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('index', tenant: $tenant, panel: 'admin'))
        ->assertNotFound();

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('view', ['record' => $report], tenant: $tenant, panel: 'admin'))
        ->assertNotFound();
});

it('returns 403 for tenant members without any supported report capability on the collection route', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    Gate::define(Capabilities::PERMISSION_POSTURE_VIEW, fn (): bool => false);
    Gate::define(Capabilities::ENTRA_ROLES_VIEW, fn (): bool => false);

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('index', tenant: $tenant, panel: 'admin'))
        ->assertForbidden();
});

it('filters collection rows and filter options by report-family capability', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    $permissionReport = storedReportEntitlementPermissionReport($tenant);
    $entraReport = storedReportEntitlementEntraReport($tenant);

    Gate::define(Capabilities::PERMISSION_POSTURE_VIEW, fn (): bool => false);

    $this->actingAs($user);
    setAdminEnvironmentContext($tenant);

    Livewire::test(ListStoredReports::class)
        ->assertCanSeeTableRecords([$entraReport])
        ->assertCanNotSeeTableRecords([$permissionReport])
        ->assertSee('Entra admin roles report')
        ->assertDontSee('Permission posture report');

    expect(StoredReportResource::visibleReportFamilyOptions())
        ->toBe([StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES => 'Entra admin roles']);
});

it('returns 403 for direct detail access when the member lacks that report-family capability', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    $permissionReport = storedReportEntitlementPermissionReport($tenant);

    Gate::define(Capabilities::PERMISSION_POSTURE_VIEW, fn (): bool => false);

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('view', ['record' => $permissionReport], tenant: $tenant, panel: 'admin'))
        ->assertForbidden();
});

it('returns 404 for unsupported stored-report families even when the actor is entitled to the tenant', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $unsupported = StoredReport::query()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'report_type' => 'future.report',
        'payload' => ['name' => 'Unexpected'],
    ]);

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('view', ['record' => $unsupported], tenant: $tenant, panel: 'admin'))
        ->assertNotFound();
});

it('returns 404 for same-tenant stored reports outside the active workspace boundary', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    $wrongWorkspace = Workspace::factory()->create();

    $wrongWorkspaceReportId = DB::table('stored_reports')->insertGetId([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $wrongWorkspace->getKey(),
        'report_type' => StoredReport::REPORT_TYPE_PERMISSION_POSTURE,
        'payload' => json_encode(['posture_score' => 1], JSON_THROW_ON_ERROR),
        'fingerprint' => 'permission-wrong-workspace-detail',
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    $this->actingAs($user)
        ->get(StoredReportResource::getUrl('view', ['record' => $wrongWorkspaceReportId], tenant: $tenant, panel: 'admin'))
        ->assertNotFound();
});
