<?php

use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Services\Providers\ProviderOperationStartResult;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\ProviderOperationStartResultPresenter;
use App\Support\ReasonTranslation\NextStepOption;
use App\Support\ReasonTranslation\ReasonResolutionEnvelope;
use Filament\Actions\Action;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('builds queued notifications for accepted provider-backed starts', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $run = OperationRun::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'type' => 'provider.connection.check',
        'status' => 'queued',
        'context' => [
            'provider_connection_id' => 123,
        ],
    ]);

    $presenter = app(ProviderOperationStartResultPresenter::class);

    $notification = $presenter->notification(
        result: ProviderOperationStartResult::started($run, true),
        blockedTitle: 'Verification blocked',
        runUrl: OperationRunLinks::tenantlessView($run),
        extraActions: [
            Action::make('manage_connections')
                ->label('Manage Provider Connections')
                ->url('/provider-connections'),
        ],
    );

    $actions = collect($notification->getActions());

    expect($notification->getTitle())->toBe('Provider connection check queued')
        ->and($notification->getBody())->toBe('Queued for execution. Open the operation for progress and next steps.')
        ->and($actions->map(fn (Action $action): string => (string) $action->getName())->all())->toBe([
            'view_run',
            'manage_connections',
        ])
        ->and($actions->map(fn (Action $action): string => (string) $action->getLabel())->all())->toBe([
            'Open operation',
            'Manage Provider Connections',
        ]);
});

it('builds already-running notifications for deduped provider-backed starts', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $run = OperationRun::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'type' => 'provider.connection.check',
        'status' => 'running',
        'context' => [
            'provider_connection_id' => 123,
        ],
    ]);

    $presenter = app(ProviderOperationStartResultPresenter::class);

    $notification = $presenter->notification(
        result: ProviderOperationStartResult::deduped($run),
        blockedTitle: 'Verification blocked',
        runUrl: OperationRunLinks::tenantlessView($run),
    );

    expect($notification->getTitle())->toBe('Provider connection check already running')
        ->and($notification->getBody())->toBe('A matching operation is already queued or running. Open the operation for progress and next steps.');
});

it('builds scope-busy notifications for conflicting provider-backed starts', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $run = OperationRun::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'type' => 'inventory_sync',
        'status' => 'running',
        'context' => [
            'provider_connection_id' => 123,
        ],
    ]);

    $presenter = app(ProviderOperationStartResultPresenter::class);

    $notification = $presenter->notification(
        result: ProviderOperationStartResult::scopeBusy($run),
        blockedTitle: 'Inventory sync blocked',
        runUrl: OperationRunLinks::tenantlessView($run),
    );

    expect($notification->getTitle())->toBe('Scope busy')
        ->and($notification->getBody())->toBe('Another provider-backed operation is already running for this scope. Open the active operation for progress and next steps.');
});

it('builds blocked notifications from translated reason detail and first next step', function (): void {
    $tenant = ManagedEnvironment::factory()->create();
    $reasonEnvelope = new ReasonResolutionEnvelope(
        internalCode: 'provider_consent_missing',
        operatorLabel: 'Admin consent required',
        shortExplanation: 'Grant admin consent for this provider connection before retrying.',
        actionability: 'prerequisite_missing',
        nextSteps: [
            NextStepOption::link('Grant admin consent', '/provider-connections/1/consent'),
            NextStepOption::link('Open provider settings', '/provider-connections/1'),
        ],
    );
    $run = OperationRun::factory()->create([
        'managed_environment_id' => $tenant->getKey(),
        'type' => 'provider.connection.check',
        'status' => 'completed',
        'outcome' => 'blocked',
        'context' => [
            'reason_code' => 'provider_consent_missing',
            'reason_translation' => $reasonEnvelope->toArray(),
        ],
    ]);

    $presenter = app(ProviderOperationStartResultPresenter::class);

    $notification = $presenter->notification(
        result: ProviderOperationStartResult::blocked($run),
        blockedTitle: 'Verification blocked',
        runUrl: OperationRunLinks::tenantlessView($run),
        extraActions: [
            Action::make('manage_connections')
                ->label('Manage Provider Connections')
                ->url('/provider-connections'),
        ],
    );

    $actions = collect($notification->getActions());

    expect($notification->getTitle())->toBe('Verification blocked')
        ->and($notification->getBody())->toBe("Admin consent required\nGrant admin consent for this provider connection before retrying.\nNext step: Grant admin consent.")
        ->and($actions->map(fn (Action $action): string => (string) $action->getName())->all())->toBe([
            'view_run',
            'next_step_0',
            'manage_connections',
        ])
        ->and($actions->map(fn (Action $action): string => (string) $action->getLabel())->all())->toBe([
            'Open operation',
            'Grant admin consent',
            'Manage Provider Connections',
        ]);
});