<?php

declare(strict_types=1);

namespace App\Blog\Support;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Symfony\Component\HttpFoundation\Response;

/**
 * 前台页面响应缓存：
 * - 仅缓存匿名 GET 请求的 HTML 页面（首页/列表/文章/归档/标签等）
 * - 登录用户、后台、API、动态端点不缓存
 * - 浏览量走独立的 /track-view 端点，不受整页缓存影响
 */
class PageCacheMiddleware
{
    public const TAG = 'pages';

    public function handle(Request $request, \Closure $next): Response
    {
        if (! $this->shouldCache($request)) {
            return $next($request);
        }

        $key = $this->key($request);
        $ttl = (int) config('blog.page_cache_ttl', 300);

        if ($cached = Cache::get($key)) {
            return response($cached['body'], 200, [
                'Content-Type' => $cached['type'],
                'Cache-Control' => 'public, max-age='.$ttl,
            ]);
        }

        $response = $next($request);

        if ($response->getStatusCode() === 200) {
            Cache::put($key, [
                'body' => $response->getContent(),
                'type' => $response->headers->get('Content-Type') ?: 'text/html; charset=utf-8',
            ], $ttl);
            self::rememberKey($key);
        }

        return $response;
    }

    public static function flush(): void
    {
        foreach ((array) Cache::get(self::TAG.'_keys', []) as $key) {
            Cache::forget($key);
        }

        Cache::forget(self::TAG.'_keys');
    }

    public static function count(): int
    {
        return count((array) Cache::get(self::TAG.'_keys', []));
    }

    private static function rememberKey(string $key): void
    {
        $keys = (array) Cache::get(self::TAG.'_keys', []);
        $keys[$key] = true;
        Cache::put(self::TAG.'_keys', $keys, now()->addDay());
    }

    private function shouldCache(Request $request): bool
    {
        if (! $request->isMethod('GET')) {
            return false;
        }

        if (auth()->check()) {
            return false;
        }

        $path = $request->path();

        if (str_starts_with($path, 'admin') || str_starts_with($path, 'api') || str_starts_with($path, 'themes')) {
            return false;
        }

        // 动态端点
        if (str_starts_with($path, 'track-view')) {
            return false;
        }

        return true;
    }

    private function key(Request $request): string
    {
        return self::TAG.':'.md5($request->fullUrl());
    }
}
