<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Services\Plugin;

use Illuminate\Support\Facades\Route;
use Throwable;

/**
 * 已启用官方插件 manifest 业务导航条目目录（侧栏注册与常用功能候选共用）。
 */
final class HostPluginNavigationCatalog
{
    public function __construct(
        private readonly DberpDatabasePluginRepository $repository,
        private readonly DberpPluginDiscoveryManager $discoveryManager,
        private readonly HostPluginManifestFileReader $manifestFileReader,
        private readonly HostPluginPermissionResolver $permissionResolver,
    ) {}

    /**
     * @return list<array{identifier: string, manifest: array<string, mixed>, label: string, route_name: string, permission: string, group_key: string, sort: int, active_routes: list<string>|null, icon: string|null}>
     */
    public function businessNavigationEntries(): array
    {
        if (! config('dberp.plugin.center_enabled', true)) {
            return [];
        }

        try {
            $this->discoveryManager->scan();
        } catch (Throwable) {
            return [];
        }

        $entries = [];

        foreach ($this->repository->enabledIdentifiers() as $identifier) {
            $manifest = $this->manifestFileReader->enriched($identifier);

            if (! is_array($manifest)) {
                continue;
            }

            $navigation = $manifest['navigation'] ?? null;

            if (! is_array($navigation)) {
                continue;
            }

            foreach ($this->normalizeNavigationEntries($navigation) as $navigationEntry) {
                $resolved = $this->resolveBusinessNavigationEntry($identifier, $manifest, $navigationEntry);

                if ($resolved !== null) {
                    $entries[] = $resolved;
                }
            }
        }

        return $entries;
    }

    public function resolveNavigationGroupLabel(string $groupKey): string
    {
        $normalized = trim($groupKey);

        if ($normalized === '') {
            return (string) __('dberp.nav.system');
        }

        $translationKey = 'dberp.nav.'.$normalized;
        $translated = __($translationKey);

        return $translated !== $translationKey ? (string) $translated : $normalized;
    }

    /**
     * @param  array<string, mixed>  $manifest
     */
    public function isSettingsRoute(array $manifest, string $routeName): bool
    {
        $normalizedRoute = trim($routeName);

        if ($normalizedRoute === '') {
            return false;
        }

        $configRoute = trim((string) ($manifest['config_route'] ?? ''));

        if ($configRoute !== '' && $normalizedRoute === $configRoute) {
            return true;
        }

        $alias = trim((string) ($manifest['alias'] ?? $manifest['identifier'] ?? ''));

        if ($alias !== '' && $normalizedRoute === $alias.'.settings') {
            return true;
        }

        return false;
    }

    /**
     * @param  array<string, mixed>  $navigation
     * @return list<array<string, mixed>>
     */
    private function normalizeNavigationEntries(array $navigation): array
    {
        if (isset($navigation['label']) || isset($navigation['route']) || isset($navigation['group'])) {
            return [$navigation];
        }

        return array_values(array_filter(
            $navigation,
            static fn (mixed $entry): bool => is_array($entry),
        ));
    }

    /**
     * @param  array<string, mixed>  $manifest
     * @param  array<string, mixed>  $navigation
     * @return array{identifier: string, manifest: array<string, mixed>, label: string, route_name: string, permission: string, group_key: string, sort: int, active_routes: list<string>|null, icon: string|null}|null
     */
    private function resolveBusinessNavigationEntry(
        string $identifier,
        array $manifest,
        array $navigation,
    ): ?array {
        $label = trim((string) ($navigation['label'] ?? ''));

        if ($label === '') {
            return null;
        }

        $routeName = trim((string) ($navigation['route'] ?? ''));

        if ($routeName === '' || ! Route::has($routeName)) {
            return null;
        }

        if ($this->isSettingsRoute($manifest, $routeName)) {
            return null;
        }

        $permission = trim((string) ($navigation['permission'] ?? ''));

        if ($permission === '') {
            $permission = $this->resolveDefaultNavigationPermission($manifest, $identifier);
        }

        $activeRoutes = $navigation['active_routes'] ?? null;
        $activeRoutePatterns = is_array($activeRoutes)
            ? array_values(array_filter(array_map(
                static fn (mixed $pattern): string => trim((string) $pattern),
                $activeRoutes,
            )))
            : null;

        return [
            'identifier' => $identifier,
            'manifest' => $manifest,
            'label' => $label,
            'route_name' => $routeName,
            'permission' => $permission,
            'group_key' => trim((string) ($navigation['group'] ?? '')),
            'sort' => (int) ($navigation['sort'] ?? 500),
            'active_routes' => $activeRoutePatterns,
            'icon' => ($icon = trim((string) ($navigation['icon'] ?? ''))) !== '' ? $icon : null,
        ];
    }

    /**
     * @param  array<string, mixed>  $manifest
     */
    private function resolveDefaultNavigationPermission(array $manifest, string $identifier): string
    {
        $codes = $this->permissionResolver->permissionCodesFromManifest($manifest);

        foreach ($codes as $code) {
            if (str_ends_with($code, '.view') || str_ends_with($code, '.manage')) {
                return $code;
            }
        }

        return $codes[0] ?? $this->permissionResolver->settingsPermissionCode($identifier);
    }
}
