<?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\Tenant;
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\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\Select;
use Filament\Forms\Components\Textarea;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
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, Tenant>
     */
    public function workspaceTenants(): Collection
    {
        return Tenant::query()
            ->where('workspace_id', (int) $this->workspace->getKey())
            ->orderBy('name')
            ->limit(10)
            ->get(['id', 'name', 'status', 'workspace_id', 'external_id']);
    }

    /**
     * @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('change_commercial_state')
                ->label('Change commercial state')
                ->icon('heroicon-o-adjustments-horizontal')
                ->color('warning')
                ->visible(fn (): bool => $this->canManageCommercialLifecycle())
                ->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);
    }

    /**
     * @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');
    }
}
