quality->scores($collection); return [ 'quality_score' => $scores['quality_score'], 'ranking_score' => $scores['ranking_score'], 'missing_metadata' => $this->missingMetadata($collection), 'attention_flags' => $this->attentionFlags($collection), 'campaign_summary' => $this->campaigns->campaignSummary($collection), 'suggested_surface_assignments' => $this->campaigns->suggestedSurfaceAssignments($collection), 'suggested_cover' => $this->curation->suggestCover($collection), 'suggested_summary' => $this->curation->suggestSummary($collection), 'suggested_related_collections' => $this->recommendations->relatedPublicCollections($collection, 4)->map(fn (Collection $item) => [ 'id' => (int) $item->id, 'title' => $item->title, 'slug' => $item->slug, ])->values()->all(), 'source' => 'editorial-automation-v1', ]; } private function missingMetadata(Collection $collection): array { $missing = []; if (blank($collection->summary)) { $missing[] = 'Add a sharper summary for social previews and homepage modules.'; } if (! $collection->resolvedCoverArtwork(false)) { $missing[] = 'Choose a cover artwork to strengthen click-through and placement eligibility.'; } if ((int) $collection->artworks_count < 4) { $missing[] = 'Expand the collection with a few more artworks to improve curation depth.'; } if (blank($collection->campaign_key) && blank($collection->event_key) && blank($collection->season_key)) { $missing[] = 'Set campaign or seasonal metadata if this collection should power event-aware discovery.'; } if (blank($collection->brand_safe_status) && (bool) $collection->commercial_eligibility) { $missing[] = 'Mark brand-safe status before using this collection for commercial or partner-facing placements.'; } return $missing; } private function attentionFlags(Collection $collection): array { $flags = []; if ($collection->last_activity_at?->lt(now()->subDays(90)) && $collection->isPubliclyAccessible()) { $flags[] = [ 'key' => 'stale_collection', 'severity' => 'medium', 'message' => 'This public collection has not been updated recently and may need editorial review.', ]; } if ($this->hasDuplicateTitleWithinOwner($collection)) { $flags[] = [ 'key' => 'possible_duplicate', 'severity' => 'medium', 'message' => 'Another collection from the same owner has the same title, so this set may duplicate an existing curation theme.', ]; } if ($collection->moderation_status !== Collection::MODERATION_ACTIVE) { $flags[] = [ 'key' => 'moderation_block', 'severity' => 'high', 'message' => 'Moderation status currently blocks this collection from editorial promotion.', ]; } if ($collection->unpublished_at?->between(now(), now()->addDays(14))) { $flags[] = [ 'key' => 'campaign_expiring', 'severity' => 'low', 'message' => 'This collection is approaching the end of its scheduled campaign window.', ]; } return $flags; } private function hasDuplicateTitleWithinOwner(Collection $collection): bool { return Collection::query() ->where('id', '!=', $collection->id) ->where('user_id', $collection->user_id) ->whereRaw('LOWER(title) = ?', [mb_strtolower(trim((string) $collection->title))]) ->exists(); } }