<?php

declare(strict_types=1);

use App\Filament\System\Pages\Directory\ViewWorkspace;
use App\Models\AuditLog;
use App\Models\PlatformUser;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Models\WorkspaceSetting;
use App\Models\WorkspaceSubscription;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Settings\SettingsWriter;
use App\Support\Audit\AuditActionId;
use App\Support\Auth\PlatformCapabilities;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Livewire\Livewire;

beforeEach(function (): void {
    Filament::setCurrentPanel('system');
    Filament::bootCurrentPanel();
});

it('renders the read-only workspace entitlement summary on the system workspace detail page', function (): void {
    $workspace = Workspace::factory()->create(['name' => 'Acme Workspace']);
    $manager = User::factory()->create(['name' => 'Workspace Manager']);

    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'user_id' => (int) $manager->getKey(),
        'role' => 'manager',
    ]);

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

    $writer = app(SettingsWriter::class);
    $writer->updateWorkspaceSetting(
        actor: $manager,
        workspace: $workspace,
        domain: 'entitlements',
        key: 'plan_profile',
        value: 'starter',
    );
    $writer->updateWorkspaceSetting(
        actor: $manager,
        workspace: $workspace,
        domain: 'entitlements',
        key: 'managed_tenant_limit_override_value',
        value: 2,
    );
    $writer->updateWorkspaceSetting(
        actor: $manager,
        workspace: $workspace,
        domain: 'entitlements',
        key: 'managed_tenant_limit_override_reason',
        value: 'Pilot workspace',
    );
    $writer->updateWorkspaceSetting(
        actor: $manager,
        workspace: $workspace,
        domain: 'entitlements',
        key: 'review_pack_generation_override_value',
        value: false,
    );
    $writer->updateWorkspaceSetting(
        actor: $manager,
        workspace: $workspace,
        domain: 'entitlements',
        key: 'review_pack_generation_override_reason',
        value: 'Escalation only',
    );

    $platformUser = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
        ],
        'is_active' => true,
    ]);

    $this->actingAs($platformUser, 'platform')
        ->get(ViewWorkspace::getUrl(panel: 'system', parameters: ['workspace' => $workspace]))
        ->assertSuccessful()
        ->assertSee('Workspace entitlements')
        ->assertSee('Starter')
        ->assertSee('Pilot workspace')
        ->assertSee('Escalation only')
        ->assertSee('workspace override')
        ->assertSee('Commercial lifecycle')
        ->assertSee('Active paid')
        ->assertSee('default active paid')
        ->assertDontSee('Save');
});

it('gates the commercial lifecycle mutation action behind a dedicated platform capability', function (): void {
    $workspace = Workspace::factory()->create();

    $viewer = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($viewer, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionHidden('change_commercial_state');
});

it('changes commercial lifecycle state through the confirmed system action and records audit truth', function (): void {
    $workspace = Workspace::factory()->create(['name' => 'Lifecycle Workspace']);
    $operator = PlatformUser::factory()->create([
        'name' => 'Platform Operator',
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionVisible('change_commercial_state')
        ->assertActionExists('change_commercial_state', fn (Action $action): bool => $action->getLabel() === 'Change commercial state'
            && $action->isConfirmationRequired())
        ->callAction('change_commercial_state', data: [
            'state' => WorkspaceCommercialLifecycleResolver::STATE_SUSPENDED_READ_ONLY,
            'reason' => 'Commercial suspension approved by support',
        ])
        ->assertNotified('Commercial state updated');

    expect(WorkspaceSetting::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('domain', WorkspaceCommercialLifecycleResolver::SETTING_DOMAIN)
        ->where('key', WorkspaceCommercialLifecycleResolver::SETTING_COMMERCIAL_LIFECYCLE_STATE)
        ->value('value'))->toBe(WorkspaceCommercialLifecycleResolver::STATE_SUSPENDED_READ_ONLY)
        ->and(WorkspaceSetting::query()
            ->where('workspace_id', (int) $workspace->getKey())
            ->where('domain', WorkspaceCommercialLifecycleResolver::SETTING_DOMAIN)
            ->where('key', WorkspaceCommercialLifecycleResolver::SETTING_COMMERCIAL_LIFECYCLE_REASON)
            ->value('value'))->toBe('Commercial suspension approved by support');

    $audit = AuditLog::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->where('action', AuditActionId::WorkspaceSettingUpdated->value)
        ->where('resource_id', WorkspaceCommercialLifecycleResolver::SETTING_DOMAIN.'.'.WorkspaceCommercialLifecycleResolver::SETTING_COMMERCIAL_LIFECYCLE_STATE)
        ->latest('id')
        ->first();

    expect($audit)->not->toBeNull()
        ->and($audit?->actor_name)->toBe('Platform Operator')
        ->and($audit?->metadata['before_state'] ?? null)->toBeNull()
        ->and($audit?->metadata['after_state'] ?? null)->toBe(WorkspaceCommercialLifecycleResolver::STATE_SUSPENDED_READ_ONLY)
        ->and($audit?->metadata['after_reason'] ?? null)->toBe('Commercial suspension approved by support');

    $summary = app(WorkspaceCommercialLifecycleResolver::class)->summary($workspace);

    expect($summary)
        ->toMatchArray([
            'state' => WorkspaceCommercialLifecycleResolver::STATE_SUSPENDED_READ_ONLY,
            'source' => WorkspaceCommercialLifecycleResolver::SOURCE_WORKSPACE_SETTING,
            'rationale' => 'Commercial suspension approved by support',
            'last_changed_by' => 'Platform Operator',
        ]);
});

it('requires a rationale before changing commercial lifecycle state', function (): void {
    $workspace = Workspace::factory()->create();
    $operator = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->callAction('change_commercial_state', data: [
            'state' => WorkspaceCommercialLifecycleResolver::STATE_GRACE,
            'reason' => '',
        ])
        ->assertHasActionErrors(['reason']);
});

it('creates subscription truth through the confirmed system action and renders subscription-backed detail', function (): void {
    $workspace = Workspace::factory()->create(['name' => 'Subscription Workspace']);
    $operator = PlatformUser::factory()->create([
        'name' => 'Platform Operator',
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
        ],
        'is_active' => true,
    ]);
    $trialEndsAt = now()->addDays(14)->startOfMinute();

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionVisible('update_subscription_truth')
        ->assertActionExists('update_subscription_truth', fn (Action $action): bool => $action->getLabel() === 'Update subscription truth'
            && $action->isConfirmationRequired())
        ->callAction('update_subscription_truth', data: [
            'state' => 'trial',
            'billing_reference' => 'sub_trial_001',
            'trial_ends_at' => $trialEndsAt->toDateTimeString(),
            'current_period_starts_at' => null,
            'current_period_ends_at' => null,
            'status_reason' => 'Trial access for onboarding.',
        ])
        ->assertNotified('Subscription truth updated');

    $subscription = WorkspaceSubscription::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->first();

    expect($subscription)
        ->not->toBeNull()
        ->and($subscription?->state)->toBe('trial')
        ->and($subscription?->billing_reference)->toBe('sub_trial_001')
        ->and($subscription?->status_reason)->toBe('Trial access for onboarding.');

    $summary = app(WorkspaceCommercialLifecycleResolver::class)->summary($workspace->fresh());

    expect($summary)
        ->toMatchArray([
            'source' => WorkspaceCommercialLifecycleResolver::SOURCE_WORKSPACE_SUBSCRIPTION,
            'subscription_present' => true,
            'subscription_state' => 'trial',
            'subscription_state_label' => 'Trial',
            'state' => WorkspaceCommercialLifecycleResolver::STATE_TRIAL,
        ]);

    $this->actingAs($operator, 'platform')
        ->get(ViewWorkspace::getUrl(panel: 'system', parameters: ['workspace' => $workspace]))
        ->assertSuccessful()
        ->assertSee('Workspace subscription')
        ->assertSee('subscription-backed')
        ->assertSee('Trial access for onboarding.')
        ->assertSee('sub_trial_001')
        ->assertSee('Trial ends');
});

it('requires a trial end date before changing subscription truth to trial', function (): void {
    $workspace = Workspace::factory()->create(['name' => 'Trial Validation Workspace']);
    $operator = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->callAction('update_subscription_truth', data: [
            'state' => 'trial',
            'billing_reference' => 'sub_trial_missing_date',
            'trial_ends_at' => null,
            'current_period_starts_at' => null,
            'current_period_ends_at' => null,
            'status_reason' => 'Trial access needs an explicit end date.',
        ])
        ->assertHasActionErrors(['trial_ends_at']);

    expect(WorkspaceSubscription::query()
        ->where('workspace_id', (int) $workspace->getKey())
        ->exists())->toBeFalse();
});

it('keeps manual lifecycle fallback controls only for fallback-backed workspaces', function (): void {
    $workspace = Workspace::factory()->create();
    $operator = PlatformUser::factory()->create([
        'capabilities' => [
            PlatformCapabilities::ACCESS_SYSTEM_PANEL,
            PlatformCapabilities::DIRECTORY_VIEW,
            PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE,
        ],
        'is_active' => true,
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace])
        ->assertActionVisible('update_subscription_truth')
        ->assertActionVisible('change_commercial_state');

    WorkspaceSubscription::factory()->create([
        'workspace_id' => (int) $workspace->getKey(),
        'state' => 'active',
        'current_period_starts_at' => now()->subDay(),
        'current_period_ends_at' => now()->addDays(29),
        'status_reason' => 'Annual plan is current.',
    ]);

    Livewire::actingAs($operator, 'platform')
        ->test(ViewWorkspace::class, ['workspace' => $workspace->fresh()])
        ->assertActionVisible('update_subscription_truth')
        ->assertActionHidden('change_commercial_state');
});
