<?php

declare(strict_types=1);

namespace App\Filament\System\Pages\Directory;

use App\Filament\System\Pages\Directory\Concerns\BuildsCustomerHealthDecisionData;
use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Models\SupportAccessGrant;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use App\Models\WorkspaceSubscription;
use App\Services\Auth\SupportAccessGrantManager;
use App\Services\Auth\SupportAccessGrantResolver;
use App\Services\Entitlements\WorkspaceCommercialLifecycleResolver;
use App\Services\Entitlements\WorkspaceEntitlementResolver;
use App\Services\Entitlements\WorkspaceSubscriptionResolver;
use App\Services\Settings\SettingsWriter;
use App\Services\Workspaces\WorkspaceLifecycleService;
use App\Support\Auth\PlatformCapabilities;
use App\Support\CustomerHealth\WorkspaceHealthSummaryQuery;
use App\Support\OperationCatalog;
use App\Support\System\SystemDirectoryLinks;
use App\Support\System\SystemOperationRunLinks;
use App\Support\SystemConsole\SystemConsoleWindow;
use Filament\Actions\Action;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Illuminate\Support\Collection;

class ViewWorkspace extends Page
{
    use BuildsCustomerHealthDecisionData;

    protected static bool $shouldRegisterNavigation = false;

    protected static ?string $slug = 'directory/workspaces/{workspace}';

    protected string $view = 'filament.system.pages.directory.view-workspace';

    public Workspace $workspace;

    public static function canAccess(): bool
    {
        $user = auth('platform')->user();

        return $user instanceof PlatformUser
            && $user->hasCapability(PlatformCapabilities::DIRECTORY_VIEW);
    }

    public function mount(Workspace $workspace): void
    {
        $workspace->loadCount('tenants');

        $this->workspace = $workspace;
    }

    /**
     * @return Collection<int, ManagedEnvironment>
     */
    public function workspaceTenants(): Collection
    {
        return ManagedEnvironment::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->orderBy('name')
            ->limit(10)
            ->get(['id', 'name', 'lifecycle_status', 'workspace_id', 'slug', 'removed_from_workspace_at']);
    }

    /**
     * @return Collection<int, array{id: int, label: string, started: string, url: string}>
     */
    public function recentRuns(): Collection
    {
        return OperationRun::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->latest('id')
            ->limit(8)
            ->get(['id', 'type', 'created_at'])
            ->map(fn (OperationRun $run): array => [
                'id' => (int) $run->getKey(),
                'label' => OperationCatalog::label((string) $run->type),
                'started' => $run->created_at?->diffForHumans() ?? '—',
                'url' => SystemOperationRunLinks::view($run),
            ]);
    }

    public function adminWorkspaceUrl(): string
    {
        return SystemDirectoryLinks::adminWorkspace($this->workspace);
    }

    public function runsUrl(): string
    {
        return SystemOperationRunLinks::index();
    }

    /**
     * @return array<string, mixed>
     */
    public function workspaceEntitlementSummary(): array
    {
        return app(WorkspaceEntitlementResolver::class)->summary($this->workspace);
    }

    /**
     * @return array<string, mixed>
     */
    public function workspaceCommercialLifecycleSummary(): array
    {
        return app(WorkspaceCommercialLifecycleResolver::class)->summary($this->workspace);
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        return [
            Action::make('close_workspace')
                ->label('Close workspace')
                ->icon('heroicon-o-lock-closed')
                ->color('danger')
                ->visible(fn (): bool => $this->canManageWorkspaceLifecycle() && ! $this->workspace->isClosed())
                ->requiresConfirmation()
                ->modalHeading('Close workspace')
                ->modalDescription('Closing a workspace removes it from active workspace selection and blocks new workspace and tenant mutations while preserving history.')
                ->form([
                    Textarea::make('reason')
                        ->label('Closure reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(2000)
                        ->rows(4),
                ])
                ->action(function (array $data, WorkspaceLifecycleService $service): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    $this->workspace = $service
                        ->closeWorkspace($this->workspace, $actor, (string) ($data['reason'] ?? ''))
                        ->fresh()
                        ->loadCount('tenants');

                    Notification::make()
                        ->title('Workspace closed')
                        ->success()
                        ->send();
                }),
            Action::make('reopen_workspace')
                ->label('Reopen workspace')
                ->icon('heroicon-o-lock-open')
                ->color('success')
                ->visible(fn (): bool => $this->canManageWorkspaceLifecycle() && $this->workspace->isClosed())
                ->requiresConfirmation()
                ->modalHeading('Reopen workspace')
                ->modalDescription('Reopening makes the workspace eligible for normal workspace selection and tenant operations again, subject to RBAC and tenant posture.')
                ->form([
                    Textarea::make('reason')
                        ->label('Reopen reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(2000)
                        ->rows(4),
                ])
                ->action(function (array $data, WorkspaceLifecycleService $service): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    $this->workspace = $service
                        ->reopenWorkspace($this->workspace, $actor, (string) ($data['reason'] ?? ''))
                        ->fresh()
                        ->loadCount('tenants');

                    Notification::make()
                        ->title('Workspace reopened')
                        ->success()
                        ->send();
                }),
            Action::make('request_support_access')
                ->label('Request support access')
                ->icon('heroicon-o-lifebuoy')
                ->visible(fn (): bool => $this->canManageSupportAccess())
                ->disabled(fn (): bool => $this->supportAccessRequestDisabled())
                ->tooltip(fn (): ?string => $this->supportAccessRequestDisabled()
                    ? 'This workspace already has active or pending support access for the current support flow.'
                    : null)
                ->requiresConfirmation()
                ->modalHeading('Request support access')
                ->modalDescription('Support access is workspace-scoped, time-limited, and audit-backed. Workspace recovery remains separate from break-glass mode.')
                ->form([
                    Select::make('scope')
                        ->label('Support scope')
                        ->options(SupportAccessGrant::scopeLabels())
                        ->default(SupportAccessGrant::SCOPE_AUDIT_VIEW)
                        ->required()
                        ->live()
                        ->afterStateUpdated(function (Set $set): void {
                            $set('waiver_reason', null);
                        }),
                    Textarea::make('reason')
                        ->label('Reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                    TextInput::make('ttl_minutes')
                        ->label('TTL')
                        ->numeric()
                        ->integer()
                        ->minValue(1)
                        ->maxValue(fn (): int => $this->supportAccessMaxTtlMinutes())
                        ->default(60)
                        ->suffix('minutes')
                        ->required(),
                    Textarea::make('waiver_reason')
                        ->label('Ownerless recovery waiver reason')
                        ->helperText('Required only when workspace recovery is requested for a workspace with zero owners. Break-glass must already be active.')
                        ->required(fn (Get $get): bool => $this->requiresOwnerlessWaiver((string) $get('scope')))
                        ->visible(fn (Get $get): bool => $this->requiresOwnerlessWaiver((string) $get('scope')))
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                ])
                ->action(function (array $data, SupportAccessGrantManager $manager): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    $grant = $manager->request(
                        workspace: $this->workspace,
                        actor: $actor,
                        scope: (string) ($data['scope'] ?? ''),
                        reason: (string) ($data['reason'] ?? ''),
                        ttlMinutes: (int) ($data['ttl_minutes'] ?? 0),
                        waiverReason: isset($data['waiver_reason']) ? (string) $data['waiver_reason'] : null,
                    );

                    $this->workspace = $this->workspace->fresh()->loadCount('tenants');

                    Notification::make()
                        ->title($grant->status === SupportAccessGrant::STATUS_ACTIVE
                            ? 'Support access active'
                            : 'Support access requested')
                        ->success()
                        ->send();
                }),
            Action::make('end_support_access')
                ->label('End support access')
                ->icon('heroicon-o-no-symbol')
                ->color('warning')
                ->visible(fn (): bool => $this->canManageSupportAccess() && $this->currentActiveSupportAccessGrant() instanceof SupportAccessGrant)
                ->requiresConfirmation()
                ->modalHeading('End support access')
                ->modalDescription('This immediately ends the active support-access grant for this workspace and records an audit event.')
                ->action(function (SupportAccessGrantManager $manager): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    $grant = $this->currentActiveSupportAccessGrant();

                    if (! $grant instanceof SupportAccessGrant) {
                        Notification::make()
                            ->title('No active support access')
                            ->warning()
                            ->send();

                        return;
                    }

                    $manager->end($grant, $actor);

                    $this->workspace = $this->workspace->fresh()->loadCount('tenants');

                    Notification::make()
                        ->title('Support access ended')
                        ->success()
                        ->send();
                }),
            Action::make('update_subscription_truth')
                ->label('Update subscription truth')
                ->icon('heroicon-o-credit-card')
                ->visible(fn (): bool => $this->canManageCommercialLifecycle())
                ->requiresConfirmation()
                ->modalHeading('Update subscription truth')
                ->modalDescription('This records the current subscription-backed commercial truth for the workspace and becomes the upstream lifecycle source while the record exists.')
                ->form([
                    Select::make('state')
                        ->label('Subscription state')
                        ->options(WorkspaceSubscriptionResolver::stateLabels())
                        ->required()
                        ->live()
                        ->afterStateUpdated(function (Set $set, ?string $state): void {
                            $normalizedState = $this->normalizeSubscriptionState($state);

                            if ($normalizedState !== WorkspaceSubscription::STATE_TRIAL) {
                                $set('trial_ends_at', null);
                            }

                            if (! in_array($normalizedState, [
                                WorkspaceSubscription::STATE_ACTIVE,
                                WorkspaceSubscription::STATE_PAST_DUE,
                                WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                            ], true)) {
                                $set('current_period_starts_at', null);
                            }

                            if (! in_array($normalizedState, [
                                WorkspaceSubscription::STATE_ACTIVE,
                                WorkspaceSubscription::STATE_PAST_DUE,
                                WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                                WorkspaceSubscription::STATE_ENDED,
                            ], true)) {
                                $set('current_period_ends_at', null);
                            }
                        })
                        ->helperText('Trial requires a trial end date. Active, past due, cancellation pending, and ended states require the matching current-period dates.')
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->state),
                    TextInput::make('billing_reference')
                        ->label('Billing reference')
                        ->maxLength(191)
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->billing_reference),
                    DateTimePicker::make('trial_ends_at')
                        ->label('Trial ends at')
                        ->required(fn (Get $get): bool => $this->selectedSubscriptionState($get) === WorkspaceSubscription::STATE_TRIAL)
                        ->visible(fn (Get $get): bool => $this->selectedSubscriptionState($get) === WorkspaceSubscription::STATE_TRIAL)
                        ->helperText('Required when the subscription state is Trial.')
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->trial_ends_at?->toDateTimeString()),
                    DateTimePicker::make('current_period_starts_at')
                        ->label('Current period starts at')
                        ->required(fn (Get $get): bool => in_array($this->selectedSubscriptionState($get), [
                            WorkspaceSubscription::STATE_ACTIVE,
                            WorkspaceSubscription::STATE_PAST_DUE,
                            WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                        ], true))
                        ->visible(fn (Get $get): bool => in_array($this->selectedSubscriptionState($get), [
                            WorkspaceSubscription::STATE_ACTIVE,
                            WorkspaceSubscription::STATE_PAST_DUE,
                            WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                        ], true))
                        ->helperText('Required for Active, Past due, and Cancellation pending subscriptions.')
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->current_period_starts_at?->toDateTimeString()),
                    DateTimePicker::make('current_period_ends_at')
                        ->label('Current period ends at')
                        ->required(fn (Get $get): bool => in_array($this->selectedSubscriptionState($get), [
                            WorkspaceSubscription::STATE_ACTIVE,
                            WorkspaceSubscription::STATE_PAST_DUE,
                            WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                            WorkspaceSubscription::STATE_ENDED,
                        ], true))
                        ->visible(fn (Get $get): bool => in_array($this->selectedSubscriptionState($get), [
                            WorkspaceSubscription::STATE_ACTIVE,
                            WorkspaceSubscription::STATE_PAST_DUE,
                            WorkspaceSubscription::STATE_CANCEL_AT_PERIOD_END,
                            WorkspaceSubscription::STATE_ENDED,
                        ], true))
                        ->helperText('Required for Active, Past due, Cancellation pending, and Ended subscriptions.')
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->current_period_ends_at?->toDateTimeString()),
                    Textarea::make('status_reason')
                        ->label('Status reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4)
                        ->default(fn (): ?string => $this->currentWorkspaceSubscription()?->status_reason),
                ])
                ->action(function (array $data, SettingsWriter $settingsWriter): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    if (! $actor->hasCapability(PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE)) {
                        abort(403);
                    }

                    $settingsWriter->updateWorkspaceSubscription(
                        actor: $actor,
                        workspace: $this->workspace,
                        attributes: $data,
                    );

                    $this->workspace = $this->workspace->fresh()->loadCount('tenants');

                    Notification::make()
                        ->title('Subscription truth updated')
                        ->success()
                        ->send();
                }),
            Action::make('change_commercial_state')
                ->label('Change commercial state')
                ->icon('heroicon-o-adjustments-horizontal')
                ->color('warning')
                ->visible(fn (): bool => $this->canManageCommercialLifecycle()
                    && (bool) ($this->workspaceCommercialLifecycleSummary()['fallback_status'] ?? true))
                ->requiresConfirmation()
                ->modalHeading('Change commercial state')
                ->modalDescription('This changes the workspace commercial lifecycle overlay. The rationale is audited and affects onboarding activation and review-pack starts.')
                ->form([
                    Select::make('state')
                        ->label('Commercial state')
                        ->options(WorkspaceCommercialLifecycleResolver::stateLabels())
                        ->required()
                        ->default(fn (): string => (string) ($this->workspaceCommercialLifecycleSummary()['state'] ?? WorkspaceCommercialLifecycleResolver::STATE_ACTIVE_PAID)),
                    Textarea::make('reason')
                        ->label('Rationale')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                ])
                ->action(function (array $data, SettingsWriter $settingsWriter): void {
                    $actor = auth('platform')->user();

                    if (! $actor instanceof PlatformUser) {
                        abort(403);
                    }

                    if (! $actor->hasCapability(PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE)) {
                        abort(403);
                    }

                    $settingsWriter->updateWorkspaceCommercialLifecycle(
                        actor: $actor,
                        workspace: $this->workspace,
                        state: (string) ($data['state'] ?? ''),
                        reason: (string) ($data['reason'] ?? ''),
                    );

                    $this->workspace->refresh();

                    Notification::make()
                        ->title('Commercial state updated')
                        ->success()
                        ->send();
                }),
        ];
    }

    private function canManageCommercialLifecycle(): bool
    {
        $user = auth('platform')->user();

        return $user instanceof PlatformUser
            && $user->hasCapability(PlatformCapabilities::COMMERCIAL_LIFECYCLE_MANAGE);
    }

    private function canManageWorkspaceLifecycle(): bool
    {
        $user = auth('platform')->user();

        return $user instanceof PlatformUser
            && $user->hasCapability(PlatformCapabilities::DIRECTORY_MANAGE);
    }

    private function canManageSupportAccess(): bool
    {
        $user = auth('platform')->user();

        return $user instanceof PlatformUser
            && $user->hasCapability(PlatformCapabilities::SUPPORT_ACCESS_MANAGE);
    }

    /**
     * @return array<string, mixed>
     */
    public function supportAccessSummary(): array
    {
        return app(SupportAccessGrantResolver::class)->summaryFor($this->workspace);
    }

    public function supportAccessMaxTtlMinutes(): int
    {
        return app(SupportAccessGrantResolver::class)->maxTtlMinutes();
    }

    private function requiresOwnerlessWaiver(string $scope): bool
    {
        return $scope === SupportAccessGrant::SCOPE_WORKSPACE_RECOVERY
            && ! app(SupportAccessGrantResolver::class)->workspaceHasOwners($this->workspace);
    }

    private function supportAccessRequestDisabled(): bool
    {
        return app(SupportAccessGrantResolver::class)->currentOpenGrantFor($this->workspace) instanceof SupportAccessGrant;
    }

    private function currentActiveSupportAccessGrant(): ?SupportAccessGrant
    {
        $grant = app(SupportAccessGrantResolver::class)->currentOpenGrantFor($this->workspace);

        return $grant instanceof SupportAccessGrant && $grant->status === SupportAccessGrant::STATUS_ACTIVE
            ? $grant
            : null;
    }

    private function currentWorkspaceSubscription(): ?WorkspaceSubscription
    {
        $this->workspace->loadMissing('subscription');

        return $this->workspace->subscription;
    }

    private function selectedSubscriptionState(Get $get): string
    {
        return $this->normalizeSubscriptionState($get('state'));
    }

    private function normalizeSubscriptionState(mixed $state): string
    {
        $normalizedState = is_string($state) ? trim($state) : '';

        return in_array($normalizedState, WorkspaceSubscription::stateIds(), true)
            ? $normalizedState
            : WorkspaceSubscription::STATE_ACTIVE;
    }

    /**
     * @return array{
     *     overall: array{label: string, color: string, icon: string|null},
     *     reason: string,
     *     impact: string,
     *     recommended_action: string,
     *     dominant_dimensions: list<array{label: string, color: string, icon: string|null}>,
     *     window_label: string
     * }|null
     */
    public function customerHealthDecision(): ?array
    {
        $window = SystemConsoleWindow::fromNullable(request()->query('window'));
        $summary = app(WorkspaceHealthSummaryQuery::class)->summaryForWorkspace($this->workspace, $window);

        if (! is_array($summary)) {
            return null;
        }

        return $this->buildCustomerHealthDecision($summary, $window, 'workspace');
    }
}
