<?php

declare(strict_types=1);

namespace App\Filament\System\Pages\Ops;

use App\Models\OperationRun;
use App\Models\PlatformUser;
use App\Services\SystemConsole\OperationRunTriageService;
use App\Support\Auth\PlatformCapabilities;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\System\SystemOperationRunLinks;
use App\Support\Ui\GovernanceActions\GovernanceActionCatalog;
use Filament\Actions\Action;
use Filament\Forms\Components\Textarea;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Contracts\Support\Htmlable;

class ViewRun extends Page
{
    protected static bool $shouldRegisterNavigation = false;

    protected static ?string $slug = 'ops/runs/{run}';

    protected string $view = 'filament.system.pages.ops.view-run';

    public OperationRun $run;

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

        if (! $user instanceof PlatformUser) {
            return false;
        }

        return $user->hasCapability(PlatformCapabilities::OPERATIONS_VIEW)
            || ($user->hasCapability(PlatformCapabilities::OPS_VIEW) && $user->hasCapability(PlatformCapabilities::RUNBOOKS_VIEW));
    }

    public function mount(OperationRun $run): void
    {
        $run->load(['tenant', 'workspace']);

        $this->run = $run;
    }

    public function getTitle(): string|Htmlable
    {
        return 'Operation #'.(int) $this->run->getKey();
    }

    /**
     * @return array<Action>
     */
    protected function getHeaderActions(): array
    {
        $retryRule = GovernanceActionCatalog::rule('retry_run');
        $cancelRule = GovernanceActionCatalog::rule('cancel_run');
        $investigatedRule = GovernanceActionCatalog::rule('mark_investigated');

        return [
            Action::make('show_all_operations')
                ->label('Show all operations')
                ->url(SystemOperationRunLinks::index()),
            Action::make('go_to_runbooks')
                ->label('Go to runbooks')
                ->url(Runbooks::getUrl(panel: 'system')),
            Action::make('retry')
                ->label($retryRule->canonicalLabel)
                ->color('primary')
                ->requiresConfirmation()
                ->modalHeading($retryRule->modalHeading)
                ->modalDescription($retryRule->modalDescription)
                ->visible(fn (): bool => $this->canManageOperations() && app(OperationRunTriageService::class)->canRetry($this->run))
                ->action(function (OperationRunTriageService $triageService): void {
                    $user = $this->requireManageUser();
                    $retryRun = $triageService->retry($this->run, $user);

                    OperationUxPresenter::queuedToast((string) $retryRun->type)
                        ->actions([
                            \Filament\Actions\Action::make('view_run')
                                ->label('View run')
                                ->url(SystemOperationRunLinks::view($retryRun)),
                        ])
                        ->send();
                }),
            Action::make('cancel')
                ->label($cancelRule->canonicalLabel)
                ->color('danger')
                ->requiresConfirmation()
                ->modalHeading($cancelRule->modalHeading)
                ->modalDescription($cancelRule->modalDescription)
                ->visible(fn (): bool => $this->canManageOperations() && app(OperationRunTriageService::class)->canCancel($this->run))
                ->form([
                    Textarea::make('reason')
                        ->label('Cancellation reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                ])
                ->action(function (array $data, OperationRunTriageService $triageService) use ($cancelRule): void {
                    $user = $this->requireManageUser();
                    $triageService->cancel($this->run, $user, (string) ($data['reason'] ?? ''));

                    Notification::make()
                        ->title($cancelRule->successTitle)
                        ->success()
                        ->send();
                }),
            Action::make('mark_investigated')
                ->label($investigatedRule->canonicalLabel)
                ->color('warning')
                ->requiresConfirmation()
                ->modalHeading($investigatedRule->modalHeading)
                ->modalDescription($investigatedRule->modalDescription)
                ->visible(fn (): bool => $this->canManageOperations())
                ->form([
                    Textarea::make('reason')
                        ->label('Investigation reason')
                        ->required()
                        ->minLength(5)
                        ->maxLength(500)
                        ->rows(4),
                ])
                ->action(function (array $data, OperationRunTriageService $triageService) use ($investigatedRule): void {
                    $user = $this->requireManageUser();
                    $triageService->markInvestigated($this->run, $user, (string) ($data['reason'] ?? ''));

                    Notification::make()
                        ->title($investigatedRule->successTitle)
                        ->success()
                        ->send();
                }),
        ];
    }

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

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

    private function requireManageUser(): PlatformUser
    {
        $user = auth('platform')->user();

        if (! $user instanceof PlatformUser || ! $user->hasCapability(PlatformCapabilities::OPERATIONS_MANAGE)) {
            abort(403);
        }

        return $user;
    }
}
