<?php

declare(strict_types=1);

namespace App\Services\EarlyGrowth;

use App\Models\Artwork;
use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * ActivityLayer  (§8 — Optional)
 *
 * Surfaces real site-activity signals as human-readable summaries.
 * All data is genuine — no fabrication, no fake counts.
 *
 * Examples:
 *   "🔥 Trending this week: 24 artworks"
 *   "📈 Rising in Wallpapers"
 *   "🌟 5 new creators joined this month"
 *   "🎨 38 artworks published recently"
 *
 * Only active when EarlyGrowth::activityLayerEnabled() returns true.
 */
final class ActivityLayer
{
    /**
     * Return an array of activity signal strings for use in UI badges/widgets.
     * Empty array when ActivityLayer is disabled.
     *
     * @return array<int, array{icon: string, text: string, type: string}>
     */
    public function getSignals(): array
    {
        if (! EarlyGrowth::activityLayerEnabled()) {
            return [];
        }

        $ttl = (int) config('early_growth.cache_ttl.activity', 1800);

        return Cache::remember('egs.activity_signals', $ttl, fn (): array => $this->buildSignals());
    }

    // ─── Signal builders ─────────────────────────────────────────────────────

    private function buildSignals(): array
    {
        $signals = [];

        // §8: "X artworks published recently"
        $recentCount = $this->recentArtworkCount(7);
        if ($recentCount > 0) {
            $signals[] = [
                'icon' => '🎨',
                'text' => "{$recentCount} artwork" . ($recentCount !== 1 ? 's' : '') . ' published this week',
                'type' => 'uploads',
            ];
        }

        // §8: "X new creators joined this month"
        $newCreators = $this->newCreatorsThisMonth();
        if ($newCreators > 0) {
            $signals[] = [
                'icon' => '🌟',
                'text' => "{$newCreators} new creator" . ($newCreators !== 1 ? 's' : '') . ' joined this month',
                'type' => 'creators',
            ];
        }

        // §8: "Trending this week"
        $trendingCount = $this->recentArtworkCount(7);
        if ($trendingCount > 0) {
            $signals[] = [
                'icon' => '🔥',
                'text' => 'Trending this week',
                'type' => 'trending',
            ];
        }

        // §8: "Rising in Wallpapers" (first content type with recent uploads)
        $risingType = $this->getRisingContentType();
        if ($risingType !== null) {
            $signals[] = [
                'icon' => '📈',
                'text' => "Rising in {$risingType}",
                'type' => 'rising',
            ];
        }

        return array_values($signals);
    }

    /**
     * Count approved public artworks published in the last N days.
     */
    private function recentArtworkCount(int $days): int
    {
        try {
            return Artwork::query()
                ->where('is_public', true)
                ->where('is_approved', true)
                ->whereNull('deleted_at')
                ->where('published_at', '>=', now()->subDays($days))
                ->count();
        } catch (\Throwable) {
            return 0;
        }
    }

    /**
     * Count users who registered (email_verified_at set) this calendar month.
     */
    private function newCreatorsThisMonth(): int
    {
        try {
            return User::query()
                ->whereNotNull('email_verified_at')
                ->where('email_verified_at', '>=', now()->startOfMonth())
                ->count();
        } catch (\Throwable) {
            return 0;
        }
    }

    /**
     * Returns the name of the content type with the most uploads in the last 30 days,
     * or null if the content_types table isn't available.
     */
    private function getRisingContentType(): ?string
    {
        try {
            $row = DB::table('artworks')
                ->join('content_types', 'content_types.id', '=', 'artworks.content_type_id')
                ->where('artworks.is_public', true)
                ->where('artworks.is_approved', true)
                ->whereNull('artworks.deleted_at')
                ->where('artworks.published_at', '>=', now()->subDays(30))
                ->selectRaw('content_types.name, COUNT(*) as cnt')
                ->groupBy('content_types.id', 'content_types.name')
                ->orderByDesc('cnt')
                ->first();

            return $row ? (string) $row->name : null;
        } catch (\Throwable) {
            return null;
        }
    }
}
