<?php

declare(strict_types=1);

namespace App\Services\Studio;

use App\Models\NovaCard;
use App\Models\NovaCardChallenge;
use App\Models\NovaCardChallengeEntry;
use App\Models\User;
use Illuminate\Support\Collection;

final class CreatorStudioChallengeService
{
    public function build(User $user): array
    {
        $entryCounts = NovaCardChallengeEntry::query()
            ->where('user_id', $user->id)
            ->whereNotIn('status', [NovaCardChallengeEntry::STATUS_HIDDEN, NovaCardChallengeEntry::STATUS_REJECTED])
            ->selectRaw('challenge_id, COUNT(*) as aggregate')
            ->groupBy('challenge_id')
            ->pluck('aggregate', 'challenge_id');

        $recentEntriesQuery = NovaCardChallengeEntry::query()
            ->with(['challenge', 'card'])
            ->where('user_id', $user->id)
            ->whereNotIn('status', [NovaCardChallengeEntry::STATUS_HIDDEN, NovaCardChallengeEntry::STATUS_REJECTED])
            ->whereHas('challenge')
            ->whereHas('card');

        $recentEntries = $recentEntriesQuery
            ->latest('created_at')
            ->limit(8)
            ->get()
            ->map(fn (NovaCardChallengeEntry $entry): array => $this->mapEntry($entry))
            ->values()
            ->all();

        $activeChallenges = NovaCardChallenge::query()
            ->whereIn('status', [NovaCardChallenge::STATUS_ACTIVE, NovaCardChallenge::STATUS_COMPLETED])
            ->orderByRaw('CASE WHEN featured = 1 THEN 0 ELSE 1 END')
            ->orderByRaw("CASE WHEN status = 'active' THEN 0 ELSE 1 END")
            ->orderBy('ends_at')
            ->orderByDesc('starts_at')
            ->limit(10)
            ->get()
            ->map(fn (NovaCardChallenge $challenge): array => $this->mapChallenge($challenge, $entryCounts))
            ->values();

        $spotlight = $activeChallenges->first();

        $cardLeaders = NovaCard::query()
            ->where('user_id', $user->id)
            ->whereNull('deleted_at')
            ->where('challenge_entries_count', '>', 0)
            ->orderByDesc('challenge_entries_count')
            ->orderByDesc('published_at')
            ->limit(6)
            ->get()
            ->map(fn (NovaCard $card): array => [
                'id' => (int) $card->id,
                'title' => (string) $card->title,
                'status' => (string) $card->status,
                'challenge_entries_count' => (int) $card->challenge_entries_count,
                'views_count' => (int) $card->views_count,
                'comments_count' => (int) $card->comments_count,
                'preview_url' => route('studio.cards.preview', ['id' => $card->id]),
                'edit_url' => route('studio.cards.edit', ['id' => $card->id]),
                'analytics_url' => route('studio.cards.analytics', ['id' => $card->id]),
            ])
            ->values()
            ->all();

        $cardsAvailable = (int) NovaCard::query()
            ->where('user_id', $user->id)
            ->whereNull('deleted_at')
            ->whereNotIn('status', [NovaCard::STATUS_HIDDEN, NovaCard::STATUS_REJECTED])
            ->count();

        $entryCount = (int) $entryCounts->sum();
        $featuredEntries = (int) (clone $recentEntriesQuery)
            ->whereIn('status', [NovaCardChallengeEntry::STATUS_FEATURED, NovaCardChallengeEntry::STATUS_WINNER])
            ->count();
        $winnerEntries = (int) (clone $recentEntriesQuery)
            ->where('status', NovaCardChallengeEntry::STATUS_WINNER)
            ->count();

        return [
            'summary' => [
                'active_challenges' => (int) $activeChallenges->where('status', NovaCardChallenge::STATUS_ACTIVE)->count(),
                'joined_challenges' => (int) $entryCounts->keys()->count(),
                'entries_submitted' => $entryCount,
                'featured_entries' => $featuredEntries,
                'winner_entries' => $winnerEntries,
                'cards_available' => $cardsAvailable,
            ],
            'spotlight' => $spotlight,
            'active_challenges' => $activeChallenges->all(),
            'recent_entries' => $recentEntries,
            'card_leaders' => $cardLeaders,
            'reminders' => $this->reminders($cardsAvailable, $entryCount, $activeChallenges, $featuredEntries, $winnerEntries),
        ];
    }

    private function mapChallenge(NovaCardChallenge $challenge, Collection $entryCounts): array
    {
        return [
            'id' => (int) $challenge->id,
            'slug' => (string) $challenge->slug,
            'title' => (string) $challenge->title,
            'description' => $challenge->description,
            'prompt' => $challenge->prompt,
            'status' => (string) $challenge->status,
            'official' => (bool) $challenge->official,
            'featured' => (bool) $challenge->featured,
            'entries_count' => (int) $challenge->entries_count,
            'starts_at' => $challenge->starts_at?->toIso8601String(),
            'ends_at' => $challenge->ends_at?->toIso8601String(),
            'is_joined' => $entryCounts->has($challenge->id),
            'submission_count' => (int) ($entryCounts->get($challenge->id) ?? 0),
            'url' => route('cards.challenges.show', ['slug' => $challenge->slug]),
        ];
    }

    private function mapEntry(NovaCardChallengeEntry $entry): array
    {
        return [
            'id' => (int) $entry->id,
            'status' => (string) $entry->status,
            'submitted_at' => $entry->created_at?->toIso8601String(),
            'note' => $entry->note,
            'challenge' => [
                'id' => (int) $entry->challenge_id,
                'title' => (string) ($entry->challenge?->title ?? 'Challenge'),
                'status' => (string) ($entry->challenge?->status ?? ''),
                'official' => (bool) ($entry->challenge?->official ?? false),
                'url' => $entry->challenge ? route('cards.challenges.show', ['slug' => $entry->challenge->slug]) : route('cards.challenges'),
            ],
            'card' => [
                'id' => (int) $entry->card_id,
                'title' => (string) ($entry->card?->title ?? 'Card'),
                'preview_url' => $entry->card ? route('studio.cards.preview', ['id' => $entry->card->id]) : route('studio.cards.index'),
                'edit_url' => $entry->card ? route('studio.cards.edit', ['id' => $entry->card->id]) : route('studio.cards.create'),
                'analytics_url' => $entry->card ? route('studio.cards.analytics', ['id' => $entry->card->id]) : route('studio.cards.index'),
            ],
        ];
    }

    private function reminders(int $cardsAvailable, int $entryCount, Collection $activeChallenges, int $featuredEntries, int $winnerEntries): array
    {
        $items = [];

        if ($cardsAvailable === 0) {
            $items[] = [
                'title' => 'Create a card to join challenges',
                'body' => 'Challenge participation starts from published or ready-to-share cards inside Studio.',
                'href' => route('studio.cards.create'),
                'cta' => 'Create card',
            ];
        }

        if ($cardsAvailable > 0 && $entryCount === 0 && $activeChallenges->where('status', NovaCardChallenge::STATUS_ACTIVE)->isNotEmpty()) {
            $items[] = [
                'title' => 'You have active challenge windows open',
                'body' => 'Submit an existing card to the current prompt lineup before the next window closes.',
                'href' => route('studio.cards.index'),
                'cta' => 'Open cards',
            ];
        }

        if ($featuredEntries > 0) {
            $items[] = [
                'title' => 'Featured challenge entries are live',
                'body' => 'Review promoted submissions and keep those cards ready for profile, editorial, or follow-up pushes.',
                'href' => route('studio.featured'),
                'cta' => 'Manage featured',
            ];
        }

        if ($winnerEntries > 0) {
            $items[] = [
                'title' => 'Winning challenge work deserves a spotlight',
                'body' => 'Use featured content and profile curation to extend the reach of cards that already placed well.',
                'href' => route('studio.profile'),
                'cta' => 'Open profile',
            ];
        }

        if ($activeChallenges->isNotEmpty()) {
            $items[] = [
                'title' => 'Public challenge archive stays one click away',
                'body' => 'Use the public challenge directory to review prompts, reference past winners, and see how new runs are framed.',
                'href' => route('cards.challenges'),
                'cta' => 'Browse challenges',
            ];
        }

        return collect($items)->take(4)->values()->all();
    }
}