<?php

declare(strict_types=1);


namespace Plugins\Neatstudio\BlogSeo\Http\Middleware;

use App\Models\Post;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response;

/**
 * SEO 增强中间件：注入 JSON-LD 结构化数据与 OG 标签。
 * 主题无关：直接改写响应 HTML 的 </head>。
 */
class SeoMiddleware
{
    public function handle(Request $request, Closure $next): Response
    {
        $response = $next($request);

        if (! $this->shouldEnhance($response)) {
            return $response;
        }

        $content = $response->getContent();
        $data = $this->structuredData($request);

        if (empty($data)) {
            return $response;
        }

        $jsonLd = '<script type="application/ld+json">'.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).'</script>';
        $og = $this->ogTags($request, $data);

        $content = preg_replace('/<\/head>/', $jsonLd."\n".$og."\n</head>", $content, 1);

        $response->setContent($content);

        return $response;
    }

    private function shouldEnhance(Response $response): bool
    {
        $contentType = $response->headers->get('Content-Type', '');

        // 跳过后台与静态资源
        if (str_starts_with(request()->path(), 'admin')) {
            return false;
        }

        return $response->getStatusCode() === 200
            && str_contains($contentType, 'text/html');
    }

    private function structuredData(Request $request): array
    {
        $siteName = blog_setting('site_name', config('blog.name'));
        $sameAs = $this->socialLinks();

        $route = $request->route();

        if ($route && $route->getName() === 'posts.show') {
            $slug = $route->parameter('slug');
            $post = Cache::remember('seo.post.'.$slug, now()->addHour(), function () use ($slug) {
                return Post::query()->where('slug', $slug)->first();
            });

            if ($post && $post->status === 'published') {
                $data = [
                    '@context' => 'https://schema.org',
                    '@type' => 'BlogPosting',
                    'headline' => $post->title,
                    'url' => route('posts.show', $post->slug ?: $post->id),
                    'datePublished' => $post->published_at?->toIso8601String(),
                    'dateModified' => $post->updated_at?->toIso8601String(),
                    'author' => ['@type' => 'Person', 'name' => $post->author?->name ?? $siteName] + ($sameAs ? ['sameAs' => $sameAs] : []),
                    'publisher' => ['@type' => 'Organization', 'name' => $siteName, 'url' => url('/')] + ($sameAs ? ['sameAs' => $sameAs] : []),
                    'description' => Str::limit(strip_tags($post->excerpt_or_fallback), 200),
                    'mainEntityOfPage' => route('posts.show', $post->slug ?: $post->id),
                ];

                if ($cover = $post->getFirstMedia('cover')) {
                    $data['image'] = [$cover->getUrl('card') ?: $cover->getUrl()];
                }

                return $data;
            }
        }

        return [
            '@context' => 'https://schema.org',
            '@type' => 'WebSite',
            'name' => $siteName,
            'url' => url('/'),
        ] + ($sameAs ? ['sameAs' => $sameAs] : []);
    }

    /**
     * 后台配置的社交账号 -> schema sameAs（微博/公众号/抖音/小红书/GitHub 等全平台）。
     */
    private function socialLinks(): array
    {
        return \App\Blog\Support\SocialLinks::sameAs();
    }

    private function ogTags(Request $request, array $data): string
    {
        $siteName = blog_setting('site_name', config('blog.name'));
        $isArticle = ($data['@type'] ?? '') === 'BlogPosting';
        $image = $data['image'][0] ?? null;

        $tags = [
            '<meta property="og:site_name" content="'.e($siteName).'">',
            '<meta property="og:locale" content="zh_CN">',
            '<meta property="og:type" content="'.($isArticle ? 'article' : 'website').'">',
            '<meta property="og:title" content="'.e($data['headline'] ?? $siteName).'">',
            '<meta property="og:url" content="'.e(url()->current()).'">',
            '<meta property="og:description" content="'.e($data['description'] ?? blog_setting('site_description', '')).'">',
            '<meta name="twitter:card" content="'.($image ? 'summary_large_image' : 'summary').'">',
            '<meta name="twitter:title" content="'.e($data['headline'] ?? $siteName).'">',
            '<meta name="twitter:description" content="'.e($data['description'] ?? blog_setting('site_description', '')).'">',
        ];

        if ($image) {
            $tags[] = '<meta property="og:image" content="'.e($image).'">';
            $tags[] = '<meta property="og:image:alt" content="'.e($data['headline'] ?? $siteName).'">';
            $tags[] = '<meta name="twitter:image" content="'.e($image).'">';
        }

        if ($isArticle) {
            $tags[] = '<meta property="article:published_time" content="'.e($data['datePublished'] ?? '').'">';
            $tags[] = '<meta property="article:modified_time" content="'.e($data['dateModified'] ?? '').'">';
        }

        return implode("\n", $tags);
    }
}
