<?php

declare(strict_types=1);

namespace App\Services\Academy;

use App\Models\AcademyCategory;
use App\Models\AcademyCourse;
use App\Models\AcademyChallenge;
use App\Models\AcademyLesson;
use App\Models\AcademyPromptTemplate;
use Illuminate\Support\Facades\Cache;

final class AcademyCacheService
{
    private const HOME_KEY = 'academy.home';
    private const FEATURED_LESSONS_KEY = 'academy.featured_lessons';
    private const FEATURED_COURSES_KEY = 'academy.featured_courses';
    private const PUBLISHED_COURSES_KEY = 'academy.published_courses';
    private const FEATURED_PROMPTS_KEY = 'academy.featured_prompts';
    private const FEATURED_CHALLENGES_KEY = 'academy.featured_challenges';
    private const CATEGORIES_KEY = 'academy.categories';

    public function homePayload(callable $resolver): array
    {
        return Cache::remember(self::HOME_KEY, $this->ttl(), $resolver);
    }

    public function featuredLessons(): array
    {
        return Cache::remember(self::FEATURED_LESSONS_KEY, $this->ttl(), static fn (): array => AcademyLesson::query()
            ->with('category')
            ->active()
            ->published()
            ->where('featured', true)
            ->orderedForCourse()
            ->limit(6)
            ->get()
            ->all());
    }

    public function featuredCourses(): array
    {
        return Cache::remember(self::FEATURED_COURSES_KEY, $this->ttl(), static fn (): array => AcademyCourse::query()
            ->published()
            ->featured()
            ->ordered()
            ->limit(6)
            ->get()
            ->all());
    }

    public function publishedCourses(): array
    {
        return Cache::remember(self::PUBLISHED_COURSES_KEY, $this->ttl(), static fn (): array => AcademyCourse::query()
            ->published()
            ->ordered()
            ->get()
            ->all());
    }

    public function featuredPrompts(): array
    {
        return Cache::remember(self::FEATURED_PROMPTS_KEY, $this->ttl(), static fn (): array => AcademyPromptTemplate::query()
            ->with('category')
            ->active()
            ->published()
            ->where(function ($query): void {
                $query->where('featured', true)->orWhere('prompt_of_week', true);
            })
            ->latest('published_at')
            ->limit(6)
            ->get()
            ->all());
    }

    public function featuredChallenges(): array
    {
        return Cache::remember(self::FEATURED_CHALLENGES_KEY, $this->ttl(), static fn (): array => AcademyChallenge::query()
            ->publiclyVisible()
            ->where('featured', true)
            ->latest('starts_at')
            ->limit(6)
            ->get()
            ->all());
    }

    public function categoriesByType(string $type): array
    {
        $cacheKey = self::CATEGORIES_KEY . '.' . $type;

        return Cache::remember($cacheKey, $this->ttl(), static fn (): array => AcademyCategory::query()
            ->active()
            ->where('type', $type)
            ->orderBy('order_num')
            ->orderBy('name')
            ->get()
            ->all());
    }

    public function clearAll(): void
    {
        Cache::forget(self::HOME_KEY);
        Cache::forget(self::FEATURED_LESSONS_KEY);
        Cache::forget(self::FEATURED_COURSES_KEY);
        Cache::forget(self::PUBLISHED_COURSES_KEY);
        Cache::forget(self::FEATURED_PROMPTS_KEY);
        Cache::forget(self::FEATURED_CHALLENGES_KEY);

        foreach (['lesson', 'prompt', 'challenge', 'pack'] as $type) {
            Cache::forget(self::CATEGORIES_KEY . '.' . $type);
        }
    }

    private function ttl(): int
    {
        return max(60, (int) config('academy.cache.ttl', 1800));
    }
}