<?php

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

use App\Http\Controllers\Controller;
use App\Models\LmsCourse;
use App\Models\LmsCourseSettings;
use App\Models\LmsCourseAccess;
use App\Models\LmsCourseCompetency;
use App\Services\RichTextSanitizer;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;

class CourseController extends Controller
{
    /**
     * Get all courses (paginated)
     * Can be filtered by status and search term
     */
    public function index(Request $request): JsonResponse
    {
        $query = LmsCourse::query();

        // Filter by status
        if ($request->has('status') && $request->status !== 'ALL') {
            $query->where('status', $request->status);
        }

        // Search by title or category
        if ($request->has('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('title', 'like', "%{$search}%")
                  ->orWhere('category', 'like', "%{$search}%");
            });
        }

        // Pagination
        $courses = $query->with(['creator', 'settings', 'access'])
            ->withCount('enrollments')
            ->orderBy('created_at', 'desc')
            ->paginate($request->get('per_page', 15));

        // Add enrolled_count to each course
        $coursesData = $courses->items();
        foreach ($coursesData as $course) {
            $course->enrolled_count = $course->enrollments_count ?? 0;
        }

        return response()->json([
            'status' => 'success',
            'data' => $coursesData,
            'pagination' => [
                'total' => $courses->total(),
                'per_page' => $courses->perPage(),
                'current_page' => $courses->currentPage(),
                'last_page' => $courses->lastPage(),
            ],
        ]);
    }

    /**
     * Create a new course (initial save, status = DRAFT)
     */
    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'title' => 'required|string|max:255',
            'short_description' => 'nullable|string|max:500',
            'description' => 'nullable|string',
            'description_json' => 'nullable',
            'overview_table' => 'nullable|array',
            'overview_table.rows' => 'nullable|integer',
            'overview_table.cols' => 'nullable|integer',
            'overview_table.cells' => 'nullable|array',
            'category' => 'nullable|string',
            'categoryName' => 'nullable|string',
            'level' => 'nullable|string', // Changed from enum to string to accept user type IDs
            'language' => 'nullable|string|max:50',
            'thumbnail' => 'nullable|image|max:10240', // 10MB max
            'duration' => 'nullable|integer',
            'cpd_hours' => 'nullable|numeric',
            'tags' => 'nullable|array',
            'tags.*.id' => 'required_with:tags|string',
            'tags.*.name' => 'required_with:tags|string',
            'tags.*.color' => 'required_with:tags|string',
            'tags.*.icon' => 'required_with:tags|string',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'max_seats' => 'nullable|integer',
            'auto_evaluate' => 'nullable|in:0,1,true,false',
        ]);

        // Handle file upload
        if ($request->hasFile('thumbnail')) {
            $path = $request->file('thumbnail')->store('course-thumbnails', 'public');
            $validated['thumbnail'] = $path;
        }

        $descriptionJson = $this->parseJsonField($request, 'description_json');
        if ($descriptionJson !== null) {
            $validated['description_json'] = $descriptionJson;
        }

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

        $validated['created_by'] = $request->user()->id ?? 1;
        $validated['status'] = 'DRAFT';

        $course = LmsCourse::create($validated);

        // Create related records
        LmsCourseSettings::create(['course_id' => $course->id]);
        LmsCourseAccess::create(['course_id' => $course->id, 'is_free' => true]);

        return response()->json([
            'status' => 'success',
            'message' => 'Course created successfully',
            'data' => $course->load(['settings', 'access']),
        ], 201);
    }

    /**
     * Get a specific course with all related data
     */
    public function show(LmsCourse $course): JsonResponse
    {
        $course->load([
            'creator',
            'settings',
            'sections.lessons',
            'competencies',
            'access',
        ]);

        // Add enrolled count
        $courseData = $course->toArray();
        $courseData['enrolled_count'] = $course->enrollments()->count();

        // Format competencies from selected IDs
        if (!empty($course->selected_units) || !empty($course->selected_competencies) || !empty($course->selected_sub_competencies)) {
            $formattedCompetencies = $this->formatSelectedCompetencies($course);
            $courseData['competencies'] = $formattedCompetencies;
        }

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

    /**
     * Format selected competencies from IDs to full objects
     */
    private function formatSelectedCompetencies(LmsCourse $course): array
    {
        $formattedCompetencies = [];
        
        // Get selected IDs
        $selectedUnits = $course->selected_units ?? [];
        $selectedCompetencies = $course->selected_competencies ?? [];
        $selectedSubCompetencies = $course->selected_sub_competencies ?? [];

        // Get all competencies and units from database
        $allCompetencies = DB::table('competencies')->get()->keyBy('id');
        $allUnits = DB::table('competency_units')->get()->keyBy('id');
        
        // Determine course language for selecting the correct description
        $courseLanguage = $course->language; // 'English' or 'French'
        $langSuffix = ($courseLanguage === 'French') ? 'fr' : 'en';
        
        // Process selected competencies
        foreach ($selectedCompetencies as $compId) {
            if ($competency = $allCompetencies->get($compId)) {
                // Get unit title based on course language
                $unit = $allUnits->get($competency->unit_id);
                $unitTitle = null;
                if ($unit) {
                    $unitTitle = $unit->{"title_{$langSuffix}"} ?? $unit->{"title_en"} ?? $unit->{"title_fr"} ?? $unit->title ?? null;
                }
                
                // Get description based on course language
                $description = $competency->{"description_{$langSuffix}"} ?? $competency->{"description_en"} ?? $competency->{"description_fr"} ?? $competency->description ?? null;

                // Get sub-competencies for this competency
                $subComps = [];
                foreach ($selectedSubCompetencies as $subId) {
                    if ($subComp = $allCompetencies->get($subId)) {
                        if ($subComp->parent_id == $compId) {
                            $subDescription = $subComp->{"description_{$langSuffix}"} ?? $subComp->{"description_en"} ?? $subComp->{"description_fr"} ?? $subComp->description ?? null;
                            $subComps[] = [
                                'id' => $subComp->id,
                                'code' => $subComp->code,
                                'description' => $subDescription,
                                'description_en' => $subComp->description_en ?? null,
                                'description_fr' => $subComp->description_fr ?? null,
                                'designation' => $subComp->designation,
                            ];
                        }
                    }
                }

                $formattedCompetencies[] = [
                    'id' => $competency->id,
                    'code' => $competency->code,
                    'competency' => $description,
                    'description' => $description,
                    'description_en' => $competency->description_en ?? null,
                    'description_fr' => $competency->description_fr ?? null,
                    'designation' => $competency->designation,
                    'unit_id' => $competency->unit_id,
                    'unit_title' => $unitTitle,
                    'sub_competencies' => $subComps,
                ];
            }
        }

        return $formattedCompetencies;
    }

    /**
     * Update course basic information
     */
    public function update(Request $request, LmsCourse $course): JsonResponse
    {
        // Authorization
        $this->authorize('update', $course);

        $validated = $request->validate([
            'title' => 'sometimes|string|max:255',
            'description' => 'nullable|string',
            'description_json' => 'nullable',
            'overview_table' => 'nullable|array',
            'overview_table.rows' => 'nullable|integer',
            'overview_table.cols' => 'nullable|integer',
            'overview_table.cells' => 'nullable|array',
            'category' => 'nullable|string',
            'categoryName' => 'nullable|string',
            'level' => 'nullable|string',
            'language' => 'nullable|string|max:50',
            'thumbnail' => 'nullable|image|max:10240', // 10MB max
            'duration' => 'nullable|integer',
            'cpd_hours' => 'nullable|numeric',
            'tags' => 'nullable|array',
            'tags.*.id' => 'required_with:tags|string',
            'tags.*.name' => 'required_with:tags|string',
            'tags.*.color' => 'required_with:tags|string',
            'tags.*.icon' => 'required_with:tags|string',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'max_seats' => 'nullable|integer',
            'auto_evaluate' => 'nullable|boolean',
        ]);

        // Handle file upload
        if ($request->hasFile('thumbnail')) {
            $path = $request->file('thumbnail')->store('course-thumbnails', 'public');
            $validated['thumbnail'] = $path;
        }

        $descriptionJson = $this->parseJsonField($request, 'description_json');
        if ($descriptionJson !== null) {
            $validated['description_json'] = $descriptionJson;
        }

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

        $course->update($validated);

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

    /**
     * Save course as draft (partial update)
     */
    public function saveDraft(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        // Allow partial updates for draft
        $validated = $request->validate([
            'title' => 'sometimes|string|max:255',
            'short_description' => 'nullable|string|max:500',
            'description' => 'nullable|string',
            'description_json' => 'nullable',
            'overview_table' => 'nullable|array',
            'overview_table.rows' => 'nullable|integer',
            'overview_table.cols' => 'nullable|integer',
            'overview_table.cells' => 'nullable|array',
            'category' => 'nullable|string',
            'categoryName' => 'nullable|string',
            'level' => 'nullable|string',
            'language' => 'nullable|string|max:50',
            'thumbnail' => 'nullable|image|max:10240', // 10MB max
            'duration' => 'nullable|integer',
            'cpd_hours' => 'nullable|numeric',
            'tags' => 'nullable|array',
            'tags.*.id' => 'required_with:tags|string',
            'tags.*.name' => 'required_with:tags|string',
            'tags.*.color' => 'required_with:tags|string',
            'tags.*.icon' => 'required_with:tags|string',
            'start_date' => 'nullable|date',
            'end_date' => 'nullable|date',
            'max_seats' => 'nullable|integer',
            'auto_evaluate' => 'nullable|boolean',
        ]);

        if ($request->hasFile('thumbnail')) {
            $path = $request->file('thumbnail')->store('course-thumbnails', 'public');
            $validated['thumbnail'] = $path;
        }

        $descriptionJson = $this->parseJsonField($request, 'description_json');
        if ($descriptionJson !== null) {
            $validated['description_json'] = $descriptionJson;
        }

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

        $course->update($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Draft saved',
            'data' => $course,
        ]);
    }

    /**
     * Submit course for review (change status to PENDING_REVIEW)
     */
    public function submit(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        // Validation: Ensure course has required data
        $request->validate([
            'title' => 'required',
        ]);

        if (!$course->title) {
            return response()->json([
                'status' => 'error',
                'message' => 'Course title is required before submission',
            ], 422);
        }

        // Default status is PENDING_REVIEW
        $status = 'PENDING_REVIEW';
        
        // If user is LMS module admin, auto-publish
        if ($request->user()->isModuleAdmin('lms')) {
            $status = 'PUBLISHED';
        }

        $course->update([
            'status' => $status,
            'published_at' => $status === 'PUBLISHED' ? now() : null,
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Course published successfully',
            'data' => $course,
        ]);
    }

    /**
     * Publish course (admin action, change status to PUBLISHED)
     */
    public function publish(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('publish', $course);

        $course->update([
            'status' => 'PUBLISHED',
            'published_at' => now(),
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Course published successfully',
            'data' => $course,
        ]);
    }

    /**
     * Reject course (admin action, change status to REJECTED)
     */
    public function reject(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('publish', $course);

        $request->validate([
            'rejection_reason' => 'required|string',
        ]);

        $course->update([
            'status' => 'REJECTED',
            'rejection_reason' => $request->rejection_reason,
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Course rejected',
            'data' => $course,
        ]);
    }

    /**
     * Unpublish course (admin action, change status back to DRAFT)
     */
    public function unpublish(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('unpublish', $course);

        $course->update([
            'status' => 'DRAFT',
            'published_at' => null,
        ]);

        return response()->json([
            'status' => 'success',
            'message' => 'Course unpublished successfully',
            'data' => $course,
        ]);
    }

    /**
     * Delete course (soft delete)
     * 
     * Best Practice: Courses with enrolled students are archived rather than deleted.
     * Enrolled students maintain access to course materials even after archival.
     */
    public function destroy(LmsCourse $course): JsonResponse
    {
        $this->authorize('delete', $course);

        // Check if course has enrolled students
        $enrollmentCount = $course->enrollments()->count();
        
        if ($enrollmentCount > 0) {
            // Soft delete - course is archived but students keep access
            $course->update(['status' => 'ARCHIVED']);
            $course->delete(); // Soft delete
            
            return response()->json([
                'status' => 'success',
                'message' => "Course archived successfully. {$enrollmentCount} enrolled student(s) will retain access to course materials.",
                'data' => [
                    'enrolled_students' => $enrollmentCount,
                    'archived' => true,
                ],
            ]);
        }

        // No enrollments - safe to delete
        $course->delete();

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

    private function parseJsonField(Request $request, string $field): ?array
    {
        if (!$request->has($field)) {
            return null;
        }

        $value = $request->input($field);
        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;
    }

    /**
     * Get list of question types available
     */
    public function getQuestionTypes(): JsonResponse
    {
        $types = [
            'true_false' => 'True/False',
            'multiple_choice' => 'Multiple Choice',
            'multiple_correct' => 'Multiple Correct Answers',
            'sorting' => 'Sorting',
            'matching' => 'Matching',
            'fill_blank' => 'Fill in the Blank',
            'dropdown' => 'Dropdown',
        ];

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