<?php

namespace App\Http\Controllers\Api\V1\Lms;

use App\Http\Controllers\Controller;
use App\Models\LmsCourse;
use App\Models\LmsCourseSection;
use App\Models\LmsCourseLesson;
use App\Services\RichTextSanitizer;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class CurriculumController extends Controller
{
    /**
     * Get all sections for a course
     */
    public function getSections(LmsCourse $course): JsonResponse
    {
        $sections = $course->sections()
            ->with('lessons')
            ->get();

        return response()->json([
            'status' => 'success',
            'data' => $sections,
        ]);
    }

    /**
     * Create a new section
     */
    public function storeSection(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'description_json' => 'nullable',
            'order' => 'nullable|integer',
        ]);

        $descriptionJson = $this->parseJsonValue($validated['description_json'] ?? null);
        if ($descriptionJson !== null) {
            $validated['description_json'] = $descriptionJson;
        } else {
            unset($validated['description_json']);
        }

        if (array_key_exists('description', $validated)) {
            $validated['description'] = RichTextSanitizer::clean($validated['description']);
        }

        // Get next order if not provided
        if (!isset($validated['order'])) {
            $validated['order'] = $course->sections()->max('order') + 1 ?? 0;
        }

        $validated['course_id'] = $course->id;
        $section = LmsCourseSection::create($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Section created successfully',
            'data' => $section,
        ], 201);
    }

    /**
     * Update a section
     */
    public function updateSection(Request $request, LmsCourseSection $section): JsonResponse
    {
        $this->authorize('update', $section->course);

        $validated = $request->validate([
            'title' => 'sometimes|string|max:255',
            'description' => 'nullable|string',
            'description_json' => 'nullable',
            'order' => 'nullable|integer',
        ]);

        $descriptionJson = $this->parseJsonValue($validated['description_json'] ?? null);
        if ($descriptionJson !== null) {
            $validated['description_json'] = $descriptionJson;
        } else {
            unset($validated['description_json']);
        }

        if (array_key_exists('description', $validated)) {
            $validated['description'] = RichTextSanitizer::clean($validated['description']);
        }

        $section->update($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Section updated successfully',
            'data' => $section,
        ]);
    }

    /**
     * Delete a section and its lessons
     */
    public function destroySection(LmsCourseSection $section): JsonResponse
    {
        $this->authorize('update', $section->course);

        $section->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Section deleted successfully',
        ]);
    }

    /**
     * Get all lessons for a section
     */
    public function getLessons(LmsCourseSection $section): JsonResponse
    {
        $lessons = $section->lessons()
            ->orderBy('order')
            ->get();

        return response()->json([
            'status' => 'success',
            'data' => $lessons,
        ]);
    }

    /**
     * Create a new lesson
     */
    public function storeLesson(Request $request, LmsCourseSection $section): JsonResponse
    {
        $this->authorize('update', $section->course);

        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'nullable|string',
            'content_json' => 'nullable',
            'type' => 'required|in:lesson,quiz,assignment,flashcard',
            'duration' => 'nullable|integer',
            'order' => 'nullable|integer',
            'is_required' => 'boolean',
            'is_free' => 'boolean',
            'video_url' => 'nullable|string',
            'article_content' => 'nullable|string',
            'article_content_json' => 'nullable',
            'lesson_content_type' => 'nullable|in:video,article',
            'attachments' => 'nullable',
            'learning_objectives' => 'nullable',
            'tags' => 'nullable',
            'questions' => 'nullable',
            'passing_score' => 'nullable|integer',
            'max_score' => 'nullable|integer',
            'deadline' => 'nullable|date',
            'assignment_video_url' => 'nullable|string',
            'assignment_learning_objectives' => 'nullable',
            'assignment_tags' => 'nullable',
            'assignment_attachments' => 'nullable',
            'flashcards' => 'nullable',
        ]);

        $contentJson = $this->parseJsonValue($validated['content_json'] ?? null);
        if ($contentJson !== null) {
            $validated['content_json'] = $contentJson;
        } else {
            unset($validated['content_json']);
        }

        $validated = $this->parseJsonFields($validated, [
            'attachments',
            'learning_objectives',
            'tags',
            'questions',
            'assignment_learning_objectives',
            'assignment_tags',
            'assignment_attachments',
            'flashcards',
        ]);

        if (array_key_exists('content', $validated)) {
            $validated['content'] = RichTextSanitizer::clean($validated['content']);
        }

        if (!isset($validated['order'])) {
            $validated['order'] = $section->lessons()->max('order') + 1 ?? 0;
        }

        $validated['section_id'] = $section->id;
        $lesson = LmsCourseLesson::create($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Lesson created successfully',
            'data' => $lesson,
        ], 201);
    }

    /**
     * Update a lesson
     */
    public function updateLesson(Request $request, LmsCourseLesson $lesson): JsonResponse
    {
        $this->authorize('update', $lesson->section->course);

        $validated = $request->validate([
            'title' => 'sometimes|string|max:255',
            'content' => 'nullable|string',
            'content_json' => 'nullable',
            'type' => 'sometimes|in:lesson,quiz,assignment,flashcard',
            'duration' => 'nullable|integer',
            'order' => 'nullable|integer',
            'is_required' => 'boolean',
            'is_free' => 'boolean',
            'video_url' => 'nullable|string',
            'video_iframe' => 'nullable|string',
            'article_content' => 'nullable|string',
            'article_content_json' => 'nullable',
            'lesson_content_type' => 'nullable|in:video,article',
            'attachments' => 'nullable',
            'learning_objectives' => 'nullable',
            'tags' => 'nullable',
            'questions' => 'nullable',
            'passing_score' => 'nullable|integer',
            'max_score' => 'nullable|integer',
            'deadline' => 'nullable|date',
            'assignment_video_url' => 'nullable|string',
            'assignment_learning_objectives' => 'nullable',
            'assignment_tags' => 'nullable',
            'assignment_attachments' => 'nullable',
            'flashcards' => 'nullable',
        ]);

        $contentJson = $this->parseJsonValue($validated['content_json'] ?? null);
        if ($contentJson !== null) {
            $validated['content_json'] = $contentJson;
        } else {
            unset($validated['content_json']);
        }

        $articleContentJson = $this->parseJsonValue($validated['article_content_json'] ?? null);
        if ($articleContentJson !== null) {
            $validated['article_content_json'] = $articleContentJson;
        } else {
            unset($validated['article_content_json']);
        }

        $validated = $this->parseJsonFields($validated, [
            'attachments',
            'learning_objectives',
            'tags',
            'questions',
            'assignment_learning_objectives',
            'assignment_tags',
            'assignment_attachments',
            'flashcards',
        ]);

        if (array_key_exists('content', $validated)) {
            $validated['content'] = RichTextSanitizer::clean($validated['content']);
        }

        if (array_key_exists('article_content', $validated)) {
            $validated['article_content'] = RichTextSanitizer::clean($validated['article_content']);
        }

        $lesson->update($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Lesson updated successfully',
            'data' => $lesson,
        ]);
    }

    /**
     * Delete a lesson
     */
    public function destroyLesson(LmsCourseLesson $lesson): JsonResponse
    {
        $this->authorize('update', $lesson->section->course);

        $lesson->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Lesson deleted successfully',
        ]);
    }

    /**
     * Save entire curriculum (sections + lessons in one request)
     */
    public function saveCurriculum(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        $validated = $request->validate([
            'sections' => 'required|array',
            'sections.*.id' => 'sometimes|integer|exists:lms_course_sections,id',
            'sections.*.title' => 'required|string',
            'sections.*.description' => 'nullable|string',
            'sections.*.description_json' => 'nullable',
            'sections.*.order' => 'required|integer',
            'sections.*.lessons' => 'sometimes|array',
            'sections.*.lessons.*.id' => 'sometimes|integer|exists:lms_course_lessons,id',
            'sections.*.lessons.*.title' => 'required|string',
            'sections.*.lessons.*.type' => 'required|in:lesson,quiz,assignment,flashcard',
            'sections.*.lessons.*.content' => 'nullable|string',
            'sections.*.lessons.*.content_json' => 'nullable',
            'sections.*.lessons.*.duration' => 'nullable|integer',
            'sections.*.lessons.*.order' => 'required|integer',
            'sections.*.lessons.*.is_required' => 'boolean',
            'sections.*.lessons.*.is_free' => 'boolean',
            'sections.*.lessons.*.video_url' => 'nullable|string',
            'sections.*.lessons.*.video_iframe' => 'nullable|string',
            'sections.*.lessons.*.article_content' => 'nullable|string',
            'sections.*.lessons.*.article_content_json' => 'nullable',
            'sections.*.lessons.*.lesson_content_type' => 'nullable|in:video,article',
            'sections.*.lessons.*.attachments' => 'nullable',
            'sections.*.lessons.*.learning_objectives' => 'nullable',
            'sections.*.lessons.*.tags' => 'nullable',
            'sections.*.lessons.*.questions' => 'nullable',
            'sections.*.lessons.*.passing_score' => 'nullable|integer',
            'sections.*.lessons.*.max_score' => 'nullable|integer',
            'sections.*.lessons.*.deadline' => 'nullable|date',
            'sections.*.lessons.*.assignment_video_url' => 'nullable|string',
            'sections.*.lessons.*.assignment_learning_objectives' => 'nullable',
            'sections.*.lessons.*.assignment_tags' => 'nullable',
            'sections.*.lessons.*.assignment_attachments' => 'nullable',
            'sections.*.lessons.*.flashcards' => 'nullable',
        ]);

        // Collect IDs of sections and lessons being saved
        $submittedSectionIds = [];
        $submittedLessonIds = [];
        
        foreach ($validated['sections'] as $sectionData) {
            if (isset($sectionData['id']) && is_numeric($sectionData['id']) && $sectionData['id'] > 0) {
                $submittedSectionIds[] = $sectionData['id'];
            }
            if (isset($sectionData['lessons']) && is_array($sectionData['lessons'])) {
                foreach ($sectionData['lessons'] as $lessonData) {
                    if (isset($lessonData['id']) && is_numeric($lessonData['id']) && $lessonData['id'] > 0) {
                        $submittedLessonIds[] = $lessonData['id'];
                    }
                }
            }
        }

        // Delete sections that are not in the submitted list
        if (!empty($submittedSectionIds)) {
            $course->sections()->whereNotIn('id', $submittedSectionIds)->delete();
        } else {
            // If no existing IDs submitted (all new), delete all existing sections
            $course->sections()->delete();
        }

        // Delete lessons that are not in the submitted list
        if (!empty($submittedLessonIds)) {
            LmsCourseLesson::whereHas('section', function ($query) use ($course) {
                $query->where('course_id', $course->id);
            })->whereNotIn('id', $submittedLessonIds)->delete();
        }

        $sections = collect($validated['sections'])->map(function ($sectionData) use ($course) {
            // Determine if this is a new section or existing
            $sectionId = $sectionData['id'] ?? null;
            $isNewSection = !$sectionId || !is_numeric($sectionId) || $sectionId < 0;

            // Update or create section
            $section = LmsCourseSection::updateOrCreate(
                $isNewSection 
                    ? ['course_id' => $course->id, 'title' => $sectionData['title']]
                    : ['id' => $sectionId],
                [
                    'course_id' => $course->id,
                    'title' => $sectionData['title'],
                    'description' => RichTextSanitizer::clean($sectionData['description'] ?? null),
                    'description_json' => $this->parseJsonValue($sectionData['description_json'] ?? null),
                    'order' => $sectionData['order'],
                ]
            );

            // Update or create lessons if provided
            if (isset($sectionData['lessons']) && is_array($sectionData['lessons'])) {
                collect($sectionData['lessons'])->each(function ($lessonData) use ($section) {
                    $lessonId = $lessonData['id'] ?? null;
                    $isNewLesson = !$lessonId || !is_numeric($lessonId) || $lessonId < 0;

                    $lessonData = $this->parseJsonFields($lessonData, [
                        'attachments',
                        'learning_objectives',
                        'tags',
                        'questions',
                        'assignment_learning_objectives',
                        'assignment_tags',
                        'assignment_attachments',
                        'flashcards',
                    ]);

                    LmsCourseLesson::updateOrCreate(
                        $isNewLesson
                            ? ['section_id' => $section->id, 'title' => $lessonData['title']]
                            : ['id' => $lessonId],
                        [
                            'section_id' => $section->id,
                            'title' => $lessonData['title'],
                            'content' => RichTextSanitizer::clean($lessonData['content'] ?? null),
                            'content_json' => $this->parseJsonValue($lessonData['content_json'] ?? null),
                            'type' => $lessonData['type'],
                            'duration' => $lessonData['duration'] ?? null,
                            'order' => $lessonData['order'],
                            'is_required' => $lessonData['is_required'] ?? true,
                            'is_free' => $lessonData['is_free'] ?? false,
                            'video_url' => $lessonData['video_url'] ?? null,
                            'video_iframe' => $lessonData['video_iframe'] ?? null,
                            'article_content' => RichTextSanitizer::clean($lessonData['article_content'] ?? null),
                            'article_content_json' => $this->parseJsonValue($lessonData['article_content_json'] ?? null),
                            'lesson_content_type' => $lessonData['lesson_content_type'] ?? null,
                            'attachments' => $lessonData['attachments'] ?? null,
                            'learning_objectives' => $lessonData['learning_objectives'] ?? null,
                            'tags' => $lessonData['tags'] ?? null,
                            'questions' => $lessonData['questions'] ?? null,
                            'passing_score' => $lessonData['passing_score'] ?? null,
                            'max_score' => $lessonData['max_score'] ?? null,
                            'deadline' => $lessonData['deadline'] ?? null,
                            'assignment_video_url' => $lessonData['assignment_video_url'] ?? null,
                            'assignment_learning_objectives' => $lessonData['assignment_learning_objectives'] ?? null,
                            'assignment_tags' => $lessonData['assignment_tags'] ?? null,
                            'assignment_attachments' => $lessonData['assignment_attachments'] ?? null,
                            'flashcards' => $lessonData['flashcards'] ?? null,
                        ]
                    );
                });
            }

            return $section;
        });

        return response()->json([
            'status' => 'success',
            'message' => 'Curriculum saved successfully',
            'data' => $course->sections()->with('lessons')->get(),
        ]);
    }

    private function parseJsonFields(array $data, array $fields): array
    {
        foreach ($fields as $field) {
            if (!array_key_exists($field, $data)) {
                continue;
            }

            $parsed = $this->parseJsonValue($data[$field]);
            if ($parsed !== null) {
                $data[$field] = $parsed;
            }
        }

        return $data;
    }

    private function parseJsonValue(mixed $value): ?array
    {
        if ($value === null) {
            return null;
        }

        if (is_array($value)) {
            return $value;
        }

        if (is_string($value)) {
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $decoded;
            }
        }

        return null;
    }
}
