<?php

declare(strict_types=1);

use App\Filament\Resources\ManagedEnvironmentResource;
use App\Filament\Resources\ManagedEnvironmentResource\Pages\ViewManagedEnvironment;
use App\Models\AuditLog;
use App\Models\ManagedEnvironment;
use App\Support\Rbac\UiTooltips;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

describe('ManagedEnvironment View header action UI enforcement', function () {
    it('keeps archive visible in the workflow header and moves edit/provider navigation into contextual unavailable entries for readonly members', function () {
        [$user, $tenant] = createUserWithTenant(role: 'readonly');

        $this->actingAs($user);

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

        Livewire::test(ViewManagedEnvironment::class, ['record' => $tenant->getRouteKey()])
            ->assertActionVisible('archive')
            ->assertActionDisabled('archive')
            ->assertActionExists('archive', function (Action $action): bool {
                return $action->getTooltip() === UiTooltips::INSUFFICIENT_PERMISSION;
            });

        $contextEntries = collect(ManagedEnvironmentResource::tenantViewContextEntries($tenant))->keyBy('key');

        expect($contextEntries->get('tenant_edit')['availability'] ?? null)->toBe('authorization_denied')
            ->and($contextEntries->get('provider_connections')['availability'] ?? null)->toBe('available');
    });

    it('keeps archive enabled for owner members and exposes edit/provider navigation in contextual related content', function () {
        [$user, $tenant] = createUserWithTenant(role: 'owner');

        $this->actingAs($user);

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

        Livewire::test(ViewManagedEnvironment::class, ['record' => $tenant->getRouteKey()])
            ->assertActionVisible('archive')
            ->assertActionEnabled('archive');

        $contextEntries = collect(ManagedEnvironmentResource::tenantViewContextEntries($tenant))->keyBy('key');

        expect($contextEntries->get('tenant_edit')['availability'] ?? null)->toBe('available')
            ->and($contextEntries->get('provider_connections')['availability'] ?? null)->toBe('available');
    });

    it('does not execute the archive action for readonly members (silently blocked by Filament)', function () {
        [$user, $tenant] = createUserWithTenant(role: 'readonly');

        $this->actingAs($user);

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

        Livewire::test(ViewManagedEnvironment::class, ['record' => $tenant->getRouteKey()])
            ->assertActionDisabled('archive')
            ->mountAction('archive')
            ->setActionData([
                'archive_reason' => 'Readonly users should not be able to archive tenants.',
            ])
            ->callMountedAction()
            ->assertSuccessful();

        expect(ManagedEnvironment::withTrashed()->find($tenant->getKey())?->trashed())->toBeFalse();
    });

    it('shows resume onboarding when the tenant has a resumable linked onboarding draft', function () {
        $tenant = ManagedEnvironment::factory()->onboarding()->create();
        [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

        createOnboardingDraft([
            'workspace' => $tenant->workspace,
            'tenant' => $tenant,
            'started_by' => $user,
            'updated_by' => $user,
            'state' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
                'tenant_name' => (string) $tenant->name,
            ],
        ]);

        $this->actingAs($user);
        Filament::setTenant(null, true);

        expect(collect(ManagedEnvironmentResource::tenantViewContextEntries($tenant))
            ->firstWhere('key', 'related_onboarding')['value'] ?? null)
            ->toBe('Resume onboarding');
    });

    it('shows a cancelled-onboarding label and repairs stale onboarding tenant status when the linked draft was cancelled', function () {
        $tenant = ManagedEnvironment::factory()->onboarding()->create([
            'name' => 'Cancelled Flow ManagedEnvironment',
        ]);
        [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner', ensureDefaultMicrosoftProviderConnection: false);

        $draft = createOnboardingDraft([
            'workspace' => $tenant->workspace,
            'tenant' => $tenant,
            'started_by' => $user,
            'updated_by' => $user,
            'status' => 'cancelled',
            'state' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
                'tenant_name' => (string) $tenant->name,
            ],
        ]);

        $this->actingAs($user);
        Filament::setTenant(null, true);

        $this->get(route('admin.onboarding.draft', ['onboardingDraft' => (int) $draft->getKey()]))
            ->assertSuccessful()
            ->assertSee('This onboarding draft is Cancelled.');

        $tenant->refresh();

        expect($tenant->status)->toBe(ManagedEnvironment::STATUS_DRAFT);
        expect(AuditLog::query()
            ->where('workspace_id', (int) $tenant->workspace_id)
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->where('action', \App\Support\Audit\AuditActionId::TenantReturnedToDraft->value)
            ->exists())->toBeTrue();

        expect(collect(ManagedEnvironmentResource::tenantViewContextEntries($tenant))
            ->firstWhere('key', 'related_onboarding')['value'] ?? null)
            ->toBe('View cancelled onboarding draft');
    });
});
