<?php

use App\Filament\Resources\EntraGroupResource\Pages\ListEntraGroups;
use App\Jobs\EntraGroupSyncJob;
use App\Jobs\SyncRoleDefinitionsJob;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Services\Directory\RoleDefinitionsSyncService;
use App\Services\Graph\GraphClientInterface;
use App\Support\Providers\ProviderReasonCodes;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;

uses(RefreshDatabase::class);

it('starts directory group sync with explicit provider connection context', function (): void {
    Queue::fake();

    $this->mock(GraphClientInterface::class, function ($mock): void {
        $mock->shouldReceive('listPolicies')->never();
        $mock->shouldReceive('getPolicy')->never();
        $mock->shouldReceive('getOrganization')->never();
        $mock->shouldReceive('applyPolicy')->never();
        $mock->shouldReceive('getServicePrincipalPermissions')->never();
        $mock->shouldReceive('request')->never();
    });

    [$user, $tenant] = createUserWithTenant(role: 'owner', fixtureProfile: 'credential-enabled');
    spec283SeedRequirementRows($tenant, ['permissions.directory_groups']);
    $this->actingAs($user);

    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    Livewire::test(ListEntraGroups::class)
        ->callAction('sync_groups');

    $run = OperationRun::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('type', 'directory.groups.sync')
        ->latest('id')
        ->first();

    expect($run)->not->toBeNull();
    expect($run?->status)->toBe('queued');
    expect($run?->context['provider_connection_id'] ?? null)->toBeInt();

    Queue::assertPushed(EntraGroupSyncJob::class, function (EntraGroupSyncJob $job) use ($run): bool {
        return $job->providerConnectionId === ($run?->context['provider_connection_id'] ?? null)
            && $job->operationRun?->is($run);
    });
});

it('blocks role definitions sync before queue when no provider connection is available', function (): void {
    Bus::fake();

    $tenant = ManagedEnvironment::factory()->create([
        'app_client_id' => 'client-123',
        'app_client_secret' => 'secret',
        'status' => 'active',
    ]);

    [$user, $tenant] = createUserWithTenant(
        tenant: $tenant,
        role: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    $result = app(RoleDefinitionsSyncService::class)->startManualSync($tenant, $user);

    expect($result->status)->toBe('blocked');
    expect($result->run->context['reason_code'] ?? null)->toBe(ProviderReasonCodes::ProviderConnectionMissing);

    Bus::assertNotDispatched(SyncRoleDefinitionsJob::class);
});
