<?php

declare(strict_types=1);

namespace App\Http\Controllers\RSS;

use App\Http\Controllers\Controller;
use App\Models\Artwork;
use App\Services\EarlyGrowth\AdaptiveTimeWindow;
use App\Services\RSS\RSSFeedBuilder;
use Illuminate\Http\Response;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * DiscoverFeedController
 *
 * Powers the /rss/discover/* feeds (spec §3.2).
 *
 * GET /rss/discover            → fresh/latest (default)
 * GET /rss/discover/trending   → trending by trending_score_7d
 * GET /rss/discover/fresh      → latest published
 * GET /rss/discover/rising     → rising by heat_score
 */
final class DiscoverFeedController extends Controller
{
    public function __construct(
        private readonly RSSFeedBuilder $builder,
        private readonly AdaptiveTimeWindow $timeWindow,
    ) {}

    /** /rss/discover → redirect to fresh */
    public function index(): Response
    {
        return $this->fresh();
    }

    /** /rss/discover/trending */
    public function trending(): Response
    {
        $feedUrl  = url('/rss/discover/trending');
        $artworks = Cache::remember('rss:discover:trending', 600, fn () =>
            Artwork::public()->published()
                ->with(['user:id,username', 'categories:id,name,slug,content_type_id'])
                ->leftJoin('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id')
                ->orderByDesc('artwork_stats.trending_score_7d')
                ->orderByDesc('artworks.published_at')
                ->select('artworks.*')
                ->limit(RSSFeedBuilder::FEED_LIMIT)
                ->get()
        );

        return $this->builder->buildFromArtworks(
            'Trending Artworks',
            'The most-viewed and trending artworks on Skinbase over the past 7 days.',
            $feedUrl,
            $artworks,
        );
    }

    /** /rss/discover/fresh */
    public function fresh(): Response
    {
        $feedUrl  = url('/rss/discover/fresh');
        $artworks = Cache::remember('rss:discover:fresh', 300, fn () =>
            Artwork::public()->published()
                ->with(['user:id,username', 'categories:id,name,slug,content_type_id'])
                ->latest('published_at')
                ->limit(RSSFeedBuilder::FEED_LIMIT)
                ->get()
        );

        return $this->builder->buildFromArtworks(
            'Fresh Uploads',
            'The latest artworks just published on Skinbase.',
            $feedUrl,
            $artworks,
        );
    }

    /** /rss/discover/rising */
    public function rising(): Response
    {
        $feedUrl  = url('/rss/discover/rising');
        $windowDays = $this->timeWindow->getTrendingWindowDays(30);
        $artworks = Cache::remember(
            "rss:discover:rising.{$windowDays}d",
            600,
            function () use ($windowDays) {
                $artworks = $this->risingArtworks($windowDays);

                if ($this->collectionHasNoRisingMomentum($artworks)) {
                    return $this->risingLowSignalArtworks($windowDays);
                }

                return $artworks;
            }
        );

        return $this->builder->buildFromArtworks(
            'Rising Artworks',
            'Fastest-growing artworks gaining momentum on Skinbase right now.',
            $feedUrl,
            $artworks,
        );
    }

    private function risingArtworks(int $windowDays): Collection
    {
        $cutoff = now()->subDays($windowDays)->startOfDay();

        return Artwork::public()
            ->published()
            ->with(['user:id,username', 'categories:id,name,slug,content_type_id'])
            ->leftJoin('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id')
            ->select('artworks.*')
            ->selectRaw('COALESCE(artwork_stats.heat_score, 0) as heat_score')
            ->selectRaw('COALESCE(artwork_stats.engagement_velocity, 0) as engagement_velocity')
            ->where('artworks.published_at', '>=', $cutoff)
            ->orderByDesc('artwork_stats.heat_score')
            ->orderByDesc('artwork_stats.engagement_velocity')
            ->orderByDesc('artworks.published_at')
            ->orderByDesc('artworks.id')
            ->limit(RSSFeedBuilder::FEED_LIMIT)
            ->get();
    }

    private function risingLowSignalArtworks(int $windowDays): Collection
    {
        $cutoff = now()->subDays($windowDays)->startOfDay();

        return Artwork::public()
            ->published()
            ->with(['user:id,username', 'categories:id,name,slug,content_type_id'])
            ->leftJoin('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id')
            ->leftJoinSub($this->risingRecentActivitySubquery(), 'recent_rising_activity', function ($join): void {
                $join->on('recent_rising_activity.artwork_id', '=', 'artworks.id');
            })
            ->select('artworks.*')
            ->selectRaw('COALESCE(artwork_stats.heat_score, 0) as heat_score')
            ->selectRaw('COALESCE(artwork_stats.engagement_velocity, 0) as engagement_velocity')
            ->selectRaw('COALESCE(recent_rising_activity.recent_signal_24h, 0) as recent_signal_24h')
            ->where('artworks.published_at', '>=', $cutoff)
            ->orderByDesc('recent_signal_24h')
            ->orderByDesc('artworks.published_at')
            ->orderByDesc('artworks.id')
            ->limit(RSSFeedBuilder::FEED_LIMIT)
            ->get();
    }

    private function collectionHasNoRisingMomentum(Collection $artworks): bool
    {
        if ($artworks->isEmpty()) {
            return false;
        }

        return $artworks->every(function (Artwork $artwork): bool {
            return (float) ($artwork->heat_score ?? 0) <= 0
                && (float) ($artwork->engagement_velocity ?? 0) <= 0;
        });
    }

    private function risingRecentActivitySubquery()
    {
        $since = now()->startOfHour()->subHours(24);

        return DB::table('artwork_metric_snapshots_hourly as rising_snapshots')
            ->selectRaw('rising_snapshots.artwork_id')
            ->selectRaw('(
                COALESCE(MAX(rising_snapshots.views_count) - MIN(rising_snapshots.views_count), 0)
                + (COALESCE(MAX(rising_snapshots.downloads_count) - MIN(rising_snapshots.downloads_count), 0) * 3)
                + (COALESCE(MAX(rising_snapshots.favourites_count) - MIN(rising_snapshots.favourites_count), 0) * 4)
                + (COALESCE(MAX(rising_snapshots.comments_count) - MIN(rising_snapshots.comments_count), 0) * 5)
                + (COALESCE(MAX(rising_snapshots.shares_count) - MIN(rising_snapshots.shares_count), 0) * 6)
            ) as recent_signal_24h')
            ->where('rising_snapshots.bucket_hour', '>=', $since)
            ->groupBy('rising_snapshots.artwork_id');
    }
}
