<?php

namespace App\Livewire;

use App\Models\Course;
use App\Models\Enrollment;
use App\Models\Lesson;
use Livewire\Attributes\Layout;
use Livewire\Component;

#[Layout('components.layouts.site')]
class CoursePlayer extends Component
{
    public Course $course;

    public Lesson $lesson;

    public function mount(Course $course, Lesson $lesson): void
    {
        abort_unless($course->is_published, 404);
        abort_unless($lesson->module->course_id === $course->id, 404);

        $this->authorizeAccess($lesson);

        $this->course = $course->load(['modules.lessons']);
        $this->lesson = $lesson;
    }

    private function authorizeAccess(Lesson $lesson): void
    {
        if ($lesson->is_free_preview) {
            return;
        }

        if (! auth()->check()) {
            redirect()->guest(route('login'));

            return;
        }

        abort_unless($this->isEnrolled(), 403, 'Enroll in this course to unlock this lesson.');
    }

    public function isEnrolled(): bool
    {
        return auth()->check()
            && Enrollment::where('user_id', auth()->id())->where('course_id', $this->course->id)->exists();
    }

    public function completedLessonIds(): array
    {
        if (! auth()->check()) {
            return [];
        }

        return auth()->user()->completedLessons()
            ->whereIn('lessons.id', $this->course->lessons()->pluck('lessons.id'))
            ->pluck('lessons.id')
            ->all();
    }

    public function progressPercent(): int
    {
        $total = $this->course->lessons()->count();

        return $total === 0 ? 0 : (int) round(count($this->completedLessonIds()) / $total * 100);
    }

    public function nextLesson(): ?Lesson
    {
        $ordered = $this->course->modules->flatMap->lessons->values();
        $index = $ordered->search(fn ($l) => $l->id === $this->lesson->id);

        return $index !== false ? $ordered->get($index + 1) : null;
    }

    public function previousLesson(): ?Lesson
    {
        $ordered = $this->course->modules->flatMap->lessons->values();
        $index = $ordered->search(fn ($l) => $l->id === $this->lesson->id);

        return $index !== false && $index > 0 ? $ordered->get($index - 1) : null;
    }

    public function toggleComplete(): void
    {
        if (! auth()->check() || ! $this->isEnrolled()) {
            return;
        }

        $user = auth()->user();
        $done = in_array($this->lesson->id, $this->completedLessonIds(), true);

        if ($done) {
            $user->completedLessons()->detach($this->lesson->id);
        } else {
            $user->completedLessons()->attach($this->lesson->id, ['completed_at' => now()]);
            $this->dispatch('celebrate');
        }

        Enrollment::where('user_id', $user->id)
            ->where('course_id', $this->course->id)
            ->first()
            ?->syncProgress();
    }

    public function completeAndContinue(): void
    {
        if (! in_array($this->lesson->id, $this->completedLessonIds(), true)) {
            $this->toggleComplete();
        }

        if ($next = $this->nextLesson()) {
            $this->redirectRoute('learn.lesson', ['course' => $this->course->slug, 'lesson' => $next->slug]);
        }
    }

    public function render()
    {
        return view('livewire.course-player', [
            'completedIds' => $this->completedLessonIds(),
            'progress' => $this->progressPercent(),
            'next' => $this->nextLesson(),
            'previous' => $this->previousLesson(),
            'enrolled' => $this->isEnrolled(),
        ])->title($this->lesson->title.', '.$this->course->title);
    }
}
