<?php

declare(strict_types=1);

namespace App\Http\Controllers\Api\V1\Marketplace;

use App\Http\Resources\DomainCategoryResource;
use App\Models\DomainCategory;
use App\Services\Marketplace\CatalogueCache;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;

/**
 * Public category taxonomy. Browsable without an account (spec section 30).
 */
final class CategoryController extends Controller
{
    public function __construct(
        private readonly CatalogueCache $cache,
    ) {}

    public function index(Request $request): JsonResponse
    {
        $featuredOnly = $request->boolean('featured');

        /*
         * The taxonomy changes rarely but is read on nearly every page, so the
         * response is cached. Invalidation lives on the model (see
         * CatalogueObserver), so an administrator's edit is visible immediately
         * whichever code path made it.
         */
        $payload = $this->cache->remember(
            CatalogueCache::categoryKey($featuredOnly),
            CatalogueCache::CATEGORY_TTL,
            function () use ($featuredOnly, $request): array {
                $categories = DomainCategory::query()
                    ->when($featuredOnly, fn ($query) => $query->featured(), fn ($query) => $query->active())
                    ->roots()
                    ->with(['children' => fn ($query) => $query->active()])
                    ->orderBy('sort_order')
                    ->orderBy('name')
                    ->get();

                // A resolved array, never an Eloquent collection: hydrated models
                // do not survive a serialising cache driver.
                return DomainCategoryResource::collection($categories)
                    ->response($request)
                    ->getData(assoc: true);
            }
        );

        return response()->json($payload);
    }

    public function show(DomainCategory $category): JsonResponse
    {
        abort_unless($category->is_active, 404);

        return response()->json([
            'data' => DomainCategoryResource::make(
                $category->load(['children' => fn ($query) => $query->active()])
            ),
        ]);
    }
}
