<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Collection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Support\Facades\Cache;

class CollectionDiscoveryService
{
    private function publicBaseQuery()
    {
        return Collection::query()
            ->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();
    }
}
