<?php

declare(strict_types=1);

namespace App\Filament\Pages\Governance;

use App\Filament\Concerns\CleansAdminTenantQueryParameter;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\Workspace;
use App\Services\Auth\CapabilityResolver;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Services\EnvironmentReviews\EnvironmentReviewRegisterService;
use App\Support\Auth\Capabilities;
use App\Support\GovernanceInbox\GovernanceInboxSectionBuilder;
use App\Support\Navigation\CanonicalNavigationContext;
use App\Support\Navigation\WorkspaceHubEnvironmentFilter;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use App\Support\Workspaces\WorkspaceContext;
use BackedEnum;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Illuminate\Support\Str;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use UnitEnum;

class GovernanceInbox extends Page
{
    use CleansAdminTenantQueryParameter;

    protected static bool $isDiscovered = false;

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-inbox-stack';

    protected static string|UnitEnum|null $navigationGroup = 'Governance';

    protected static ?string $navigationLabel = 'Governance inbox';

    protected static ?int $navigationSort = 5;

    protected static ?string $title = 'Governance inbox';

    protected static ?string $slug = 'governance/inbox';

    protected string $view = 'filament.pages.governance.governance-inbox';

    /**
     * @var array<int, ManagedEnvironment>|null
     */
    private ?array $authorizedTenants = null;

    /**
     * @var array<int, ManagedEnvironment>|null
     */
    private ?array $visibleFindingTenants = null;

    /**
     * @var array<int, ManagedEnvironment>|null
     */
    private ?array $reviewTenants = null;

    /**
     * @var array<string, mixed>|null
     */
    private ?array $inboxPayload = null;

    /**
     * @var array<string, mixed>|null
     */
    private ?array $unfilteredInboxPayload = null;

    private ?Workspace $workspace = null;

    private ?bool $visibleAlertsFamily = null;

    private ?bool $visibleFindingExceptionsFamily = null;

    public ?int $tenantId = null;

    public ?string $family = null;

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forPage(ActionSurfaceProfile::ListOnlyReadOnly, ActionSurfaceType::ReadOnlyRegistryReport)
            ->satisfy(ActionSurfaceSlot::ListHeader, 'Header actions keep the workspace decision surface calm and read-only.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'The governance inbox routes into existing source surfaces instead of exposing row-level secondary actions.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'The governance inbox does not expose bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'Empty states stay calm and capability-safe when no visible attention exists.')
            ->exempt(ActionSurfaceSlot::DetailHeader, 'The governance inbox owns no local detail surface in v1.');
    }

    public function mount(): void
    {
        $this->authorizeWorkspaceMembership();
        $this->applyRequestedTenantPrefilter();
        $this->family = $this->resolveRequestedFamily();
        $this->ensureAtLeastOneVisibleFamily();
        $this->ensureRequestedFamilyIsVisible();
    }

    /**
     * @return array<string, mixed>
     */
    public function appliedScope(): array
    {
        $selectedTenant = $this->selectedTenant();
        $availableFamilies = collect($this->availableFamilies())
            ->keyBy('key');

        return [
            'workspace_label' => $this->workspace()?->name,
            'tenant_label' => $selectedTenant?->name,
            'tenant_prefilter_source' => $selectedTenant instanceof ManagedEnvironment ? 'explicit_filter' : 'none',
            'family_key' => $this->family,
            'family_label' => $this->family !== null
                ? ($availableFamilies->get($this->family)['label'] ?? Str::headline($this->family))
                : 'All attention',
            'total_count' => (int) ($this->inboxPayload()['total_count'] ?? 0),
        ];
    }

    /**
     * @return list<array{key: string, label: string, count: int}>
     */
    public function availableFamilies(): array
    {
        return $this->inboxPayload()['available_families'] ?? [];
    }

    /**
     * @return list<array<string, mixed>>
     */
    public function sections(): array
    {
        return $this->inboxPayload()['sections'] ?? [];
    }

    /**
     * @return array<string, mixed>
     */
    public function calmEmptyState(): array
    {
        if ($this->tenantFilterAloneExcludesRows()) {
            return [
                'title' => 'This environment filter is hiding other visible attention',
                'body' => 'The current environment scope is calm, but other visible environments in this workspace still have governance attention.',
                'action_label' => 'Clear environment filter',
                'action_url' => $this->pageUrl(['environment_id' => null, 'family' => null]),
            ];
        }

        return [
            'title' => 'No visible governance attention right now',
            'body' => 'The current workspace scope is calm across the visible governance families.',
            'action_label' => null,
            'action_url' => null,
        ];
    }

    public function hasTenantPrefilter(): bool
    {
        return $this->selectedTenant() instanceof ManagedEnvironment;
    }

    public function isActiveFamily(?string $familyKey): bool
    {
        return $this->family === $familyKey;
    }

    public function pageUrl(array $overrides = []): string
    {
        $selectedTenant = $this->selectedTenant();
        $resolvedTenant = array_key_exists('environment_id', $overrides)
            ? $overrides['environment_id']
            : ($selectedTenant?->getKey() !== null ? (string) $selectedTenant->getKey() : null);
        $resolvedFamily = array_key_exists('family', $overrides)
            ? $overrides['family']
            : $this->family;

        return static::getUrl(
            panel: 'admin',
            parameters: array_filter([
                'environment_id' => (is_string($resolvedTenant) || is_numeric($resolvedTenant)) && (string) $resolvedTenant !== '' ? (string) $resolvedTenant : null,
                'family' => is_string($resolvedFamily) && $resolvedFamily !== '' ? $resolvedFamily : null,
            ], static fn (mixed $value): bool => $value !== null && $value !== ''),
        );
    }

    public function navigationContext(): CanonicalNavigationContext
    {
        return CanonicalNavigationContext::forGovernanceInbox(
            canonicalRouteName: static::getRouteName(Filament::getPanel('admin')),
            tenantId: $this->tenantId,
            backLinkUrl: $this->pageUrl(),
            familyKey: $this->family,
        );
    }

    private function authorizeWorkspaceMembership(): void
    {
        $user = auth()->user();
        $workspace = $this->workspace();

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

        if (! $workspace instanceof Workspace) {
            throw new NotFoundHttpException;
        }

        $resolver = app(WorkspaceCapabilityResolver::class);

        if (! $resolver->isMember($user, $workspace)) {
            throw new NotFoundHttpException;
        }
    }

    private function ensureAtLeastOneVisibleFamily(): void
    {
        if (
            $this->hasVisibleOperationsFamily()
            || $this->visibleFindingTenants() !== []
            || $this->hasVisibleFindingExceptionsFamily()
            || $this->reviewTenants() !== []
            || $this->hasVisibleAlertsFamily()
        ) {
            return;
        }

        abort(403);
    }

    private function ensureRequestedFamilyIsVisible(): void
    {
        if ($this->family === null) {
            return;
        }

        if (in_array($this->family, collect($this->availableFamilies())->pluck('key')->all(), true)) {
            return;
        }

        throw new NotFoundHttpException;
    }

    private function hasVisibleOperationsFamily(): bool
    {
        return $this->authorizedTenants() !== [];
    }

    private function hasVisibleAlertsFamily(): bool
    {
        if (is_bool($this->visibleAlertsFamily)) {
            return $this->visibleAlertsFamily;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->visibleAlertsFamily = false;
        }

        return $this->visibleAlertsFamily = app(WorkspaceCapabilityResolver::class)->can($user, $workspace, Capabilities::ALERTS_VIEW);
    }

    private function hasVisibleFindingExceptionsFamily(): bool
    {
        if (is_bool($this->visibleFindingExceptionsFamily)) {
            return $this->visibleFindingExceptionsFamily;
        }

        if ($this->authorizedTenants() === []) {
            return $this->visibleFindingExceptionsFamily = false;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->visibleFindingExceptionsFamily = false;
        }

        return $this->visibleFindingExceptionsFamily = app(WorkspaceCapabilityResolver::class)
            ->can($user, $workspace, Capabilities::FINDING_EXCEPTION_APPROVE);
    }

    /**
     * @return array<int, ManagedEnvironment>
     */
    private function visibleFindingTenants(): array
    {
        if ($this->visibleFindingTenants !== null) {
            return $this->visibleFindingTenants;
        }

        $user = auth()->user();
        $tenants = $this->authorizedTenants();

        if (! $user instanceof User || $tenants === []) {
            return $this->visibleFindingTenants = [];
        }

        $resolver = app(CapabilityResolver::class);
        $resolver->primeMemberships(
            $user,
            array_map(static fn (ManagedEnvironment $tenant): int => (int) $tenant->getKey(), $tenants),
        );

        return $this->visibleFindingTenants = array_values(array_filter(
            $tenants,
            fn (ManagedEnvironment $tenant): bool => $resolver->can($user, $tenant, Capabilities::TENANT_FINDINGS_VIEW),
        ));
    }

    /**
     * @return array<int, ManagedEnvironment>
     */
    private function reviewTenants(): array
    {
        if ($this->reviewTenants !== null) {
            return $this->reviewTenants;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->reviewTenants = [];
        }

        $service = app(EnvironmentReviewRegisterService::class);

        if (! $service->canAccessWorkspace($user, $workspace)) {
            return $this->reviewTenants = [];
        }

        return $this->reviewTenants = $service->authorizedTenants($user, $workspace);
    }

    /**
     * @return array<int, ManagedEnvironment>
     */
    private function authorizedTenants(): array
    {
        if ($this->authorizedTenants !== null) {
            return $this->authorizedTenants;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->authorizedTenants = [];
        }

        return $this->authorizedTenants = $user->accessibleManagedEnvironmentsQuery((int) $workspace->getKey())
            ->where('managed_environments.lifecycle_status', 'active')
            ->orderBy('managed_environments.name')
            ->get(['managed_environments.id', 'managed_environments.name', 'managed_environments.slug', 'managed_environments.workspace_id'])
            ->all();
    }

    private function applyRequestedTenantPrefilter(): void
    {
        $workspace = $this->workspace();

        if (! $workspace instanceof Workspace) {
            return;
        }

        $filter = WorkspaceHubEnvironmentFilter::fromRequest(request(), $workspace);

        if (! $filter instanceof WorkspaceHubEnvironmentFilter) {
            return;
        }

        $environmentId = $filter->environmentId();

        foreach ($this->authorizedTenants() as $tenant) {
            if ((int) $tenant->getKey() === $environmentId) {
                $this->tenantId = $environmentId;

                return;
            }
        }

        throw new NotFoundHttpException;
    }

    private function resolveRequestedFamily(): ?string
    {
        $family = request()->query('family');

        if (! is_string($family)) {
            return null;
        }

        return in_array($family, [
            'assigned_findings',
            'intake_findings',
            'finding_exceptions',
            'stale_operations',
            'alert_delivery_failures',
            'review_follow_up',
        ], true) ? $family : null;
    }

    private function workspace(): ?Workspace
    {
        if ($this->workspace instanceof Workspace) {
            return $this->workspace;
        }

        $workspaceId = app(WorkspaceContext::class)->currentWorkspaceId(request());

        if (! is_int($workspaceId)) {
            return null;
        }

        return $this->workspace = Workspace::query()->whereKey($workspaceId)->first();
    }

    /**
     * @return array<string, mixed>
     */
    private function inboxPayload(): array
    {
        if (is_array($this->inboxPayload)) {
            return $this->inboxPayload;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->inboxPayload = [
                'sections' => [],
                'available_families' => [],
                'family_counts' => [],
                'total_count' => 0,
            ];
        }

        return $this->inboxPayload = app(GovernanceInboxSectionBuilder::class)->build(
            user: $user,
            workspace: $workspace,
            authorizedTenants: $this->authorizedTenants(),
            visibleFindingTenants: $this->visibleFindingTenants(),
            reviewTenants: $this->reviewTenants(),
            canViewAlerts: $this->hasVisibleAlertsFamily(),
            canViewFindingExceptions: $this->hasVisibleFindingExceptionsFamily(),
            selectedTenant: $this->selectedTenant(),
            selectedFamily: $this->family,
            navigationContext: $this->navigationContext(),
        );
    }

    /**
     * @return array<string, mixed>
     */
    private function unfilteredInboxPayload(): array
    {
        if (is_array($this->unfilteredInboxPayload)) {
            return $this->unfilteredInboxPayload;
        }

        $user = auth()->user();
        $workspace = $this->workspace();

        if (! $user instanceof User || ! $workspace instanceof Workspace) {
            return $this->unfilteredInboxPayload = [
                'sections' => [],
                'available_families' => [],
                'family_counts' => [],
                'total_count' => 0,
            ];
        }

        return $this->unfilteredInboxPayload = app(GovernanceInboxSectionBuilder::class)->build(
            user: $user,
            workspace: $workspace,
            authorizedTenants: $this->authorizedTenants(),
            visibleFindingTenants: $this->visibleFindingTenants(),
            reviewTenants: $this->reviewTenants(),
            canViewAlerts: $this->hasVisibleAlertsFamily(),
            canViewFindingExceptions: $this->hasVisibleFindingExceptionsFamily(),
            selectedTenant: null,
            selectedFamily: null,
            navigationContext: $this->navigationContext(),
        );
    }

    private function selectedTenant(): ?ManagedEnvironment
    {
        if (! is_int($this->tenantId)) {
            return null;
        }

        foreach ($this->authorizedTenants() as $tenant) {
            if ((int) $tenant->getKey() === $this->tenantId) {
                return $tenant;
            }
        }

        return null;
    }

    private function tenantFilterAloneExcludesRows(): bool
    {
        if (! is_int($this->tenantId) || $this->family !== null) {
            return false;
        }

        if ($this->sections() !== []) {
            return false;
        }

        return (int) ($this->unfilteredInboxPayload()['total_count'] ?? 0) > 0;
    }
}
