<?php

namespace App\Console\Commands;

use App\Support\AdminAuthorizationRegistry;
use App\Support\AdminPermissionLanguage;
use Illuminate\Console\Command;

final class CheckAdminPermissionLanguageCommand extends Command
{
    protected $signature = 'lottery:admin-permission-language-check
        {--page=integration-sites : 页面 key（当前只验证 integration-sites 示例映射）}';

    protected $description = '检查“权限语言映射”与后端 Registry / API 资源绑定的一致性';

    public function handle(): int
    {
        $pageKey = (string) $this->option('page');
        if ($pageKey === '') {
            $this->error('Missing --page');
            return self::FAILURE;
        }

        $issues = [];

        $requiredPrdSlugs = AdminPermissionLanguage::requiredAnyPrdSlugs($pageKey);
        if ($requiredPrdSlugs === []) {
            $issues[] = [
                'type' => 'config',
                'message' => sprintf('No required prd slugs found for page `%s`.', $pageKey),
            ];
        }

        $permissionDefinitions = AdminAuthorizationRegistry::permissionDefinitions();

        /** @var array<string, array{slug: string, permission_codes: list<string>}> $bySlug */
        $bySlug = [];
        foreach ($permissionDefinitions as $def) {
            $slug = $def['slug'] ?? '';
            if (! is_string($slug) || $slug === '') {
                continue;
            }
            $bySlug[$slug] = $def;
        }

        foreach (AdminPermissionLanguage::requiredBundleKeys($pageKey) as $bundleKey) {
            $expectedSlug = AdminPermissionLanguage::prdSlug($pageKey, $bundleKey);
            $expectedCodes = AdminPermissionLanguage::permissionCodes($pageKey, $bundleKey);

            if (! isset($bySlug[$expectedSlug])) {
                $issues[] = [
                    'type' => 'prd_slug',
                    'message' => sprintf('PRD slug `%s` for bundle `%s` not found in AdminAuthorizationRegistry::permissionDefinitions().', $expectedSlug, $bundleKey),
                ];
                continue;
            }

            $actualCodes = $bySlug[$expectedSlug]['permission_codes'] ?? [];
            $actualSet = array_fill_keys(is_array($actualCodes) ? $actualCodes : [], true);
            $expectedSet = array_fill_keys($expectedCodes, true);

            $missing = array_values(array_diff(array_keys($expectedSet), array_keys($actualSet)));
            if ($missing !== []) {
                $issues[] = [
                    'type' => 'prd_action_codes',
                    'message' => sprintf(
                        'PRD slug `%s` (bundle `%s`) missing action codes: %s',
                        $expectedSlug,
                        $bundleKey,
                        implode(', ', $missing),
                    ),
                ];
            }
        }

        // Sidebar / “页面可进”入口：integration-sites 对应 nav_segment=integration
        foreach (AdminAuthorizationRegistry::navigationDefinitions() as $nav) {
            if (($nav['segment'] ?? '') !== 'integration') {
                continue;
            }

            $requiredAny = $nav['requiredAny'] ?? [];
            if (! is_array($requiredAny)) {
                $requiredAny = [];
            }

            foreach ($requiredPrdSlugs as $requiredSlug) {
                if (! in_array($requiredSlug, $requiredAny, true)) {
                    $issues[] = [
                        'type' => 'navigation_requiredAny',
                        'message' => sprintf('Navigation segment `integration` missing requiredAny slug `%s`.', $requiredSlug),
                    ];
                }
            }

            break;
        }

        // API 资源：检查 integration-sites 的路由资源 binding 至少包含对应 action code。
        $resources = AdminAuthorizationRegistry::resources();
        /** @var array<string, array{permission_codes: list<string>}> $resourceByCode */
        $resourceByCode = [];
        foreach ($resources as $resource) {
            $code = $resource['code'] ?? '';
            if (! is_string($code) || $code === '') {
                continue;
            }
            $resourceByCode[$code] = $resource;
        }

        $viewActionCodes = AdminPermissionLanguage::permissionCodes($pageKey, 'view');
        $manageActionCodes = AdminPermissionLanguage::permissionCodes($pageKey, 'manage');

        $endpointChecks = [
            // view
            'admin.integration-sites.index' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
            'admin.integration-sites.show' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
            'admin.integration-sites.connectivity-test' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],
            'admin.integration-sites.export' => ['expected_permission_codes' => $viewActionCodes, 'expected_bundle' => 'view'],

            // manage
            'admin.integration-sites.store' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
            'admin.integration-sites.update' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
            'admin.integration-sites.rotate-secrets' => ['expected_permission_codes' => $manageActionCodes, 'expected_bundle' => 'manage'],
        ];

        foreach ($endpointChecks as $resourceCode => $check) {
            if (! isset($resourceByCode[$resourceCode])) {
                $issues[] = [
                    'type' => 'resource_definitions',
                    'message' => sprintf('API resource `%s` not found in AdminAuthorizationRegistry::resources().', $resourceCode),
                ];
                continue;
            }

            $expectedCodes = $check['expected_permission_codes'] ?? [];
            $resourcePermissionCodes = $resourceByCode[$resourceCode]['permission_codes'] ?? [];

            $resourceSet = array_fill_keys(is_array($resourcePermissionCodes) ? $resourcePermissionCodes : [], true);
            foreach ($expectedCodes as $expectedCode) {
                if (! isset($resourceSet[$expectedCode])) {
                    $issues[] = [
                        'type' => 'api_resource_action_codes',
                        'message' => sprintf('API resource `%s` missing action code `%s`.', $resourceCode, $expectedCode),
                    ];
                }
            }
        }

        if ($issues === []) {
            $this->info('Admin permission language check passed.');
            return self::SUCCESS;
        }

        $this->error(sprintf('Admin permission language check found %d issue(s).', count($issues)));
        foreach ($issues as $issue) {
            $this->line(sprintf('- [%s] %s', $issue['type'], $issue['message']));
        }

        return self::FAILURE;
    }
}

