<?php

declare(strict_types=1);

namespace App\Providers;

use App\Models\DomainCategory;
use App\Models\Listing;
use App\Models\Plan;
use App\Models\Tld;
use App\Observers\CatalogueObserver;
use App\Observers\ListingCounterObserver;
use App\Services\Fees\FeeResolver;
use App\Services\Marketplace\CatalogueCache;
use App\Services\Marketplace\TldSuffixes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

/**
 * Wires the marketplace domain services.
 */
class MarketplaceServiceProvider extends ServiceProvider
{
    /**
     * Models whose rows feed the cached public catalogue.
     *
     * @var list<class-string<Model>>
     */
    private const CATALOGUE_MODELS = [
        DomainCategory::class,
        Tld::class,
        Plan::class,
    ];

    public function register(): void
    {
        /*
         * Scoped rather than singleton: the resolver caches fee rules for the
         * life of a request, which is the right window for a checkout quote but
         * would go stale in a long-running queue worker.
         */
        $this->app->scoped(FeeResolver::class);

        $this->app->singleton(CatalogueCache::class);

        /*
         * Singleton rather than scoped: the suffix list is read on every domain
         * write, and unlike a fee quote it is not request-sensitive. It is
         * invalidated when a TLD changes, not by elapsed time, so a long-running
         * queue worker stays correct.
         */
        $this->app->singleton(TldSuffixes::class);
    }

    public function boot(): void
    {
        /*
         * Cache invalidation is attached to the models, so it fires whoever
         * changed the data -- an admin endpoint, a seeder, or a console command.
         * Wiring it into the controllers instead is what left the previous
         * implementation with no working invalidation path at all.
         */
        foreach (self::CATALOGUE_MODELS as $model) {
            $model::observe(CatalogueObserver::class);
        }

        /*
         * The browse-grid counters live on the catalogue tables but are driven
         * by listing writes, so they are maintained from the listing side.
         */
        Listing::observe(ListingCounterObserver::class);
    }
}
