<?php

declare(strict_types=1);

namespace App\Http\Controllers\Academy;

use App\Http\Controllers\Controller;
use App\Models\AcademyCourse;
use App\Models\AcademyCourseLesson;
use App\Services\Academy\AcademyAccessService;
use App\Services\Academy\AcademyInteractionService;
use App\Services\Academy\AcademyCacheService;
use App\Services\Academy\AcademyCourseNavigationService;
use App\Services\Academy\AcademyCourseProgressService;
use App\Support\AcademyAnalytics\AcademyAnalyticsContentType;
use App\Support\Seo\SeoFactory;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

final class AcademyCourseController extends Controller
{
    public function __construct(
        private readonly AcademyAccessService $access,
        private readonly AcademyCacheService $cache,
        private readonly AcademyCourseNavigationService $navigation,
        private readonly AcademyCourseProgressService $progress,
        private readonly AcademyInteractionService $interactions,
    ) {
    }

    public function index(Request $request): Response
    {
        abort_unless((bool) config('academy.enabled', true), 404);

        $filters = $request->validate([
            'difficulty' => ['nullable', 'string', 'max:40'],
            'access' => ['nullable', 'string', 'max:40'],
        ]);

        $query = AcademyCourse::query()->published()->ordered();

        if (filled($filters['difficulty'] ?? null)) {
            $query->where('difficulty', $filters['difficulty']);
        }

        if (filled($filters['access'] ?? null)) {
            $query->where('access_level', $filters['access']);
        }

        $courses = $query->paginate(12)->withQueryString();
        $courses->getCollection()->transform(function (AcademyCourse $course) use ($request): array {
            return $this->access->coursePayload($course, $request->user(), [
                'progress' => $this->progress->getProgress($request->user(), $course),
            ]);
        });

        $featuredCourses = collect($this->cache->featuredCourses())->map(fn (AcademyCourse $course): array => $this->access->coursePayload($course, $request->user(), [
            'progress' => $this->progress->getProgress($request->user(), $course),
        ]))->values();

        $seoCourses = $featuredCourses
            ->concat(collect($courses->items()))
            ->unique(fn (array $course): string => (string) ($course['slug'] ?? ''))
            ->values();

        $seo = app(SeoFactory::class)
            ->academyCourseListingPage(
                'Academy Courses — Skinbase',
                'Follow guided Skinbase AI Academy courses built from reusable lessons, chapters, and creator workflows.',
                route('academy.courses.index', $request->query()),
                $seoCourses,
                [
                    ['name' => 'Academy', 'url' => route('academy.index')],
                    ['name' => 'Courses', 'url' => route('academy.courses.index')],
                ],
            )
            ->toArray();

        return Inertia::render('Academy/CoursesIndex', [
            'seo' => $seo,
            'title' => 'Academy courses',
            'description' => 'Guided learning paths built from reusable Academy lessons and creator workflows.',
            'items' => $courses,
            'featuredCourses' => $featuredCourses->all(),
            'filters' => $filters,
            'pricingUrl' => route('academy.pricing'),
            'lessonsUrl' => route('academy.lessons.index'),
            'promptLibraryUrl' => route('academy.prompts.index'),
            'academyAccess' => array_merge($this->access->accessSummary($request->user()), [
                'billingUrl' => $request->user() && (bool) config('academy_billing.enabled', false)
                    ? route('academy.billing.account')
                    : route('academy.pricing'),
            ]),
            'analytics' => [
                'enabled' => true,
                'contentType' => null,
                'contentId' => null,
                'eventUrl' => route('academy.analytics.events.store'),
                'pageName' => 'academy_courses_index',
                'isPremium' => false,
                'isGuest' => $request->user() === null,
                'isSubscriber' => $request->user()?->hasAcademyCreatorAccess() || $request->user()?->hasAcademyProAccess(),
            ],
        ])->rootView('collections');
    }

    public function show(Request $request, AcademyCourse $course): Response
    {
        abort_unless((bool) config('academy.enabled', true), 404);
        abort_unless($course->isPublished(), 404);

        $course->load(['sections', 'courseLessons.section', 'courseLessons.lesson.category']);

        $progress = $this->progress->getProgress($request->user(), $course);
        $completedLessonIds = $request->user() ? $this->progress->getCompletedLessonIds($request->user(), $course) : [];
        $orderedLessons = $this->navigation->orderedCourseLessons($course);
        $stepMeta = $orderedLessons
            ->values()
            ->mapWithKeys(fn (AcademyCourseLesson $courseLesson, int $index): array => [
                $courseLesson->id => [
                    'course_step_number' => $index + 1,
                    'course_step_label' => sprintf('Step %02d', $index + 1),
                ],
            ]);
        $sections = $course->sections
            ->sortBy([['order_num', 'asc'], ['id', 'asc']])
            ->values()
            ->map(function ($section) use ($completedLessonIds, $orderedLessons, $request, $stepMeta): array {
                $sectionLessons = $orderedLessons
                    ->where('section_id', $section->id)
                    ->values()
                    ->map(fn (AcademyCourseLesson $courseLesson): array => $this->access->courseLessonPayload($courseLesson, $request->user(), false, [
                        'completed_lesson_ids' => $completedLessonIds,
                        ...((array) $stepMeta->get($courseLesson->id, [])),
                    ]))
                    ->all();

                return [
                    'id' => (int) $section->id,
                    'title' => (string) $section->title,
                    'slug' => (string) ($section->slug ?? ''),
                    'description' => (string) ($section->description ?? ''),
                    'order_num' => (int) ($section->order_num ?? 0),
                    'is_visible' => (bool) ($section->is_visible ?? true),
                    'lessons' => $sectionLessons,
                ];
            })
            ->all();

        $unsectionedLessons = $orderedLessons
            ->whereNull('section_id')
            ->values()
            ->map(fn (AcademyCourseLesson $courseLesson): array => $this->access->courseLessonPayload($courseLesson, $request->user(), false, [
                'completed_lesson_ids' => $completedLessonIds,
                ...((array) $stepMeta->get($courseLesson->id, [])),
            ]))
            ->all();

        $coursePayload = $this->access->coursePayload($course, $request->user(), ['progress' => $progress]);
        $courseKeywords = collect(explode(',', (string) ($course->meta_keywords ?? '')))
            ->map(fn (string $keyword): string => trim($keyword))
            ->filter()
            ->values()
            ->all();
        $courseImage = (string) ($coursePayload['cover_image_url'] ?? $coursePayload['teaser_image_url'] ?? $course->og_image ?? $course->cover_image ?? $course->teaser_image ?? '');

        $seo = app(SeoFactory::class)
            ->academyCoursePage(
                (string) ($course->seo_title ?: ($course->title . ' — Skinbase Academy')),
                (string) ($course->seo_description ?: $course->excerpt ?: 'Skinbase Academy course'),
                route('academy.courses.show', ['course' => $course->slug]),
                $courseImage,
                [
                    ['name' => 'Academy', 'url' => route('academy.index')],
                    ['name' => 'Courses', 'url' => route('academy.courses.index')],
                    ['name' => (string) $course->title, 'url' => route('academy.courses.show', ['course' => $course->slug])],
                ],
                $courseKeywords,
                $course->published_at?->toAtomString(),
                $course->updated_at?->toAtomString(),
                (string) ($course->access_level ?? ''),
                (string) ($course->difficulty ?? ''),
                (int) ($course->estimated_minutes ?? 0),
                $orderedLessons
                    ->values()
                    ->map(fn (AcademyCourseLesson $courseLesson): array => $this->access->courseLessonPayload($courseLesson, $request->user(), false, [
                        'completed_lesson_ids' => $completedLessonIds,
                        ...((array) $stepMeta->get($courseLesson->id, [])),
                    ]))
                    ->all(),
            )
            ->toArray();

        $interaction = $this->interactions->getInteractionState($request->user(), AcademyAnalyticsContentType::COURSE, (int) $course->id);

        return Inertia::render('Academy/CoursesShow', [
            'seo' => $seo,
            'course' => $coursePayload,
            'sections' => $sections,
            'unsectionedLessons' => $unsectionedLessons,
            'pricingUrl' => route('academy.pricing'),
            'startUrl' => $request->user() ? route('academy.courses.start', ['course' => $course->slug]) : null,
            'interaction' => $interaction,
            'interactionRoutes' => [
                'like' => route('academy.interactions.like'),
                'save' => route('academy.interactions.save'),
            ],
            'loginUrl' => route('login'),
            'analytics' => [
                'enabled' => true,
                'contentType' => AcademyAnalyticsContentType::COURSE,
                'contentId' => (int) $course->id,
                'eventUrl' => route('academy.analytics.events.store'),
                'pageName' => 'academy_course_show',
                'isPremium' => (string) ($course->access_level ?? 'free') !== 'free',
                'isGuest' => $request->user() === null,
                'isSubscriber' => $request->user()?->hasAcademyCreatorAccess() || $request->user()?->hasAcademyProAccess(),
                'isLocked' => false,
            ],
        ])->rootView('collections');
    }
}