<?php

namespace App\Http\Controllers;

use App\Models\MediaFile;
use App\Services\MediaThumb;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * Serves resized variants of `MediaStorage`-tracked images. Editor pulls
 * thumbs instead of original-resolution PNGs so a 3000×6500 px screenshot
 * downloads as a 480 KB thumbnail instead of a 4 MB original. First hit
 * generates + caches the variant via {@see MediaThumb::generate}; subsequent
 * hits serve straight from the local cache disk.
 *
 * **Security model:**
 *   - The `path` query param must be a known `media_files` row. Random
 *     `?path=foo/bar.png` 404s — prevents arbitrary file access via the
 *     thumbnail pipeline.
 *   - No auth required to view (same model as `/storage/{path}` direct
 *     URLs — those are publicly accessible too). Tenancy is the boundary
 *     for editor access; once a file path leaks, it's already public.
 *   - Width is constrained to the bucket allowlist so the cache directory
 *     doesn't fill up with near-duplicate widths.
 */
class MediaThumbController extends Controller
{
    public function show(Request $request): Response|BinaryFileResponse
    {
        $path = ltrim((string) $request->query('path', ''), '/');
        $width = (int) $request->query('w', 480);

        if ($path === '') {
            abort(404);
        }

        // Source must exist in the registry — otherwise the endpoint
        // becomes a generic file-read primitive against any path the
        // server-side disk can resolve (including paths outside the
        // public folder). The registry is the allowlist.
        $exists = MediaFile::query()->where('path', $path)->exists();
        if (! $exists) {
            abort(404);
        }

        $thumb = MediaThumb::generate($path, $width);
        if ($thumb === null) {
            abort(404);
        }

        $headers = [
            'Content-Type' => $thumb['mime'],
            // Long cache — `MediaStorage::delete()` calls
            // `MediaThumb::invalidate()` so a replaced source drops its
            // cached thumbs server-side. Clients see the staleness
            // window only if a CDN sits in front + ignores upstream
            // invalidation; for a CodeCanyon shared-host install
            // there's no CDN by default.
            'Cache-Control' => 'public, max-age=31536000, immutable',
        ];

        // Streaming the file from disk via BinaryFileResponse avoids
        // buffering the bytes in memory + supports Range requests for free
        // (browsers' image loader uses Range occasionally for larger PNGs).
        return response()->file($thumb['path'], $headers);
    }
}
