<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Tenant;

use App\Filament\Support\VerificationReportViewer;
use App\Models\OperationRun;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Verification\StartVerification;
use App\Support\Auth\Capabilities;
use App\Support\Auth\UiTooltips;
use App\Support\OperationRunLinks;
use App\Support\OperationRunStatus;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Notifications\Notification;
use Filament\Widgets\Widget;

class TenantVerificationReport extends Widget
{
    protected static bool $isLazy = false;

    protected string $view = 'filament.widgets.tenant.tenant-verification-report';

    public ?Tenant $record = null;

    private function resolveTenant(): ?Tenant
    {
        $tenant = Filament::getTenant();

        if ($tenant instanceof Tenant) {
            return $tenant;
        }

        return $this->record instanceof Tenant ? $this->record : null;
    }

    public function startVerification(StartVerification $verification): void
    {
        $user = auth()->user();

        if (! $user instanceof User) {
            abort(403);
        }

        $tenant = $this->resolveTenant();

        if (! $tenant instanceof Tenant) {
            abort(404);
        }

        if (! $user->canAccessTenant($tenant)) {
            abort(404);
        }

        $result = $verification->providerConnectionCheckForTenant(
            tenant: $tenant,
            initiator: $user,
            extraContext: [
                'surface' => [
                    'kind' => 'tenant_verification_widget',
                ],
            ],
        );

        $runUrl = OperationRunLinks::tenantlessView($result->run);

        if ($result->status === 'scope_busy') {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);

            Notification::make()
                ->title('Another operation is already running')
                ->body('Please wait for the active run to finish.')
                ->warning()
                ->actions([
                    Action::make('view_run')
                        ->label('View run')
                        ->url($runUrl),
                ])
                ->send();

            return;
        }

        if ($result->status === 'deduped') {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);

            OperationUxPresenter::alreadyQueuedToast((string) $result->run->type)
                ->actions([
                    Action::make('view_run')
                        ->label('View run')
                        ->url($runUrl),
                ])
                ->send();

            return;
        }

        if ($result->status === 'blocked') {
            $reasonCode = is_string($result->run->context['reason_code'] ?? null)
                ? (string) $result->run->context['reason_code']
                : 'unknown_error';

            $actions = [
                Action::make('view_run')
                    ->label('View run')
                    ->url($runUrl),
            ];

            $nextSteps = $result->run->context['next_steps'] ?? [];
            $nextSteps = is_array($nextSteps) ? $nextSteps : [];

            foreach ($nextSteps as $index => $step) {
                if (! is_array($step)) {
                    continue;
                }

                $label = is_string($step['label'] ?? null) ? trim((string) $step['label']) : '';
                $url = is_string($step['url'] ?? null) ? trim((string) $step['url']) : '';

                if ($label === '' || $url === '') {
                    continue;
                }

                $actions[] = Action::make('next_step_'.$index)
                    ->label($label)
                    ->url($url);

                break;
            }

            Notification::make()
                ->title('Verification blocked')
                ->body("Blocked by provider configuration ({$reasonCode}).")
                ->warning()
                ->actions($actions)
                ->send();

            return;
        }

        OpsUxBrowserEvents::dispatchRunEnqueued($this);

        OperationUxPresenter::queuedToast((string) $result->run->type)
            ->actions([
                Action::make('view_run')
                    ->label('View run')
                    ->url($runUrl),
            ])
            ->send();
    }

    /**
     * @return array<string, mixed>
     */
    protected function getViewData(): array
    {
        $tenant = $this->resolveTenant();

        if (! $tenant instanceof Tenant) {
            return [
                'tenant' => null,
                'run' => null,
                'runData' => null,
                'runUrl' => null,
                'report' => null,
                'isInProgress' => false,
                'canStart' => false,
                'startTooltip' => null,
            ];
        }

        $run = OperationRun::query()
            ->where('tenant_id', (int) $tenant->getKey())
            ->where('type', 'provider.connection.check')
            ->orderByDesc('id')
            ->first();

        $report = $run instanceof OperationRun
            ? VerificationReportViewer::report($run)
            : null;

        $isInProgress = $run instanceof OperationRun
            && (string) $run->status !== OperationRunStatus::Completed->value;

        $user = auth()->user();
        $isTenantMember = $user instanceof User && $user->canAccessTenant($tenant);
        $canStart = $isTenantMember
            && $user->can(Capabilities::PROVIDER_RUN, $tenant);

        $runData = null;

        if ($run instanceof OperationRun) {
            $context = is_array($run->context ?? null) ? $run->context : [];
            $targetScope = $context['target_scope'] ?? [];
            $targetScope = is_array($targetScope) ? $targetScope : [];

            $runData = [
                'id' => (int) $run->getKey(),
                'type' => (string) $run->type,
                'status' => (string) $run->status,
                'outcome' => (string) $run->outcome,
                'initiator_name' => (string) $run->initiator_name,
                'started_at' => $run->started_at?->toJSON(),
                'completed_at' => $run->completed_at?->toJSON(),
                'target_scope' => $targetScope,
                'failures' => is_array($run->failure_summary ?? null) ? $run->failure_summary : [],
            ];
        }

        return [
            'tenant' => $tenant,
            'run' => $run,
            'runData' => $runData,
            'runUrl' => $run instanceof OperationRun ? OperationRunLinks::tenantlessView($run) : null,
            'report' => $report,
            'redactionNotes' => VerificationReportViewer::redactionNotes($report),
            'isInProgress' => $isInProgress,
            'canStart' => $canStart,
            'startTooltip' => $isTenantMember && ! $canStart ? UiTooltips::insufficientPermission() : null,
        ];
    }
}
