<?php

declare(strict_types=1);

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Services\ErrorSuggestionService;
use App\Services\NotFoundLogger;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

/**
 * ErrorController
 *
 * Handles contextual 404 rendering.
 * Invoked from bootstrap/app.php exception handler for web 404s.
 *
 * Pattern detection:
 *   /blog/*           → blog-not-found      (latest posts)
 *   /tag/*            → tag-not-found       (similar + trending tags)
 *   /@username        → creator-not-found   (trending creators)
 *   /pages/*          → page-not-found
 *   /about|/help etc. → page-not-found
 *   everything else   → generic 404         (trending artworks + tags)
 */
final class ErrorController extends Controller
{
    public function __construct(
        private readonly ErrorSuggestionService $suggestions,
        private readonly NotFoundLogger $logger,
    ) {}

    public function handleNotFound(Request $request): Response|JsonResponse
    {
        // For JSON / Inertia API requests return a minimal JSON 404.
        if ($request->expectsJson() || $request->header('X-Inertia')) {
            return response()->json(['message' => 'Not Found'], 404);
        }

        // Log every 404 hit for later analysis.
        try {
            $this->logger->log404($request);
        } catch (\Throwable) {
            // Never let the logger itself break the error page.
        }

        $path = ltrim($request->path(), '/');

        // ── /blog/* ──────────────────────────────────────────────────────────
        if (str_starts_with($path, 'blog/')) {
            return response(view('errors.contextual.blog-not-found', [
                'latestPosts' => $this->safeFetch(fn () => $this->suggestions->latestBlogPosts()),
            ]), 404);
        }

        // ── /tag/* ───────────────────────────────────────────────────────────
        if (str_starts_with($path, 'tag/')) {
            $slug = ltrim(substr($path, 4), '/');
            return response(view('errors.contextual.tag-not-found', [
                'requestedSlug' => $slug,
                'similarTags'   => $this->safeFetch(fn () => $this->suggestions->similarTags($slug)),
                'trendingTags'  => $this->safeFetch(fn () => $this->suggestions->trendingTags()),
            ]), 404);
        }

        // ── /@username  or  /creator/* ───────────────────────────────────────
        if (str_starts_with($path, '@') || str_starts_with($path, 'creator/')) {
            $username = str_starts_with($path, '@') ? substr($path, 1) : null;
            return response(view('errors.contextual.creator-not-found', [
                'requestedUsername'  => $username,
                'trendingCreators'   => $this->safeFetch(fn () => $this->suggestions->trendingCreators()),
                'recentCreators'     => $this->safeFetch(fn () => $this->suggestions->recentlyJoinedCreators()),
            ]), 404);
        }

        // ── /{contentType}/{category}/{artwork-slug} — artwork not found ──────
        if (preg_match('#^(wallpapers|skins|photography|other)/#', $path)) {
            return response(view('errors.contextual.artwork-not-found', [
                'trendingArtworks' => $this->safeFetch(fn () => $this->suggestions->trendingArtworks()),
            ]), 404);
        }

        // ── /pages/*  or  /about | /help | /contact | /legal/* ───────────────
        if (
            str_starts_with($path, 'pages/')
            || in_array($path, ['about', 'help', 'contact', 'faq', 'staff', 'privacy-policy', 'terms-of-service', 'rules-and-guidelines'])
            || str_starts_with($path, 'legal/')
        ) {
            return response(view('errors.contextual.page-not-found'), 404);
        }

        // ── Generic 404 ───────────────────────────────────────────────────────
        return response(view('errors.404', [
            'trendingArtworks' => $this->safeFetch(fn () => $this->suggestions->trendingArtworks()),
            'trendingTags'     => $this->safeFetch(fn () => $this->suggestions->trendingTags()),
        ]), 404);
    }

    /**
     * Silently catch any DB/cache error so the error page itself never crashes.
     */
    private function safeFetch(callable $fn): mixed
    {
        try {
            return $fn();
        } catch (\Throwable) {
            return collect();
        }
    }
}
