<?php

declare(strict_types=1);

namespace Kylin\Scaffold\Commands;

use Illuminate\Console\Command;

/**
 * 合规检查命令
 *
 * 依据 GB/T 22239-2019 等保 2.0，安装后需执行合规检查。
 *
 * 检查项：
 *  - 密码策略
 *  - 审计日志
 *  - 访问控制
 *  - 数据加密
 *  - 安全配置
 *  - 各模块合规状态
 *
 * 使用方式：
 *   php artisan kylin:compliance-check
 *   php artisan kylin:compliance-check --json
 */
class ComplianceCheckCommand extends Command
{
    protected $signature = 'kylin:compliance-check
                            {--json : JSON 格式输出}
                            {--module= : 仅检查指定模块}';

    protected $description = '执行 Kylin 合规检查，验证各模块合规状态';

    /** 合规检查结果 */
    private array $results = [];

    /** 合规检查清单 */
    private array $checklist = [];

    public function handle(): int
    {
        $this->info('Kylin 合规检查');
        $this->line('法律依据：GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》');
        $this->line('        《个人信息保护法》《数据安全法》《网络安全法》');
        $this->newLine();

        $module = $this->option('module');

        // 初始化检查清单
        $this->initChecklist();

        // 执行检查
        $this->checkPasswordPolicy();
        $this->checkAuditLog();
        $this->checkAccessControl();
        $this->checkDataEncryption();
        $this->checkSecurityConfig();
        $this->checkModuleCompliance($module);

        $passCount = count(array_filter($this->checklist, fn ($item) => $item['status'] === 'pass'));
        $failCount = count(array_filter($this->checklist, fn ($item) => $item['status'] === 'fail'));
        $totalCount = count($this->checklist);

        if ($this->option('json')) {
            $this->line(json_encode([
                'summary' => [
                    'total' => $totalCount,
                    'pass' => $passCount,
                    'fail' => $failCount,
                    'pass_rate' => $totalCount > 0 ? round($passCount / $totalCount * 100, 2) : 0,
                ],
                'items' => $this->checklist,
            ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
        } else {
            $this->newLine();
            $this->line('──────────────────────────────────────────');
            $this->line('  合规检查结果');
            $this->line('──────────────────────────────────────────');
            $this->newLine();

            foreach ($this->checklist as $item) {
                $icon = $item['status'] === 'pass' ? '✅' : ($item['status'] === 'fail' ? '❌' : '⚠️');
                $this->line("  {$icon} {$item['item']}：{$item['message']}");
            }

            $this->newLine();
            $this->line("  通过率：{$passCount}/{$totalCount}（" . round($passCount / $totalCount * 100, 1) . '%）');
            $this->newLine();

            if ($failCount === 0) {
                $this->info('  所有合规检查项通过！');
            } else {
                $this->warn("  存在 {$failCount} 项不通过，请检查上述 ❌ 标记项。");
            }
        }

        return $failCount === 0 ? self::SUCCESS : self::FAILURE;
    }

    /**
     * 初始化检查清单
     */
    private function initChecklist(): void
    {
        $this->checklist = [];
    }

    /**
     * 检查密码策略
     *
     * 依据等保 2.0 (GB/T 22239) 8.1.4.6：
     * 密码长度 >= 8 位，包含大小写字母、数字、特殊字符。
     */
    private function checkPasswordPolicy(): void
    {
        $minLength = config('kylin-auth.password.min_length', 8);
        $requireMixed = config('kylin-auth.password.mixed_case', true);
        $requireNumber = config('kylin-auth.password.numbers', true);
        $requireSymbol = config('kylin-auth.password.symbols', true);

        $allPass = $minLength >= 8 && $requireMixed && $requireNumber && $requireSymbol;

        $this->checklist[] = [
            'item' => '密码策略',
            'status' => $allPass ? 'pass' : 'fail',
            'message' => $allPass
                ? '密码长度 >= 8，包含大小写字母/数字/特殊字符'
                : '密码策略不满足等保 2.0 要求',
            'law' => 'GB/T 22239 8.1.4.6',
        ];
    }

    /**
     * 检查审计日志
     *
     * 依据等保 2.0 (GB/T 22239) 8.1.4.6：
     * 系统需记录审计日志且不可篡改。
     */
    private function checkAuditLog(): void
    {
        $auditEnabled = class_exists(\Kylin\AuditLog\Models\AuditLog::class);
        $immutable = $auditEnabled && config('kylin-audit-log.immutable', true);

        $this->checklist[] = [
            'item' => '审计日志',
            'status' => $auditEnabled ? 'pass' : 'fail',
            'message' => $auditEnabled
                ? ($immutable ? '已启用且不可篡改' : '已启用但未配置不可篡改')
                : '未集成 kylin/audit-log 包',
            'law' => 'GB/T 22239 8.1.4.6',
        ];
    }

    /**
     * 检查访问控制
     *
     * 依据等保 2.0 (GB/T 22239) 8.1.4.1：
     * 系统需实现基于角色的访问控制。
     */
    private function checkAccessControl(): void
    {
        $rbacEnabled = class_exists(\Kylin\Rbac\RbacServiceProvider::class);

        $this->checklist[] = [
            'item' => '访问控制',
            'status' => $rbacEnabled ? 'pass' : 'fail',
            'message' => $rbacEnabled
                ? '已集成 RBAC 权限管理'
                : '未集成 kylin/rbac 包',
            'law' => 'GB/T 22239 8.1.4.1',
        ];
    }

    /**
     * 检查数据加密
     *
     * 依据《个人信息保护法》第五十一条：
     * 敏感个人信息需加密存储。
     */
    private function checkDataEncryption(): void
    {
        $userEncrypt = config('kylin-user.privacy.encrypt_id_card', false);
        $phoneEncrypt = config('kylin-user.privacy.encrypt_phone', false);

        $this->checklist[] = [
            'item' => '数据加密',
            'status' => ($userEncrypt && $phoneEncrypt) ? 'pass' : 'warning',
            'message' => ($userEncrypt && $phoneEncrypt)
                ? '身份证/手机号加密存储已启用'
                : '建议启用身份证/手机号加密存储',
            'law' => '《个人信息保护法》第五十一条',
        ];
    }

    /**
     * 检查安全配置
     */
    private function checkSecurityConfig(): void
    {
        $debugOff = ! config('app.debug');
        $httpsEnabled = config('session.secure', false);

        $this->checklist[] = [
            'item' => '安全配置',
            'status' => ($debugOff && $httpsEnabled) ? 'pass' : 'warning',
            'message' => $debugOff
                ? ($httpsEnabled ? '生产环境安全配置正确' : '建议启用 HTTPS')
                : '生产环境不应开启 DEBUG',
            'law' => '《网络安全法》第二十一条',
        ];
    }

    /**
     * 检查各模块合规状态
     */
    private function checkModuleCompliance(?string $module): void
    {
        $modules = [
            'user' => ['label' => '用户模块', 'check' => fn () => class_exists(\Kylin\User\UserServiceProvider::class)],
            'auth' => ['label' => '认证模块', 'check' => fn () => class_exists(\Kylin\Auth\AuthServiceProvider::class)],
            'audit-log' => ['label' => '审计日志模块', 'check' => fn () => class_exists(\Kylin\AuditLog\AuditLogServiceProvider::class)],
            'rbac' => ['label' => '权限管理模块', 'check' => fn () => class_exists(\Kylin\Rbac\RbacServiceProvider::class)],
            'settings' => ['label' => '系统设置模块', 'check' => fn () => class_exists(\Kylin\Settings\SettingsServiceProvider::class)],
        ];

        foreach ($modules as $name => $info) {
            if ($module && $module !== $name) {
                continue;
            }
            $loaded = $info['check']();
            $this->checklist[] = [
                'item' => $info['label'],
                'status' => $loaded ? 'pass' : 'warning',
                'message' => $loaded ? '模块已加载' : '模块未安装',
                'law' => '建议安装以增强合规性',
            ];
        }
    }
}