<?php

declare(strict_types=1);

namespace App\Filament\Support;

use App\Filament\Pages\DberpCommonShortcutsPreferencesPage;
use App\Filament\Pages\WorkbenchDashboard;
use Filament\Facades\Filament;
use Filament\Pages\Page as FilamentPage;
use Filament\Panel;
use Filament\Resources\Resource;

/**
 * 从 Filament Panel 的 Resource/Page 导航元数据生成「可固定到常用功能」的候选项（不落库、不暴露路由名）。
 */
final class DberpFilamentNavigationShortcutCatalog
{
    /**
     * @param  array<class-string<resource>>  $skipResourceClasses  与预置 erp.* 工作台键位对应的 Resource 不再重复出现在候选列表。
     * @return list<DberpShortcutItem>
     */
    public function discover(Panel $panel, array $skipResourceClasses): array
    {
        if (! Filament::isServing()) {
            return [];
        }

        $skip = array_flip($skipResourceClasses);
        $items = [];

        foreach ($panel->getResources() as $resourceClass) {
            if (isset($skip[$resourceClass])) {
                continue;
            }

            if (! is_subclass_of($resourceClass, Resource::class)) {
                continue;
            }

            if (filled($resourceClass::getCluster())) {
                continue;
            }

            if ($resourceClass::getParentResourceRegistration()) {
                continue;
            }

            if (! $resourceClass::shouldRegisterNavigation()) {
                continue;
            }

            if ($resourceClass::getNavigationItems() === []) {
                continue;
            }

            if (! $resourceClass::canAccess()) {
                continue;
            }

            $slug = (string) str($resourceClass::getSlug($panel))->replace('/', '.');
            $key = 'nav.r.'.$slug;

            $groupNav = $resourceClass::getNavigationGroup();
            $uiGroup = $groupNav === null ? (string) __('dberp.nav.system') : (string) $groupNav;

            $items[] = new DberpShortcutItem(
                key: $key,
                labelLangKey: 'dberp.shortcuts.nav_discovered.label',
                descriptionLangKey: null,
                resourceClass: $resourceClass,
                pageClass: null,
                permissionCodesAny: null,
                group: 'pinnable_resource',
                sort: (int) ($resourceClass::getNavigationSort() ?? 999),
                placements: [DberpShortcutRegistry::PLACEMENT_SIDEBAR_PINNABLE],
                openResourceCreate: false,
                usesFilamentNavigationLabel: true,
                navigationUiGroup: $uiGroup,
            );
        }

        foreach ($panel->getPages() as $pageClass) {
            if (! is_subclass_of($pageClass, FilamentPage::class)) {
                continue;
            }

            if ($pageClass === WorkbenchDashboard::class || $pageClass === DberpCommonShortcutsPreferencesPage::class) {
                continue;
            }

            if (filled($pageClass::getCluster())) {
                continue;
            }

            if (! $pageClass::shouldRegisterNavigation()) {
                continue;
            }

            if (! $pageClass::canAccess()) {
                continue;
            }

            $slug = (string) str($pageClass::getSlug($panel))->replace('/', '.');
            $key = 'nav.p.'.$slug;

            $groupNav = $pageClass::getNavigationGroup();
            $uiGroup = $groupNav === null ? (string) __('dberp.nav.system') : (string) $groupNav;

            $items[] = new DberpShortcutItem(
                key: $key,
                labelLangKey: 'dberp.shortcuts.nav_discovered.label',
                descriptionLangKey: null,
                resourceClass: null,
                pageClass: $pageClass,
                permissionCodesAny: null,
                group: 'pinnable_page',
                sort: (int) ($pageClass::getNavigationSort() ?? 999),
                placements: [DberpShortcutRegistry::PLACEMENT_SIDEBAR_PINNABLE],
                openResourceCreate: false,
                usesFilamentNavigationLabel: true,
                navigationUiGroup: $uiGroup,
            );
        }

        usort($items, static function (DberpShortcutItem $a, DberpShortcutItem $b): int {
            $ra = DberpAdminSidebarNavigationOrder::rankForResolvedLabel($a->sectionLabel());
            $rb = DberpAdminSidebarNavigationOrder::rankForResolvedLabel($b->sectionLabel());
            if ($ra !== $rb) {
                return $ra <=> $rb;
            }
            if ($a->sidebarNavigationSort() !== $b->sidebarNavigationSort()) {
                return $a->sidebarNavigationSort() <=> $b->sidebarNavigationSort();
            }

            return strcmp($a->localizedLabel(), $b->localizedLabel());
        });

        return $items;
    }
}
