<?php

declare(strict_types=1);

namespace App\Support\Navigation;

use App\Filament\Pages\Governance\DecisionRegister;
use App\Filament\Pages\Governance\GovernanceInbox;
use App\Filament\Pages\Monitoring\Alerts;
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\Reviews\CustomerReviewWorkspace;
use App\Filament\Pages\Reviews\ReviewRegister;
use App\Filament\Pages\Settings\WorkspaceSettings;
use App\Filament\Pages\WorkspaceOverview;
use App\Filament\Resources\AlertDeliveryResource;
use App\Filament\Resources\AlertDestinationResource;
use App\Filament\Resources\AlertRuleResource;
use App\Filament\Resources\ProviderConnectionResource;
use App\Filament\Resources\Workspaces\WorkspaceResource;
use App\Models\User;
use App\Models\Workspace;
use App\Models\WorkspaceMembership;
use App\Services\Auth\WorkspaceCapabilityResolver;
use App\Services\Auth\WorkspaceRoleCapabilityMap;
use App\Support\Auth\Capabilities;
use App\Support\OperationRunLinks;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Navigation\NavigationBuilder;
use Filament\Navigation\NavigationGroup;
use Filament\Navigation\NavigationItem;

final class WorkspaceSidebarNavigation
{
    public function build(): NavigationBuilder
    {
        return app(NavigationBuilder::class)
            ->item(WorkspaceOverview::navigationItem())
            ->groups([
                NavigationGroup::make(__('localization.navigation.monitoring'))
                    ->items($this->visibleItems([
                        NavigationItem::make(FindingExceptionsQueue::getNavigationLabel())
                            ->url(fn (): string => $this->workspaceHubUrl(FindingExceptionsQueue::getUrl(panel: 'admin')))
                            ->icon(FindingExceptionsQueue::getNavigationIcon())
                            ->visible(fn (): bool => FindingExceptionsQueue::canAccess()),
                        NavigationItem::make(__('localization.navigation.operations'))
                            ->url(fn (): string => $this->workspaceHubUrl(OperationRunLinks::index()))
                            ->icon('heroicon-o-queue-list')
                            ->visible(fn (): bool => true),
                        NavigationItem::make(__('localization.navigation.alerts'))
                            ->url(fn (): string => $this->workspaceHubUrl(route('filament.admin.alerts')))
                            ->icon('heroicon-o-bell-alert')
                            ->visible(fn (): bool => Alerts::canAccess())
                            ->childItems($this->visibleItems([
                                NavigationItem::make(AlertDestinationResource::getNavigationLabel())
                                    ->url(fn (): string => $this->workspaceHubUrl(AlertDestinationResource::getUrl(panel: 'admin')))
                                    ->icon(AlertDestinationResource::getNavigationIcon())
                                    ->visible(fn (): bool => AlertDestinationResource::canViewAny()),
                                NavigationItem::make(AlertRuleResource::getNavigationLabel())
                                    ->url(fn (): string => $this->workspaceHubUrl(AlertRuleResource::getUrl(panel: 'admin')))
                                    ->icon(AlertRuleResource::getNavigationIcon())
                                    ->visible(fn (): bool => AlertRuleResource::canViewAny()),
                                NavigationItem::make(AlertDeliveryResource::getNavigationLabel())
                                    ->url(fn (): string => $this->workspaceHubUrl(AlertDeliveryResource::getUrl(panel: 'admin')))
                                    ->icon(AlertDeliveryResource::getNavigationIcon())
                                    ->visible(fn (): bool => AlertDeliveryResource::canViewAny()),
                            ])),
                        NavigationItem::make(__('localization.navigation.audit_log'))
                            ->url(fn (): string => $this->workspaceHubUrl(route('admin.monitoring.audit-log')))
                            ->icon('heroicon-o-clipboard-document-list'),
                    ])),
                NavigationGroup::make(__('localization.review.reporting'))
                    ->items($this->visibleItems([
                        NavigationItem::make(ReviewRegister::getNavigationLabel())
                            ->url(fn (): string => $this->workspaceHubUrl(ReviewRegister::getUrl(panel: 'admin')))
                            ->icon(ReviewRegister::getNavigationIcon()),
                        NavigationItem::make(CustomerReviewWorkspace::getNavigationLabel())
                            ->url(fn (): string => $this->workspaceHubUrl(CustomerReviewWorkspace::getUrl(panel: 'admin')))
                            ->icon(CustomerReviewWorkspace::getNavigationIcon()),
                    ])),
                NavigationGroup::make(__('localization.navigation.settings'))
                    ->items($this->visibleItems([
                        NavigationItem::make(__('localization.navigation.manage_workspaces'))
                            ->url(fn (): string => $this->workspaceHubUrl(route('filament.admin.resources.workspaces.index')))
                            ->icon(WorkspaceResource::getNavigationIcon())
                            ->visible(fn (): bool => $this->canManageWorkspaces()),
                        NavigationItem::make(__('localization.navigation.integrations'))
                            ->url(fn (): string => $this->workspaceHubUrl(ProviderConnectionResource::getUrl('index', panel: 'admin')))
                            ->icon(ProviderConnectionResource::getNavigationIcon())
                            ->visible(fn (): bool => ProviderConnectionResource::canViewAny())
                            ->childItems($this->visibleItems([
                                NavigationItem::make(ProviderConnectionResource::getNavigationLabel())
                                    ->url(fn (): string => $this->workspaceHubUrl(ProviderConnectionResource::getUrl('index', panel: 'admin')))
                                    ->icon(ProviderConnectionResource::getNavigationIcon())
                                    ->visible(fn (): bool => ProviderConnectionResource::canViewAny()),
                            ])),
                        NavigationItem::make(__('localization.navigation.settings'))
                            ->url(fn (): string => $this->workspaceHubUrl(WorkspaceSettings::getUrl(panel: 'admin')))
                            ->icon('heroicon-o-cog-6-tooth')
                            ->visible(fn (): bool => $this->canViewWorkspaceSettings()),
                    ])),
                NavigationGroup::make(__('localization.navigation.governance'))
                    ->items($this->visibleItems([
                        NavigationItem::make(GovernanceInbox::getNavigationLabel())
                            ->url(fn (): string => $this->workspaceHubUrl(GovernanceInbox::getUrl(panel: 'admin')))
                            ->icon(GovernanceInbox::getNavigationIcon()),
                        NavigationItem::make(DecisionRegister::getNavigationLabel())
                            ->url(fn (): string => $this->workspaceHubUrl(DecisionRegister::getUrl(panel: 'admin')))
                            ->icon(DecisionRegister::getNavigationIcon())
                            ->visible(fn (): bool => DecisionRegister::canAccess()),
                    ])),
            ]);
    }

    /**
     * @param  array<int, NavigationItem>  $items
     * @return array<int, NavigationItem>
     */
    private function visibleItems(array $items): array
    {
        return array_values(array_filter(
            $items,
            static fn (NavigationItem $item): bool => $item->isVisible(),
        ));
    }

    private function workspaceHubUrl(string $url): string
    {
        return WorkspaceHubRegistry::cleanUrl($url);
    }

    private function canManageWorkspaces(): bool
    {
        $user = auth()->user();

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

        $roles = WorkspaceRoleCapabilityMap::rolesWithCapability(Capabilities::WORKSPACE_MEMBERSHIP_MANAGE);

        return WorkspaceMembership::query()
            ->where('user_id', (int) $user->getKey())
            ->whereIn('role', $roles)
            ->exists();
    }

    private function canViewWorkspaceSettings(): bool
    {
        $user = auth()->user();

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

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

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

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

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

        $resolver = app(WorkspaceCapabilityResolver::class);

        return $resolver->isMember($user, $workspace)
            && $resolver->can($user, $workspace, Capabilities::WORKSPACE_SETTINGS_VIEW);
    }
}
