<?php

declare(strict_types=1);

namespace App\Filament\Widgets\ManagedEnvironment;

use App\Filament\Resources\StoredReportResource;
use App\Jobs\ScanEntraAdminRolesJob;
use App\Models\StoredReport;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\OperationRunService;
use App\Support\Auth\Capabilities;
use App\Support\OperationRunLinks;
use App\Support\OpsUx\OperationUxPresenter;
use App\Support\OpsUx\OpsUxBrowserEvents;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Widgets\Widget;

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

    protected string $view = 'filament.widgets.managed-environment.admin-roles-summary';

    public ?ManagedEnvironment $record = null;

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

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

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

    public function scanNow(): void
    {
        $user = auth()->user();

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

        $tenant = $this->resolveTenant();

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

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

        if (! $user->can(Capabilities::ENTRA_ROLES_MANAGE, $tenant)) {
            abort(403);
        }

        /** @var OperationRunService $operationRuns */
        $operationRuns = app(OperationRunService::class);

        $opRun = $operationRuns->ensureRunWithIdentity(
            tenant: $tenant,
            type: 'entra.admin_roles.scan',
            identityInputs: [
                'managed_environment_id' => (int) $tenant->getKey(),
                'trigger' => 'scan',
            ],
            context: [
                'workspace_id' => (int) $tenant->workspace_id,
                'initiator_user_id' => (int) $user->getKey(),
            ],
            initiator: $user,
        );

        $runUrl = OperationRunLinks::tenantlessView($opRun);

        if ($opRun->wasRecentlyCreated === false) {
            OpsUxBrowserEvents::dispatchRunEnqueued($this);

            OperationUxPresenter::alreadyQueuedToast((string) $opRun->type)
                ->actions([
                    Action::make('view_run')
                        ->label('Open operation')
                        ->url($runUrl),
                ])
                ->send();

            return;
        }

        $operationRuns->dispatchOrFail($opRun, function () use ($tenant, $user): void {
            ScanEntraAdminRolesJob::dispatch(
                tenantId: (int) $tenant->getKey(),
                workspaceId: (int) $tenant->workspace_id,
                initiatorUserId: (int) $user->getKey(),
            );
        });

        OpsUxBrowserEvents::dispatchRunEnqueued($this);

        OperationUxPresenter::queuedToast((string) $opRun->type)
            ->body('The scan will run in the background. Results appear once complete.')
            ->actions([
                Action::make('view_run')
                    ->label('Open operation')
                    ->url($runUrl),
            ])
            ->send();
    }

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

        if (! $tenant instanceof ManagedEnvironment) {
            return $this->emptyState();
        }

        $user = auth()->user();
        $isTenantMember = $user instanceof User && $user->canAccessTenant($tenant);
        $canView = $isTenantMember && $user->can(Capabilities::ENTRA_ROLES_VIEW, $tenant);
        $canManage = $isTenantMember && $user->can(Capabilities::ENTRA_ROLES_MANAGE, $tenant);

        $report = StoredReport::query()
            ->where('managed_environment_id', (int) $tenant->getKey())
            ->where('report_type', StoredReport::REPORT_TYPE_ENTRA_ADMIN_ROLES)
            ->orderByDesc('created_at')
            ->orderByDesc('id')
            ->first();

        if (! $report instanceof StoredReport) {
            return [
                'tenant' => $tenant,
                'reportSummary' => null,
                'lastScanAt' => null,
                'highPrivilegeCount' => 0,
                'canManage' => $canManage,
                'canView' => $canView,
                'viewReportUrl' => null,
            ];
        }

        $payload = is_array($report->payload) ? $report->payload : [];
        $totals = is_array($payload['totals'] ?? null) ? $payload['totals'] : [];
        $highPrivilegeCount = (int) ($totals['high_privilege_assignments'] ?? 0);

        return [
            'tenant' => $tenant,
            'reportSummary' => $totals,
            'lastScanAt' => $report->created_at?->diffForHumans() ?? '—',
            'highPrivilegeCount' => $highPrivilegeCount,
            'canManage' => $canManage,
            'canView' => $canView,
            'viewReportUrl' => $canView
                ? StoredReportResource::getUrl('view', ['record' => $report], tenant: $tenant)
                : null,
        ];
    }

    /**
     * @return array<string, mixed>
     */
    private function emptyState(): array
    {
        return [
            'tenant' => null,
            'reportSummary' => null,
            'lastScanAt' => null,
            'highPrivilegeCount' => 0,
            'canManage' => false,
            'canView' => false,
            'viewReportUrl' => null,
        ];
    }
}
