<?php

namespace Kylin\Core\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * 安全响应头中间件
 *
 * 依据等保 2.0 (GB/T 22239) 8.1.4.3 通信安全要求，
 * 为所有 HTTP 响应添加安全相关的 HTTP 头，防止常见 Web 攻击：
 *  - X-Content-Type-Options: nosniff —— 禁止 MIME 类型嗅探
 *  - X-Frame-Options: DENY —— 防止点击劫持
 *  - X-XSS-Protection: 1; mode=block —— 启用 XSS 过滤器
 *  - Referrer-Policy: strict-origin-when-cross-origin —— 控制 Referer 信息
 *  - Permissions-Policy: 禁用摄像头/麦克风/定位 —— 限制浏览器 API 权限
 *  - Content-Security-Policy: 默认策略 —— 防御 XSS 和数据注入攻击
 *  - Strict-Transport-Security: 强制 HTTPS —— 生产环境启用 HSTS
 *
 * 使用方式：路由中通过 middleware('kylin.security') 注册
 */
class SecurityHeaders
{
    /**
     * 处理请求并添加安全响应头
     *
     * @param  Request  $request 当前请求
     * @param  Closure  $next    下一个中间件/处理器
     * @return Response
     */
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        $config = config('kylin-core.security_headers', []);

        // 基础安全响应头
        $response->headers->set('X-Content-Type-Options', $config['x_content_type_options'] ?? 'nosniff');
        $response->headers->set('X-Frame-Options', $config['x_frame_options'] ?? 'DENY');
        $response->headers->set('X-XSS-Protection', $config['x_xss_protection'] ?? '1; mode=block');
        $response->headers->set('Referrer-Policy', $config['referrer_policy'] ?? 'strict-origin-when-cross-origin');
        $response->headers->set('Permissions-Policy', $config['permissions_policy'] ?? 'geolocation=(), microphone=(), camera=()');

        // Content-Security-Policy (CSP) —— 防御 XSS 和数据注入攻击
        if (! empty($config['csp']['enabled'])) {
            $response->headers->set('Content-Security-Policy', $this->buildCspHeader($config['csp']));
        }

        // Strict-Transport-Security (HSTS) —— 生产环境强制 HTTPS
        if (! empty($config['hsts']['enabled'])) {
            $hstsValue = 'max-age=' . ($config['hsts']['max_age'] ?? 31536000);
            if (! empty($config['hsts']['include_subdomains'])) {
                $hstsValue .= '; includeSubDomains';
            }
            if (! empty($config['hsts']['preload'])) {
                $hstsValue .= '; preload';
            }
            $response->headers->set('Strict-Transport-Security', $hstsValue);
        }

        return $response;
    }

    /**
     * 构建 Content-Security-Policy 响应头值
     *
     * 依据 OWASP Top 10 (2021) A05 安全配置错误，
     * CSP 是防御 XSS 和数据注入攻击的核心机制。
     *
     * @param array $cspConfig CSP 配置
     * @return string
     */
    private function buildCspHeader(array $cspConfig): string
    {
        $directives = [];

        $mappings = [
            'default_src' => 'default-src',
            'script_src' => 'script-src',
            'style_src' => 'style-src',
            'img_src' => 'img-src',
            'font_src' => 'font-src',
            'connect_src' => 'connect-src',
            'frame_src' => 'frame-src',
            'object_src' => 'object-src',
        ];

        foreach ($mappings as $configKey => $directiveName) {
            if (! empty($cspConfig[$configKey])) {
                $directives[] = $directiveName . ' ' . $cspConfig[$configKey];
            }
        }

        return implode('; ', $directives);
    }
}
