<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

/**
 * 子域名跨域 CORS 中间件
 *
 * 当绑定了子域名的应用（如 bbs.cmspro.com）通过 AJAX 请求主域名 API 时，
 * 需要返回正确的 CORS 响应头。
 *
 * 使用 withCredentials=true 时，Access-Control-Allow-Origin 不能为 *，
 * 必须设置为请求来源的具体 origin。
 *
 * 当前仅放行签到状态查询 API，便于论坛子域名签到弹窗关闭后刷新状态。
 */
class AllowSubdomainCors
{
    /**
     * 允许跨域访问的 API 路径前缀
     */
    protected array $allowedPaths = [
        'api/user/cmspro/signin/status',
    ];

    /**
     * 处理传入请求
     */
    public function handle(Request $request, Closure $next)
    {
        $origin = $request->header('Origin', '');

        // 无 Origin 头（非跨域请求），直接放行
        if (empty($origin)) {
            return $next($request);
        }

        // 检查请求路径是否在白名单中
        $path = $request->decodedPath();
        $matched = false;
        foreach ($this->allowedPaths as $allowed) {
            if (str_ends_with($allowed, '/*')) {
                $prefix = rtrim($allowed, '/*');
                if (str_starts_with($path, $prefix)) {
                    $matched = true;
                    break;
                }
            } elseif ($path === $allowed) {
                $matched = true;
                break;
            }
        }

        if (!$matched) {
            return $next($request);
        }

        // 检查 origin 是否为已绑定的子域名
        $boundDomains = \App\Providers\AppServiceProvider::getBoundDomains();
        $allowedOrigin = null;

        foreach ($boundDomains as $domain) {
            $originHost = parse_url($origin, PHP_URL_HOST);
            if ($originHost === $domain) {
                $allowedOrigin = $origin;
                break;
            }
        }

        if (!$allowedOrigin) {
            return $next($request);
        }

        // 预检请求（OPTIONS）：直接返回 204，不进入路由层
        // 若不拦截，OPTIONS 请求会被 auth:web 中间件重定向到登录页（无 cookie），
        // 浏览器收到 302 而非 204/200，判定 CORS 失败。
        if ($request->isMethod('OPTIONS')) {
            return response('', 204, [
                'Access-Control-Allow-Origin' => $allowedOrigin,
                'Access-Control-Allow-Credentials' => 'true',
                'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS',
                'Access-Control-Allow-Headers' => 'Content-Type, X-Requested-With, Authorization',
                'Access-Control-Max-Age' => '86400',
            ]);
        }

        /** @var \Illuminate\Http\Response $response */
        $response = $next($request);

        $response->headers->set('Access-Control-Allow-Origin', $allowedOrigin);
        $response->headers->set('Access-Control-Allow-Credentials', 'true');

        return $response;
    }
}
