publicEligible() ->with([ 'user:id,username,name', 'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at', ]); } public function publicFeaturedCollections(int $limit = 18): EloquentCollection { $safeLimit = max(1, min($limit, 30)); $ttl = (int) config('collections.discovery.featured_cache_seconds', 120); $cacheKey = sprintf('collections:featured:%d', $safeLimit); return Cache::remember($cacheKey, $ttl, function () use ($safeLimit): EloquentCollection { return $this->publicBaseQuery() ->featuredPublic() ->orderByDesc('featured_at') ->orderByDesc('likes_count') ->orderByDesc('followers_count') ->orderByDesc('updated_at') ->limit($safeLimit) ->get(); }); } public function publicRecentCollections(int $limit = 8): EloquentCollection { return $this->publicBaseQuery() ->orderByDesc('published_at') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 20))) ->get(); } public function publicCollectionsByType(string $type, int $limit = 8): EloquentCollection { return $this->publicBaseQuery() ->where('type', $type) ->orderByDesc('is_featured') ->orderByDesc('followers_count') ->orderByDesc('saves_count') ->limit(max(1, min($limit, 20))) ->get(); } public function publicTrendingCollections(int $limit = 12): EloquentCollection { return $this->publicBaseQuery() ->orderByRaw('( (likes_count * 3) + (followers_count * 4) + (saves_count * 4) + (comments_count * 2) + (views_count * 0.05) ) desc') ->orderByDesc('last_activity_at') ->orderByDesc('published_at') ->limit(max(1, min($limit, 24))) ->get(); } public function publicRecentlyActiveCollections(int $limit = 8): EloquentCollection { return $this->publicBaseQuery() ->orderByDesc('last_activity_at') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 20))) ->get(); } public function publicSeasonalCollections(int $limit = 12): EloquentCollection { return $this->publicBaseQuery() ->where(function ($query): void { $query->whereNotNull('event_key') ->orWhereNotNull('season_key'); }) ->orderByDesc('is_featured') ->orderByDesc('published_at') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 24))) ->get(); } public function publicCampaignCollections(string $campaignKey, int $limit = 18): EloquentCollection { $normalizedKey = trim($campaignKey); return $this->publicBaseQuery() ->where('campaign_key', $normalizedKey) ->orderByDesc('is_featured') ->orderByDesc('ranking_score') ->orderByDesc('followers_count') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 30))) ->get(); } public function publicCampaignCollectionsByType(string $campaignKey, string $type, int $limit = 8): EloquentCollection { $normalizedKey = trim($campaignKey); return $this->publicBaseQuery() ->where('campaign_key', $normalizedKey) ->where('type', $type) ->orderByDesc('is_featured') ->orderByDesc('ranking_score') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 20))) ->get(); } public function publicTrendingCampaignCollections(string $campaignKey, int $limit = 8): EloquentCollection { $normalizedKey = trim($campaignKey); return $this->publicBaseQuery() ->where('campaign_key', $normalizedKey) ->orderByRaw('( (likes_count * 3) + (followers_count * 4) + (saves_count * 4) + (comments_count * 2) + (views_count * 0.05) ) desc') ->orderByDesc('last_activity_at') ->orderByDesc('published_at') ->limit(max(1, min($limit, 20))) ->get(); } public function publicRecentCampaignCollections(string $campaignKey, int $limit = 8): EloquentCollection { $normalizedKey = trim($campaignKey); return $this->publicBaseQuery() ->where('campaign_key', $normalizedKey) ->orderByDesc('published_at') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 20))) ->get(); } public function relatedPublicCollections(Collection $collection, int $limit = 4): EloquentCollection { return $this->publicBaseQuery() ->where('id', '!=', $collection->id) ->where(function ($query) use ($collection): void { $query->where('type', $collection->type) ->orWhere('user_id', $collection->user_id); }) ->orderByDesc('followers_count') ->orderByDesc('saves_count') ->orderByDesc('updated_at') ->limit(max(1, min($limit, 12))) ->get(); } }