<?php

declare(strict_types=1);

use App\Models\OperationRun;
use App\Models\ProviderConnection;
use App\Models\ManagedEnvironment;
use App\Services\Verification\StartVerification;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Support\Facades\Queue;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

it('returns 404 for non-members on verification view and start', function (): void {
    Queue::fake();

    $tenant = ManagedEnvironment::factory()->create();
    $otherTenant = ManagedEnvironment::factory()->create();

    [$user] = createUserWithTenant($otherTenant, role: 'readonly');

    $run = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'provider.connection.check',
        'status' => 'completed',
        'outcome' => 'failed',
        'context' => [
            'verification_report' => json_decode(
                (string) file_get_contents(repo_path('specs/074-verification-checklist/contracts/examples/fail.json')),
                true,
                512,
                JSON_THROW_ON_ERROR,
            ),
        ],
    ]);

    $this->actingAs($user)
        ->get(route('admin.operations.view', [
            'workspace' => (int) $tenant->workspace_id,
            'run' => (int) $run->getKey(),
        ]))
        ->assertStatus(404);

    $connection = ProviderConnection::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
    ]);

    expect(fn () => app(StartVerification::class)->providerConnectionCheck(
        tenant: $tenant,
        connection: $connection,
        initiator: $user,
    ))->toThrow(NotFoundHttpException::class);
});

it('allows readonly members to view verification reports but forbids starting verification', function (): void {
    Queue::fake();

    [$user, $tenant] = createUserWithTenant(role: 'readonly');

    $run = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'type' => 'provider.connection.check',
        'status' => 'completed',
        'outcome' => 'failed',
        'context' => [
            'verification_report' => json_decode(
                (string) file_get_contents(repo_path('specs/074-verification-checklist/contracts/examples/fail.json')),
                true,
                512,
                JSON_THROW_ON_ERROR,
            ),
        ],
    ]);

    $this->actingAs($user)
        ->get(route('admin.operations.view', [
            'workspace' => (int) $tenant->workspace_id,
            'run' => (int) $run->getKey(),
        ]))
        ->assertOk()
        ->assertSee('Verification report');

    $connection = ProviderConnection::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
    ]);

    expect(fn () => app(StartVerification::class)->providerConnectionCheck(
        tenant: $tenant,
        connection: $connection,
        initiator: $user,
    ))->toThrow(AuthorizationException::class);
});

it('allows members with start capability to start verification', function (): void {
    Queue::fake();

    [$user, $tenant] = createUserWithTenant(role: 'operator', fixtureProfile: 'credential-enabled');

    $connection = ProviderConnection::query()
        ->where('managed_environment_id', (int) $tenant->getKey())
        ->where('provider', 'microsoft')
        ->where('is_default', true)
        ->firstOrFail();

    $result = app(StartVerification::class)->providerConnectionCheck(
        tenant: $tenant,
        connection: $connection,
        initiator: $user,
    );

    expect($result->status)->toBe('started');
    expect($result->run->type)->toBe('provider.connection.check');
    expect($result->run->managed_environment_id)->toBe((int) $tenant->getKey());
    expect($result->run->context)->toMatchArray([
        'provider_connection_id' => (int) $connection->getKey(),
    ]);
});
