<?php

declare(strict_types=1);

use App\Filament\Pages\Workspaces\ManagedEnvironmentOnboardingWizard;
use App\Models\AuditLog;
use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentOnboardingSession;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\ProviderConnection;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Entitlements\WorkspaceEntitlementResolver;
use App\Services\Settings\SettingsWriter;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;

/**
 * @return array{workspace: Workspace, user: User, tenant: ManagedEnvironment, draft: ManagedEnvironmentOnboardingSession, component: \Livewire\Features\SupportTesting\Testable}
 */
function readyOnboardingEntitlementContext(
    int $activeEnvironmentCount = 0,
    ?int $limitOverride = null,
    ?string $overrideReason = null,
    ?string $commercialState = null,
    ?array $subscription = null,
): array {
    Queue::fake();

    $workspace = Workspace::factory()->create();
    $user = User::factory()->create();

    $tenant = ManagedEnvironment::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'status' => ManagedEnvironment::STATUS_ONBOARDING,
    ]);

    createUserWithTenant(
        tenant: $tenant,
        user: $user,
        role: 'owner',
        workspaceRole: 'owner',
        ensureDefaultMicrosoftProviderConnection: false,
    );

    if ($activeEnvironmentCount > 0) {
        ManagedEnvironment::factory()->count($activeEnvironmentCount)->create([
            'workspace_id' => (int) $workspace->getKey(),
            'status' => ManagedEnvironment::STATUS_ACTIVE,
        ]);
    }

    $connection = ProviderConnection::factory()->platform()->consentGranted()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'managed_environment_id' => (int) $tenant->getKey(),
        'provider' => 'microsoft',
        'entra_tenant_id' => (string) $tenant->managed_environment_id,
        'display_name' => 'Ready connection',
        'is_default' => true,
        'consent_status' => 'granted',
    ]);

    $run = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $user->getKey(),
        'type' => 'provider.connection.check',
        'status' => OperationRunStatus::Completed->value,
        'outcome' => OperationRunOutcome::Succeeded->value,
        'context' => [
            'provider' => 'microsoft',
            'module' => 'health_check',
            'provider_connection_id' => (int) $connection->getKey(),
            'target_scope' => [
                'entra_tenant_id' => (string) $tenant->managed_environment_id,
            ],
        ],
    ]);

    $draft = createOnboardingDraft([
        'workspace' => $workspace,
        'tenant' => $tenant,
        'started_by' => $user,
        'updated_by' => $user,
        'current_step' => 'bootstrap',
        'state' => [
            'entra_tenant_id' => (string) $tenant->managed_environment_id,
            'environment_name' => (string) $tenant->name,
            'provider_connection_id' => (int) $connection->getKey(),
            'verification_operation_run_id' => (int) $run->getKey(),
        ],
    ]);

    if ($limitOverride !== null) {
        $writer = app(SettingsWriter::class);
        $writer->updateWorkspaceSetting(
            actor: $user,
            workspace: $workspace,
            domain: WorkspaceEntitlementResolver::SETTING_DOMAIN,
            key: WorkspaceEntitlementResolver::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_VALUE,
            value: $limitOverride,
        );

        if ($overrideReason !== null) {
            $writer->updateWorkspaceSetting(
                actor: $user,
                workspace: $workspace,
                domain: WorkspaceEntitlementResolver::SETTING_DOMAIN,
                key: WorkspaceEntitlementResolver::SETTING_MANAGED_TENANT_LIMIT_OVERRIDE_REASON,
                value: $overrideReason,
            );
        }
    }

    if ($commercialState !== null) {
        app(SettingsWriter::class)->updateWorkspaceCommercialLifecycle(
            actor: PlatformUser::factory()->create([
                'capabilities' => [
                    PlatformCapabilities::ACCESS_SYSTEM_PANEL,
                    PlatformCapabilities::DIRECTORY_VIEW,
                    PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
                ],
                'is_active' => true,
            ]),
            workspace: $workspace,
            state: $commercialState,
            reason: 'Onboarding entitlement test commercial state',
        );
    }

    if (is_array($subscription)) {
        app(SettingsWriter::class)->updateWorkspaceSubscription(
            actor: PlatformUser::factory()->create([
                'capabilities' => [
                    PlatformCapabilities::ACCESS_SYSTEM_PANEL,
                    PlatformCapabilities::DIRECTORY_VIEW,
                    PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
                ],
                'is_active' => true,
            ]),
            workspace: $workspace,
            attributes: $subscription,
        );
    }

    session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());

    $component = Livewire::actingAs($user)->test(ManagedEnvironmentOnboardingWizard::class, [
        'onboardingDraft' => (int) $draft->getKey(),
    ]);

    return compact('workspace', 'user', 'tenant', 'draft', 'component');
}

it('allows onboarding activation when the workspace is within its managed environment limit', function (): void {
    $context = readyOnboardingEntitlementContext(activeEnvironmentCount: 0);

    $context['component']->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ACTIVE)
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $context['workspace']->getKey())
            ->where('action', 'managed_environment_onboarding.activation')
            ->exists())->toBeTrue();
});

it('blocks onboarding activation with a business-state reason when the workspace is at limit', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 1,
        limitOverride: 1,
        overrideReason: 'Customer currently allows one active tenant',
    );

    $decision = app(WorkspaceEntitlementResolver::class)->resolve(
        $context['workspace'],
        WorkspaceEntitlementResolver::KEY_MANAGED_TENANT_ACTIVATION_LIMIT,
    );

    expect($decision['is_blocked'])->toBeTrue();

    $context['component']
        ->assertSee('Activation entitlement')
        ->assertSee('Blocked')
        ->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ONBOARDING)
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $context['workspace']->getKey())
            ->where('action', 'managed_environment_onboarding.activation')
            ->exists())->toBeFalse();
});

it('allows onboarding activation when a workspace override raises the limit above current usage', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 1,
        limitOverride: 2,
        overrideReason: 'Temporary support-approved exception',
    );

    $decision = app(WorkspaceEntitlementResolver::class)->resolve(
        $context['workspace'],
        WorkspaceEntitlementResolver::KEY_MANAGED_TENANT_ACTIVATION_LIMIT,
    );

    expect($decision)
        ->toMatchArray([
            'source' => 'workspace_override',
            'effective_value' => 2,
            'current_usage' => 1,
            'is_blocked' => false,
            'rationale' => 'Temporary support-approved exception',
        ]);

    $context['component']->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ACTIVE);
});

it('allows onboarding activation while a workspace is in trial', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 0,
        commercialState: WorkspaceCommercialLifecycleResolver::STATE_TRIAL,
    );

    $context['component']
        ->assertSee('Activation entitlement')
        ->assertSee('Trial')
        ->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ACTIVE)
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $context['workspace']->getKey())
            ->where('action', 'managed_environment_onboarding.activation')
            ->exists())->toBeTrue();
});

it('identifies subscription-backed commercial posture on the onboarding completion step', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 0,
        subscription: [
            'state' => 'trial',
            'billing_reference' => 'sub_trial_001',
            'trial_ends_at' => now()->addDays(14)->startOfMinute()->toDateTimeString(),
            'status_reason' => 'Trial access for onboarding.',
        ],
    );

    $context['component']
        ->assertSee('Activation entitlement')
        ->assertSee('Trial')
        ->assertSee('subscription-backed')
        ->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ACTIVE);
});

it('blocks onboarding activation with a grace commercial-state reason before tenant mutation', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 0,
        commercialState: WorkspaceCommercialLifecycleResolver::STATE_GRACE,
    );

    $context['component']
        ->assertSee('Activation entitlement')
        ->assertSee('Grace')
        ->assertSee('fallback-backed')
        ->assertSee('New managed-tenant activation is frozen while this workspace is in grace.')
        ->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ONBOARDING)
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $context['workspace']->getKey())
            ->where('action', 'managed_environment_onboarding.activation')
            ->exists())->toBeFalse();
});

it('blocks onboarding activation with a suspended read-only commercial-state reason before tenant mutation', function (): void {
    $context = readyOnboardingEntitlementContext(
        activeEnvironmentCount: 0,
        commercialState: WorkspaceCommercialLifecycleResolver::STATE_SUSPENDED_READ_ONLY,
    );

    $context['component']
        ->assertSee('Activation entitlement')
        ->assertSee('Suspended / read-only')
        ->assertSee('This workspace is suspended / read-only. New managed-tenant activation is blocked')
        ->call('completeOnboarding');

    $context['tenant']->refresh();

    expect($context['tenant']->status)->toBe(ManagedEnvironment::STATUS_ONBOARDING)
        ->and(AuditLog::query()
            ->where('workspace_id', (int) $context['workspace']->getKey())
            ->where('action', 'managed_environment_onboarding.activation')
            ->exists())->toBeFalse();
});
