<?php

declare(strict_types=1);

namespace App\Http\Controllers\Academy;

use App\Http\Controllers\Controller;
use App\Models\AcademyCourse;
use App\Models\AcademyLesson;
use App\Services\Academy\AcademyAccessService;
use App\Services\Academy\AcademyProgressService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

final class AcademyProgressController extends Controller
{
    public function __construct(
        private readonly AcademyAccessService $access,
        private readonly AcademyProgressService $progress,
    ) {
    }

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

        $validated = $request->validate([
            'lesson_id' => ['required', 'integer', 'min:1'],
            'course_id' => ['nullable', 'integer', 'min:1'],
        ]);

        $lesson = AcademyLesson::query()->findOrFail((int) $validated['lesson_id']);
        abort_unless($this->access->canAccessLesson($request->user(), $lesson), 403);

        $courseId = $request->filled('course_id') ? (int) $validated['course_id'] : null;
        if ($courseId !== null) {
            $course = AcademyCourse::query()->published()->findOrFail($courseId);
            abort_unless($course->courseLessons()->where('lesson_id', $lesson->id)->exists(), 403);
        }

        $record = $this->progress->startLesson($request->user(), (int) $lesson->id, $courseId, $request);

        return response()->json([
            'ok' => true,
            'status' => (string) $record->status,
        ]);
    }

    public function complete(Request $request, AcademyLesson $lesson): JsonResponse
    {
        abort_unless((bool) config('academy.enabled', true), 404);
        abort_unless($this->access->canAccessLesson($request->user(), $lesson), 403);

        $course = null;

        if ($request->filled('course_id')) {
            $course = AcademyCourse::query()->published()->find($request->integer('course_id'));
        }

        $record = $this->progress->markLessonComplete($request->user(), $lesson, $course, $request);

        return response()->json([
            'ok' => true,
            'completed' => true,
            'completed_at' => $record->completed_at?->toISOString(),
        ]);
    }

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

        $validated = $request->validate([
            'lesson_id' => ['required', 'integer', 'min:1'],
            'course_id' => ['nullable', 'integer', 'min:1'],
        ]);

        $lesson = AcademyLesson::query()->findOrFail((int) $validated['lesson_id']);

        return $this->complete($request, $lesson);
    }

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

        $validated = $request->validate([
            'course_id' => ['required', 'integer', 'min:1'],
        ]);

        $course = AcademyCourse::query()->published()->findOrFail((int) $validated['course_id']);
        $record = $this->progress->startCourse($request->user(), (int) $course->id, $request);

        return response()->json([
            'ok' => true,
            'status' => (string) $record->status,
            'progress_percent' => (int) $record->progress_percent,
        ]);
    }

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

        $validated = $request->validate([
            'course_id' => ['required', 'integer', 'min:1'],
        ]);

        $course = AcademyCourse::query()->published()->findOrFail((int) $validated['course_id']);
        $record = $this->progress->completeCourse($request->user(), (int) $course->id, $request);

        return response()->json([
            'ok' => true,
            'status' => (string) $record->status,
            'progress_percent' => (int) $record->progress_percent,
            'completed' => (string) $record->status === 'completed',
        ]);
    }
}