<?php

namespace App\Filament\Resources;

use App\Exceptions\Entitlements\WorkspaceEntitlementBlockedException;
use App\Exceptions\ReviewPackEvidenceResolutionException;
use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Filament\Concerns\WorkspaceScopedEnvironmentRoutes;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Resources\EvidenceSnapshotResource as TenantEvidenceSnapshotResource;
use App\Filament\Resources\ReviewPackResource\Pages;
use App\Models\ManagedEnvironment;
use App\Models\ReviewPack;
use App\Models\User;
use App\Services\ReviewPackService;
use App\Support\Auth\Capabilities;
use App\Support\Auth\UiTooltips as AuthUiTooltips;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Navigation\NavigationScope;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\Rbac\UiEnforcement;
use App\Support\ReviewPackStatus;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthEnvelope;
use App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter;
use App\Support\Ui\GovernanceArtifactTruth\CompressedGovernanceOutcome;
use App\Support\Ui\GovernanceArtifactTruth\SurfaceCompressionContext;
use BackedEnum;
use Filament\Actions;
use Filament\Forms\Components\Toggle;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Number;
use UnitEnum;

class ReviewPackResource extends Resource
{
    use ResolvesPanelTenantContext;
    use WorkspaceScopedEnvironmentRoutes;

    protected static ?string $model = ReviewPack::class;

    protected static ?string $tenantOwnershipRelationshipName = 'tenant';

    protected static bool $isGloballySearchable = false;

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-document-arrow-down';

    protected static string|UnitEnum|null $navigationGroup = 'Reporting';

    protected static ?string $navigationLabel = 'Review Packs';

    protected static ?int $navigationSort = 50;

    public static function shouldRegisterNavigation(): bool
    {
        return NavigationScope::shouldRegisterEnvironmentNavigation()
            && parent::shouldRegisterNavigation();
    }

    public static function canViewAny(): bool
    {
        $tenant = static::resolveTenantContextForCurrentPanel();
        $user = auth()->user();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User) {
            return false;
        }

        if (! $user->canAccessTenant($tenant)) {
            return false;
        }

        return $user->can(Capabilities::REVIEW_PACK_VIEW, $tenant);
    }

    public static function canView(Model $record): bool
    {
        $tenant = static::resolveTenantContextForCurrentPanel();
        $user = auth()->user();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User) {
            return false;
        }

        if (! $user->canAccessTenant($tenant)) {
            return false;
        }

        if (! $user->can(Capabilities::REVIEW_PACK_VIEW, $tenant)) {
            return false;
        }

        if ($record instanceof ReviewPack) {
            return (int) $record->managed_environment_id === (int) $tenant->getKey();
        }

        return true;
    }

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::CrudListAndView, ActionSurfaceType::ReadOnlyRegistryReport)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Generate Pack action appears in the list header once review packs exist.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'Empty state carries the single Generate CTA while the registry is empty.')
            ->satisfy(ActionSurfaceSlot::ListRowMoreMenu, 'Clickable-row inspection stays primary while Download remains the only direct row shortcut and Expire is grouped under More.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'No bulk operations are supported for review packs.')
            ->satisfy(ActionSurfaceSlot::DetailHeader, 'Download and Regenerate actions in ViewReviewPack header.');
    }

    public static function form(Schema $schema): Schema
    {
        return $schema;
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('Outcome summary')
                    ->schema([
                        ViewEntry::make('artifact_truth')
                            ->hiddenLabel()
                            ->view('filament.infolists.entries.governance-artifact-truth')
                            ->state(fn (ReviewPack $record): array => static::truthState($record))
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
                Section::make('Status')
                    ->schema([
                        TextEntry::make('status')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::ReviewPackStatus))
                            ->color(BadgeRenderer::color(BadgeDomain::ReviewPackStatus))
                            ->icon(BadgeRenderer::icon(BadgeDomain::ReviewPackStatus))
                            ->iconColor(BadgeRenderer::iconColor(BadgeDomain::ReviewPackStatus)),
                        TextEntry::make('tenant.name')->label('ManagedEnvironment'),
                        TextEntry::make('generated_at')->dateTime()->placeholder('—'),
                        TextEntry::make('expires_at')->dateTime()->placeholder('—'),
                        TextEntry::make('file_size')
                            ->label('File size')
                            ->formatStateUsing(fn ($state): string => $state ? Number::fileSize((int) $state) : '—'),
                        TextEntry::make('sha256')->label('SHA-256')->copyable()->placeholder('—')
                            ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),

                Section::make('Summary')
                    ->schema([
                        TextEntry::make('summary.finding_count')->label('Findings')->placeholder('—'),
                        TextEntry::make('summary.report_count')->label('Reports')->placeholder('—'),
                        TextEntry::make('summary.operation_count')->label('Operations')->placeholder('—'),
                        TextEntry::make('summary.data_freshness.permission_posture')
                            ->label('Permission posture freshness')
                            ->placeholder('—'),
                        TextEntry::make('summary.data_freshness.entra_admin_roles')
                            ->label('Entra admin roles freshness')
                            ->placeholder('—'),
                        TextEntry::make('summary.data_freshness.findings')
                            ->label('Findings freshness')
                            ->placeholder('—'),
                        TextEntry::make('summary.data_freshness.hardening')
                            ->label('Hardening freshness')
                            ->placeholder('—'),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),

                Section::make('Options')
                    ->schema([
                        TextEntry::make('options.include_pii')
                            ->label('Include PII')
                            ->formatStateUsing(fn ($state): string => $state ? 'Yes' : 'No'),
                        TextEntry::make('options.include_operations')
                            ->label('Include operations')
                            ->formatStateUsing(fn ($state): string => $state ? 'Yes' : 'No'),
                    ])
                    ->columns(2)
                    ->hidden(fn (): bool => static::isCustomerWorkspaceFlow())
                    ->columnSpanFull(),

                Section::make('Metadata')
                    ->schema([
                        TextEntry::make('initiator.name')->label('Initiated by')->placeholder('—'),
                        TextEntry::make('environmentReview.id')
                            ->label('ManagedEnvironment review')
                            ->formatStateUsing(fn (?int $state): string => $state ? '#'.$state : '—')
                            ->url(fn (ReviewPack $record): ?string => $record->environmentReview && $record->tenant
                                ? EnvironmentReviewResource::environmentScopedUrl('view', ['record' => $record->environmentReview], $record->tenant)
                                : null)
                            ->placeholder('—'),
                        TextEntry::make('customer_workspace')
                            ->label('Customer workspace')
                            ->state(fn (): string => 'Open workspace')
                            ->url(fn (ReviewPack $record): ?string => $record->tenant instanceof ManagedEnvironment
                                ? CustomerReviewWorkspace::environmentFilterUrl($record->tenant)
                                : null)
                            ->placeholder('—'),
                        TextEntry::make('summary.review_status')
                            ->label('Review status')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EnvironmentReviewStatus))
                            ->color(BadgeRenderer::color(BadgeDomain::EnvironmentReviewStatus))
                            ->icon(BadgeRenderer::icon(BadgeDomain::EnvironmentReviewStatus))
                            ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EnvironmentReviewStatus))
                            ->placeholder('—'),
                        TextEntry::make('operationRun.id')
                            ->label('Operation')
                            ->url(function (ReviewPack $record): ?string {
                                if (! $record->operation_run_id) {
                                    return null;
                                }

                                $tenant = $record->tenant;

                                if ($tenant instanceof ManagedEnvironment) {
                                    return OperationRunLinks::view((int) $record->operation_run_id, $tenant);
                                }

                                return OperationRunLinks::tenantlessView((int) $record->operation_run_id);
                            })
                            ->openUrlInNewTab()
                            ->hidden(fn (): bool => static::isCustomerWorkspaceFlow())
                            ->placeholder('—'),
                        TextEntry::make('fingerprint')->label('Fingerprint')->copyable()->placeholder('—')
                            ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                        TextEntry::make('previous_fingerprint')->label('Previous fingerprint')->copyable()->placeholder('—')
                            ->hidden(fn (): bool => static::isCustomerWorkspaceFlow()),
                        TextEntry::make('created_at')->label('Created')->dateTime(),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),

                Section::make('Evidence snapshot')
                    ->schema([
                        TextEntry::make('summary.evidence_resolution.outcome')
                            ->label('Resolution')
                            ->placeholder('—'),
                        TextEntry::make('evidenceSnapshot.id')
                            ->label('Snapshot')
                            ->formatStateUsing(fn (?int $state): string => $state ? '#'.$state : '—')
                            ->url(fn (ReviewPack $record): ?string => static::evidenceSnapshotUrl($record)),
                        TextEntry::make('evidenceSnapshot.completeness_state')
                            ->label('Snapshot completeness')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::EvidenceCompleteness))
                            ->color(BadgeRenderer::color(BadgeDomain::EvidenceCompleteness))
                            ->icon(BadgeRenderer::icon(BadgeDomain::EvidenceCompleteness))
                            ->iconColor(BadgeRenderer::iconColor(BadgeDomain::EvidenceCompleteness))
                            ->placeholder('—'),
                        TextEntry::make('summary.evidence_resolution.snapshot_fingerprint')
                            ->label('Snapshot fingerprint')
                            ->copyable()
                            ->placeholder('—'),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('created_at', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::resource())
            ->recordUrl(fn (ReviewPack $record): string => static::getUrl('view', ['record' => $record]))
            ->columns([
                Tables\Columns\TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::ReviewPackStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::ReviewPackStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::ReviewPackStatus))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::ReviewPackStatus))
                    ->sortable(),
                Tables\Columns\TextColumn::make('outcome')
                    ->label('Outcome')
                    ->badge()
                    ->getStateUsing(fn (ReviewPack $record): string => static::compressedOutcome($record)->primaryLabel)
                    ->color(fn (ReviewPack $record): string => static::compressedOutcome($record)->primaryBadge->color)
                    ->icon(fn (ReviewPack $record): ?string => static::compressedOutcome($record)->primaryBadge->icon)
                    ->iconColor(fn (ReviewPack $record): ?string => static::compressedOutcome($record)->primaryBadge->iconColor)
                    ->description(fn (ReviewPack $record): ?string => static::compressedOutcome($record)->primaryReason)
                    ->wrap(),
                Tables\Columns\TextColumn::make('tenant.name')
                    ->label('ManagedEnvironment')
                    ->searchable(),
                Tables\Columns\TextColumn::make('generated_at')
                    ->dateTime()
                    ->sortable()
                    ->placeholder('—'),
                Tables\Columns\TextColumn::make('environmentReview.id')
                    ->label('Review')
                    ->formatStateUsing(fn (?int $state): string => $state ? '#'.$state : '—')
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('expires_at')
                    ->dateTime()
                    ->sortable()
                    ->placeholder('—'),
                Tables\Columns\TextColumn::make('file_size')
                    ->label('Size')
                    ->formatStateUsing(fn ($state): string => $state ? Number::fileSize((int) $state) : '—')
                    ->sortable(),
                Tables\Columns\TextColumn::make('next_step')
                    ->label('Next step')
                    ->getStateUsing(fn (ReviewPack $record): string => static::compressedOutcome($record)->nextActionText)
                    ->wrap(),
                Tables\Columns\TextColumn::make('created_at')
                    ->label('Created')
                    ->since()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('status')
                    ->options(collect(ReviewPackStatus::cases())
                        ->mapWithKeys(fn (ReviewPackStatus $s): array => [$s->value => ucfirst($s->value)])
                        ->all()),
            ])
            ->actions([
                Actions\Action::make('download')
                    ->label('Download')
                    ->icon('heroicon-o-arrow-down-tray')
                    ->color('success')
                    ->visible(fn (ReviewPack $record): bool => $record->status === ReviewPackStatus::Ready->value)
                    ->url(function (ReviewPack $record): string {
                        return app(ReviewPackService::class)->generateDownloadUrl($record);
                    })
                    ->openUrlInNewTab(),
                Actions\ActionGroup::make([
                    UiEnforcement::forAction(
                        Actions\Action::make('expire')
                            ->label('Expire')
                            ->icon('heroicon-o-clock')
                            ->color('danger')
                            ->hidden(fn (ReviewPack $record): bool => $record->status !== ReviewPackStatus::Ready->value)
                            ->requiresConfirmation()
                            ->modalDescription('This will mark the pack as expired and delete the file. This cannot be undone.')
                            ->action(function (ReviewPack $record): void {
                                if ($record->file_path && $record->file_disk) {
                                    \Illuminate\Support\Facades\Storage::disk($record->file_disk)->delete($record->file_path);
                                }

                                $record->update(['status' => ReviewPackStatus::Expired->value]);
                                static::truthEnvelope($record->refresh(), fresh: true);

                                Notification::make()
                                    ->success()
                                    ->title('Review pack expired')
                                    ->send();
                            }),
                    )
                        ->preserveVisibility()
                        ->requireCapability(Capabilities::REVIEW_PACK_MANAGE)
                        ->apply(),
                ])->label('More'),
            ])
            ->emptyStateHeading('No review packs yet')
            ->emptyStateDescription('Generate a review pack to export tenant data for external review.')
            ->emptyStateIcon('heroicon-o-document-arrow-down')
            ->emptyStateActions([
                static::generatePackAction(name: 'generate_first', label: 'Generate first pack'),
            ]);
    }

    public static function generatePackAction(string $name = 'generate_pack', string $label = 'Generate Pack'): Actions\Action
    {
        $action = UiEnforcement::forAction(
            Actions\Action::make($name)
                ->label($label)
                ->icon('heroicon-o-plus')
                ->disabled(fn (): bool => static::reviewPackGenerationBlocked())
                ->action(function (array $data): void {
                    static::executeGeneration($data);
                })
                ->form(static::reviewPackGenerationFormSchema())
        )
            ->requireCapability(Capabilities::REVIEW_PACK_MANAGE)
            ->preserveDisabled()
            ->apply();

        $action->tooltip(fn (): ?string => static::reviewPackGenerationActionTooltip());

        return $action;
    }

    /**
     * @return array<int, Section>
     */
    public static function reviewPackGenerationFormSchema(): array
    {
        return [
            Section::make('Pack options')
                ->schema([
                    Toggle::make('include_pii')
                        ->label('Include PII')
                        ->helperText('Include personally identifiable information in the export.')
                        ->default(config('tenantpilot.review_pack.include_pii_default', true)),
                    Toggle::make('include_operations')
                        ->label('Include operations')
                        ->helperText('Include recent operation history in the export.')
                        ->default(config('tenantpilot.review_pack.include_operations_default', true)),
                ]),
        ];
    }

    public static function getEloquentQuery(): Builder
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        if (! $tenant instanceof ManagedEnvironment) {
            return parent::getEloquentQuery()->whereRaw('1 = 0');
        }

        return parent::getEloquentQuery()
            ->with(['tenant', 'operationRun', 'evidenceSnapshot', 'environmentReview'])
            ->where('managed_environment_id', (int) $tenant->getKey());
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListReviewPacks::route('/'),
            'view' => Pages\ViewReviewPack::route('/{record}'),
        ];
    }

    public static function isCustomerWorkspaceFlow(): bool
    {
        return request()->query('source_surface') === CustomerReviewWorkspace::SOURCE_SURFACE;
    }

    private static function evidenceSnapshotUrl(ReviewPack $record): ?string
    {
        if (! $record->evidenceSnapshot) {
            return null;
        }

        $url = TenantEvidenceSnapshotResource::getUrl('view', ['record' => $record->evidenceSnapshot], tenant: $record->tenant);

        return static::isCustomerWorkspaceFlow()
            ? static::appendQuery($url, ['source_surface' => CustomerReviewWorkspace::SOURCE_SURFACE])
            : $url;
    }

    /**
     * @param  array<string, mixed>  $query
     */
    private static function appendQuery(string $url, array $query): string
    {
        if ($query === []) {
            return $url;
        }

        return $url.(str_contains($url, '?') ? '&' : '?').http_build_query($query);
    }

    private static function truthEnvelope(ReviewPack $record, bool $fresh = false): ArtifactTruthEnvelope
    {
        $presenter = app(ArtifactTruthPresenter::class);

        return $fresh
            ? $presenter->forReviewPackFresh($record)
            : $presenter->forReviewPack($record);
    }

    /**
     * @return array<string, mixed>
     */
    private static function truthState(ReviewPack $record, bool $fresh = false): array
    {
        $presenter = app(ArtifactTruthPresenter::class);
        $truth = $fresh
            ? static::truthEnvelope($record, true)
            : static::truthEnvelope($record);

        return $presenter->surfaceStateFor($record, SurfaceCompressionContext::reviewPack(), $fresh)
            ?? $truth->toArray(static::compressedOutcome($record, $fresh));
    }

    private static function compressedOutcome(ReviewPack $record, bool $fresh = false): CompressedGovernanceOutcome
    {
        $presenter = app(ArtifactTruthPresenter::class);

        return $presenter->compressedOutcomeFor($record, SurfaceCompressionContext::reviewPack(), $fresh)
            ?? $presenter->compressedOutcomeFromEnvelope(
                static::truthEnvelope($record, $fresh),
                SurfaceCompressionContext::reviewPack(),
            );
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public static function executeGeneration(array $data): void
    {
        $tenant = static::currentTenantContext();
        $user = auth()->user();

        if (! $tenant instanceof ManagedEnvironment || ! $user instanceof User) {
            Notification::make()->danger()->title('Unable to generate pack — missing context.')->send();

            return;
        }

        $service = app(ReviewPackService::class);

        if ($service->checkActiveRun($tenant)) {
            Notification::make()->warning()->title('A review pack is already being generated.')->send();

            return;
        }

        $options = [
            'include_pii' => (bool) ($data['include_pii'] ?? true),
            'include_operations' => (bool) ($data['include_operations'] ?? true),
        ];

        try {
            $reviewPack = $service->generate($tenant, $user, $options);
        } catch (WorkspaceEntitlementBlockedException $exception) {
            Notification::make()
                ->warning()
                ->title('Review pack generation unavailable')
                ->body($exception->getMessage())
                ->send();

            return;
        } catch (ReviewPackEvidenceResolutionException $exception) {
            $reasons = $exception->result->reasons;

            Notification::make()
                ->danger()
                ->title(match ($exception->result->outcome) {
                    'missing_snapshot' => 'Create snapshot required',
                    'snapshot_ineligible' => 'Snapshot is not eligible',
                    default => 'Unable to generate review pack',
                })
                ->body($reasons === [] ? $exception->getMessage() : implode(' ', $reasons))
                ->send();

            return;
        }

        static::truthEnvelope($reviewPack->refresh(), fresh: true);

        if (! $reviewPack->wasRecentlyCreated) {
            Notification::make()
                ->success()
                ->title('Review pack already available')
                ->body('A matching review pack is already ready. No new run was started.')
                ->actions([
                    Actions\Action::make('view_pack')
                        ->label('View pack')
                        ->url(static::getUrl('view', ['record' => $reviewPack], tenant: $tenant)),
                ])
                ->send();

            return;
        }

        OperationUxPresenter::queuedToast('environment.review_pack.generate')->send();
    }

    /**
     * @return array<string, mixed>
     */
    public static function reviewPackGenerationDecision(?ManagedEnvironment $tenant = null): array
    {
        $tenant ??= static::resolveTenantContextForCurrentPanel();

        if (! $tenant instanceof ManagedEnvironment) {
            return [];
        }

        return app(ReviewPackService::class)->reviewPackGenerationDecisionForTenant($tenant);
    }

    public static function currentTenantContext(): ?ManagedEnvironment
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        return $tenant instanceof ManagedEnvironment ? $tenant : null;
    }

    public static function reviewPackGenerationBlocked(?ManagedEnvironment $tenant = null): bool
    {
        return (bool) (static::reviewPackGenerationDecision($tenant)['is_blocked'] ?? false);
    }

    public static function reviewPackGenerationBlockReason(?ManagedEnvironment $tenant = null): ?string
    {
        $decision = static::reviewPackGenerationDecision($tenant);

        if (! (bool) ($decision['is_blocked'] ?? false)) {
            return null;
        }

        $reason = $decision['block_reason'] ?? null;

        return is_string($reason) && $reason !== '' ? $reason : null;
    }

    public static function reviewPackGenerationWarningReason(?ManagedEnvironment $tenant = null): ?string
    {
        $decision = static::reviewPackGenerationDecision($tenant);

        if (! (bool) ($decision['is_warning'] ?? false)) {
            return null;
        }

        $reason = $decision['warning_reason'] ?? null;

        return is_string($reason) && $reason !== '' ? $reason : null;
    }

    public static function reviewPackGenerationActionTooltip(?ManagedEnvironment $tenant = null): ?string
    {
        $tenant ??= static::currentTenantContext();
        $user = auth()->user();

        if ($tenant instanceof ManagedEnvironment && $user instanceof User && ! $user->can(Capabilities::REVIEW_PACK_MANAGE, $tenant)) {
            return AuthUiTooltips::insufficientPermission();
        }

        return static::reviewPackGenerationBlockReason($tenant)
            ?? static::reviewPackGenerationWarningReason($tenant);
    }
}
