<?php

declare(strict_types=1);

use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function createEntraReport(ManagedEnvironment $tenant, array $summaryOverrides = [], ?string $fingerprint = null): StoredReport
{
    $totals = array_merge([
        'roles_total' => 8,
        'assignments_total' => 12,
        'high_privilege_assignments' => 5,
    ], $summaryOverrides);

    return StoredReport::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'report_type' => StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES,
        'fingerprint' => $fingerprint ?? hash('sha256', (string) now()->timestamp.random_int(0, 99999)),
        'payload' => [
            'provider_key' => 'microsoft',
            'domain' => 'entra.admin_roles',
            'measured_at' => now()->toIso8601String(),
            'role_definitions' => [],
            'role_assignments' => [],
            'totals' => $totals,
            'high_privilege' => [
                [
                    'role_display_name' => 'Global Administrator',
                    'role_template_id' => '62e90394-69f5-4237-9190-012177145e10',
                    'principal_id' => 'user-ga-1',
                    'principal_display_name' => 'Admin User',
                    'assignment_scope' => '/',
                    'severity' => 'critical',
                ],
            ],
        ],
    ]);
}

// ---------------------------------------------------------------------------
// StoredReport query by report type
// ---------------------------------------------------------------------------

it('returns stored reports with report_type entra.admin_roles', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $report = createEntraReport($tenant);

    // Also create a report of a different type to ensure filtering works
    StoredReport::query()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'managed_environment_id' => (int) $tenant->getKey(),
        'report_type' => 'permission_posture',
        'fingerprint' => hash('sha256', 'other-report'),
        'payload' => ['summary' => ['score' => 85]],
    ]);

    $results = StoredReport::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('report_type', StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES)
        ->get();

    expect($results)
        ->toHaveCount(1)
        ->and((int) $results->first()->getKey())->toBe((int) $report->getKey());
});

// ---------------------------------------------------------------------------
// Report payload contains summary and high-privilege assignments table
// ---------------------------------------------------------------------------

it('report payload contains summary totals and high-privilege assignments', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $report = createEntraReport($tenant, [
        'roles_total' => 10,
        'assignments_total' => 20,
        'high_privilege_assignments' => 8,
    ]);

    $report->refresh();
    $payload = $report->payload;

    expect($payload)
        ->toBeArray()
        ->toHaveKey('totals')
        ->toHaveKey('high_privilege');

    $totals = $payload['totals'];
    expect($totals)
        ->toHaveKey('roles_total', 10)
        ->toHaveKey('assignments_total', 20)
        ->toHaveKey('high_privilege_assignments', 8);

    $assignments = $payload['high_privilege'];
    expect($assignments)
        ->toBeArray()
        ->toHaveCount(1);

    expect($assignments[0])
        ->toHaveKey('role_display_name', 'Global Administrator')
        ->toHaveKey('severity', 'critical')
        ->toHaveKey('principal_display_name', 'Admin User');
});

// ---------------------------------------------------------------------------
// Multiple reports ordered by creation date descending
// ---------------------------------------------------------------------------

it('orders multiple reports by creation date descending', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $older = createEntraReport($tenant, ['high_privilege_assignments' => 3], 'fp-older');
    $older->forceFill(['created_at' => now()->subHours(2)])->save();

    $newer = createEntraReport($tenant, ['high_privilege_assignments' => 7], 'fp-newer');
    $newer->forceFill(['created_at' => now()->subHour()])->save();

    $latest = createEntraReport($tenant, ['high_privilege_assignments' => 1], 'fp-latest');

    $results = StoredReport::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('report_type', StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES)
        ->orderByDesc('created_at')
        ->get();

    expect($results)->toHaveCount(3);
    expect((int) $results[0]->getKey())->toBe((int) $latest->getKey());
    expect((int) $results[1]->getKey())->toBe((int) $newer->getKey());
    expect((int) $results[2]->getKey())->toBe((int) $older->getKey());
});
