<?php

namespace App\Http\Controllers\Student;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Cache;

class CourseController extends Controller
{
    public function index(Request $request)
    {
        // ✅ Get student session data
        $student = Session::get('student');
        
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            Log::warning('Student session missing or incomplete', [
                'has_student' => !empty($student),
                'session_keys' => $student ? array_keys($student) : []
            ]);
            
            if ($request->ajax()) {
                return response()->json(['error' => 'Session expired. Please login again.'], 401);
            }
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }
        
        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];

        // ✅ Get filter from request or set default
        $filter = $request->input('filter', 'current');
        session(['course_filter' => $filter]);

        // ✅ Fetch allocation for this student
        $allocation = DB::table('allocatecourses')
            ->where('uname', $uname)
            ->where('cname', $cname)
            ->where('dept', $dept)
            ->where('batch', $batch)
            ->first();

        $courses = collect();
        $completedCoursesCount = 0;
        $activeCoursesCount = 0;
        $allCourses = collect();

        if ($allocation && !empty($allocation->courseid)) {
            $courseIds = array_filter(explode(',', $allocation->courseid));

            $allCourses = DB::table('courses')
                ->leftJoin('programs', 'courses.pname', '=', 'programs.id')
                ->whereIn('courses.id', $courseIds)
                ->select(
                    'courses.*',
                    'programs.image as program_image',
                    'programs.pname as language_name'
                )
                ->get()
                ->map(function ($course) use ($student, &$completedCoursesCount, &$activeCoursesCount) {
                    
                    // ✅ MODULE COUNT
                    $moduleCount = DB::table('modules')
                        ->where('uname', $student['uname'])
                        ->where('coursename', $course->id)
                        ->count();

                    // ✅ CODING COUNT
                    $codingCount = DB::table('allocatecodings')
                        ->where('uname', $student['uname'])
                        ->where('coursename', $course->id)
                        ->where('batch', $student['batch'])
                        ->get()
                        ->reduce(function ($carry, $row) {
                            if (!empty($row->questionid)) {
                                $carry += count(array_filter(explode(',', $row->questionid)));
                            }
                            return $carry;
                        }, 0);

                    // ✅ MCQ COUNT
                    $mcqCount = DB::table('allocatemcqs')
                        ->where('uname', $student['uname'])
                        ->where('coursename', $course->id)
                        ->where('batch', $student['batch'])
                        ->get()
                        ->reduce(function ($carry, $row) {
                            if (!empty($row->questionid)) {
                                $carry += count(array_filter(explode(',', $row->questionid)));
                            }
                            return $carry;
                        }, 0);

                    // ✅ Calculate percentage
                    $percentage = 0;
                    try {
                        $modules = DB::table('modules')
                            ->where('coursename', $course->id)
                            ->get();

                        if (!$modules->isEmpty()) {
                            $totalCoveredTopics = 0;
                            $totalTopicsInCourse = 0;

                            foreach ($modules as $module) {
                                // Get coverage for this module
                                $coverage = DB::table('topiccoverages')
                                    ->where('uname', $student['uname'])
                                    ->where('cname', $student['cname'])
                                    ->where('dept', $student['dept'])
                                    ->where('batch', $student['batch'])
                                    ->where('coursename', $course->id)
                                    ->where('module_id', $module->id)
                                    ->first();

                                $coveredTopics = 0;
                                if ($coverage && !empty($coverage->topics)) {
                                    $coveredTopics = count(array_filter(explode(',', $coverage->topics)));
                                }

                                $totalTopicsInModule = DB::table('topics')
                                    ->where('coursename', $course->id)
                                    ->where('module', $module->id)
                                    ->count();

                                $totalCoveredTopics += $coveredTopics;
                                $totalTopicsInCourse += $totalTopicsInModule;
                            }

                            if ($totalTopicsInCourse > 0) {
                                $percentage = round(($totalCoveredTopics / $totalTopicsInCourse) * 100, 2);
                                $percentage = min($percentage, 100);
                            }
                        }
                    } catch (\Exception $e) {
                        Log::error('Error calculating topic coverage: ' . $e->getMessage());
                        $percentage = 0;
                    }

                    // ✅ Determine if course is completed
                    $isCompleted = $percentage == 100;
                    
                    // ✅ Update counters
                    if ($isCompleted) {
                        $completedCoursesCount++;
                    } else {
                        $activeCoursesCount++;
                    }

                    // ✅ Format image path
                    $imagePath = null;
                    if ($course->program_image) {
                        $imagePath = ltrim($course->program_image, 'images/');
                    }

                    // ✅ Assign computed values
                    $course->modules = $moduleCount;
                    $course->codings = $codingCount;
                    $course->mcq = $mcqCount;
                    $course->percentage = $percentage;
                    $course->formatted_image = $imagePath;
                    $course->language = $course->language_name;
                    $course->is_completed = $isCompleted;
                    $course->completion_status = $isCompleted ? 'completed' : 'current';
                    $course->hours = $course->hours ?? 0;

                    return $course;
                });

            // ✅ Apply filter
            switch ($filter) {
                case 'completed':
                    $courses = $allCourses->filter(function ($course) {
                        return $course->is_completed;
                    });
                    break;
                case 'current':
                    $courses = $allCourses->filter(function ($course) {
                        return !$course->is_completed;
                    });
                    break;
                case 'all':
                default:
                    $courses = $allCourses;
                    break;
            }
        } else {
            // No allocation found
            $courses = collect();
            $allCourses = collect();
            Log::info('No course allocation found for student', [
                'uname' => $uname,
                'cname' => $cname,
                'dept' => $dept,
                'batch' => $batch
            ]);
        }

        // ✅ Calculate total courses
        $totalCourses = $allCourses->count();

        // ✅ If AJAX request, return JSON
        if ($request->ajax()) {
            $html = view('student.course.partials.courses_grid', [
                'courses' => $courses,
                'currentFilter' => $filter
            ])->render();

            return response()->json([
                'success' => true,
                'html' => $html,
                'counts' => [
                    'total' => $totalCourses,
                    'completed' => $completedCoursesCount,
                    'active' => $activeCoursesCount,
                    'displayed' => $courses->count()
                ],
                'currentFilter' => $filter
            ]);
        }

        return view('student.course.index', [
            'courses' => $courses,
            'totalCourses' => $totalCourses,
            'completedCoursesCount' => $completedCoursesCount,
            'activeCoursesCount' => $activeCoursesCount,
            'currentFilter' => $filter
        ]);
    }
    
    public function viewModule(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id'
        ]);
    
        $courseId = $request->input('course_id');
    
        // ✅ Get student session data
        $student = Session::get('student');
        $batch = $student['batch'] ?? null;
    
        if (!$student || !$batch) {
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }
    
        $course = DB::table('courses')->where('id', $courseId)->first();
    
        if (!$course) {
            return redirect()->back()->with('error', 'Course not found.');
        }
    
        // ✅ Fetch modules with topic count
        $modules = DB::table('modules')
            ->leftJoin('topics', function ($join) use ($courseId) {
                $join->on('modules.id', '=', 'topics.module')
                     ->where('topics.coursename', '=', $courseId);
            })
            ->where('modules.coursename', $courseId)
            ->select(
                'modules.id',
                'modules.module',
                'modules.coursename',
                'modules.uname',
                'modules.created_at',
                'modules.updated_at',
                DB::raw('COUNT(topics.id) as topics_count')
            )
            ->groupBy(
                'modules.id',
                'modules.module',
                'modules.coursename',
                'modules.uname',
                'modules.created_at',
                'modules.updated_at'
            )
            ->get();
    
        return view('student.course.viewmodule', [
            'course' => $course,
            'modules' => $modules,
            'student' => $student
        ]);
    }
    
    /**
     * Get ALL materials for a specific module (from all staff)
     */
    public function getModuleMaterials(Request $request)
    {
        try {
            $request->validate([
                'course_id' => 'required|integer|exists:courses,id',
                'module_id' => 'required|integer|exists:modules,id',
                'search' => 'nullable|string' // Add search parameter
            ]);
    
            $student = Session::get('student');
            
            if (!$student) {
                return response()->json(['error' => 'Session expired.'], 401);
            }
    
            // Get materials from database with search filter
            $query = DB::table('materials')
                ->where('coursename', $request->course_id)
                ->where('module', $request->module_id)
                ->where('batch', $student['batch']);
            
            // Apply search filter if search term exists
            if ($request->has('search') && !empty($request->search)) {
                $searchTerm = $request->search;
                $query->where(function($q) use ($searchTerm) {
                    $q->where('material_name', 'LIKE', '%' . $searchTerm . '%')
                      ->orWhere('file_name', 'LIKE', '%' . $searchTerm . '%');
                });
            }
            
            $materials = $query->orderBy('created_at', 'desc')->get();
    
            $materials = $materials->map(function ($material) {
                // Check if it's a Google Drive URL or local file
                $isDriveUrl = !empty($material->drive_url) && 
                              filter_var($material->drive_url, FILTER_VALIDATE_URL);
                
                $isLocalFile = !empty($material->file_name);
                
                // Determine file URL
                $fileUrl = null;
                if ($isDriveUrl) {
                    $fileUrl = $material->drive_url;
                } elseif ($isLocalFile) {
                    // Assuming files are stored in storage
                    $fileUrl = asset('storage/' . $material->file_name);
                }
                
                // Get file extension from file_name or determine from URL
                $extension = '';
                if ($material->file_name) {
                    $extension = pathinfo($material->file_name, PATHINFO_EXTENSION);
                } elseif ($material->drive_url) {
                    // For Google Drive, we can't easily get extension
                    $extension = 'drive';
                }
                
                return [
                    'id' => $material->id,
                    'title' => $material->material_name,
                    'filename' => $material->file_name ?: 'Google Drive File',
                    'extension' => strtoupper($extension),
                    'file_url' => $fileUrl,
                    'uploaded_by' => $material->uname,
                    'uploaded_at' => date('d M Y', strtotime($material->created_at)),
                    'file_type' => $this->getFileType($extension),
                    'is_drive_url' => $isDriveUrl
                ];
            });
    
            return response()->json([
                'success' => true,
                'materials' => $materials,
                'count' => $materials->count()
            ]);
    
        } catch (\Exception $e) {
            Log::error('Error in getModuleMaterials: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'error' => 'Failed to load materials: ' . $e->getMessage()
            ], 500);
        }
    }
    
    private function getFileType($extension)
    {
        $imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg'];
        $documentTypes = ['pdf', 'doc', 'docx', 'txt', 'rtf'];
        $presentationTypes = ['ppt', 'pptx'];
        $spreadsheetTypes = ['xls', 'xlsx', 'csv'];
        
        if (in_array($extension, $imageTypes)) return 'image';
        if (in_array($extension, $documentTypes)) return 'document';
        if (in_array($extension, $presentationTypes)) return 'presentation';
        if (in_array($extension, $spreadsheetTypes)) return 'spreadsheet';
        if ($extension === 'drive') return 'drive';
        return 'file';
    }
    
    /**
     * Get ALL EIQ (Extra Important Questions) for module (from all staff)
     */
    public function getModuleEiq(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id'
        ]);
    
        $student = Session::get('student');
        
        if (!$student) {
            return response()->json(['error' => 'Session expired.'], 401);
        }
    
        // Get ALL EIQ for this course and batch
        $eiq = DB::table('eiq')
            ->where('coursename', $request->course_id)
            ->where('batch', $student['batch']) // Same batch as student
            ->orderBy('created_at', 'desc')
            ->get();
    
        return response()->json([
            'success' => true,
            'eiq' => $eiq
        ]);
    }
    /**
     * Show EIQ page for a course
     */
    public function viewEiq($courseId)
    {
        // ✅ Get student session data
        $student = Session::get('student');
        
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }
        
        $course = DB::table('courses')->where('id', $courseId)->first();
        
        if (!$course) {
            return redirect()->back()->with('error', 'Course not found.');
        }
        
        // Get ALL EIQ for this course and batch
        $eiq = DB::table('eiq')
            ->where('coursename', $courseId)
            ->where('batch', $student['batch'])
            ->orderBy('created_at', 'desc')
            ->get();
        
        return view('student.course.eiq', [
            'course' => $course,
            'eiq' => $eiq,
            'student' => $student
        ]);
    }
    
    /**
     * Search EIQ questions (AJAX)
     */
    public function searchEiq(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id',
            'search' => 'nullable|string'
        ]);
    
        $student = Session::get('student');
        
        if (!$student) {
            return response()->json(['error' => 'Session expired.'], 401);
        }
    
        $query = DB::table('eiq')
            ->where('coursename', $request->course_id)
            ->where('batch', $student['batch']);
        
        // Apply search filter if search term exists
        if ($request->has('search') && !empty($request->search)) {
            $searchTerm = $request->search;
            $query->where(function($q) use ($searchTerm) {
                $q->where('title', 'LIKE', '%' . $searchTerm . '%')
                  ->orWhere('question', 'LIKE', '%' . $searchTerm . '%');
            });
        }
        
        $eiq = $query->orderBy('created_at', 'desc')->get();
    
        return response()->json([
            'success' => true,
            'eiq' => $eiq,
            'count' => $eiq->count()
        ]);
    }
    /**
     * Get ALL PQB (Previous Question Bank) for course (from all staff)
     */
    public function getModulePqb(Request $request)
    {
        try {
            $request->validate([
                'course_id' => 'required|integer|exists:courses,id'
            ]);
    
            $student = Session::get('student');
            
            if (!$student) {
                return response()->json(['error' => 'Session expired.'], 401);
            }
    
            // Get ALL PQB/PQP files for this course and batch
            $pqb = DB::table('pqps')
                ->where('coursename', $request->course_id)
                ->where('batch', $student['batch'])
                ->orderBy('created_at', 'desc')
                ->get()
                ->map(function ($pqp) {
                    // Determine file type from extension
                    $filename = $pqp->file_name;
                    $extension = pathinfo($filename, PATHINFO_EXTENSION);
                    
                    return [
                        'id' => $pqp->id,
                        'title' => $pqp->pqp_name ?? pathinfo($filename, PATHINFO_FILENAME),
                        'filename' => $filename,
                        'extension' => strtoupper($extension),
                        'file_url' => $pqp->drive_url, // Google Drive URL
                        'uploaded_by' => $pqp->uname,
                        'uploaded_at' => date('d M Y', strtotime($pqp->created_at)),
                        'file_type' => $this->getFileType($extension),
                        'is_drive_url' => !empty($pqp->drive_url)
                    ];
                });
    
            return response()->json([
                'success' => true,
                'pqb' => $pqb
            ]);
    
        } catch (\Exception $e) {
            Log::error('Error in getModulePqb: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'error' => 'Failed to load PQB: ' . $e->getMessage()
            ], 500);
        }
    }

    public function viewTopics(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id',
            'module_id' => 'required|integer|exists:modules,id',
        ]);

        $courseId = $request->input('course_id');
        $moduleId = $request->input('module_id');

        // ✅ Get student session data
        $student = Session::get('student');
        $batch = $student['batch'] ?? null;

        if (!$student || !$batch) {
            return response()->json(['error' => 'Session expired. Please log in again.'], 401);
        }

        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];

        // Fetch topics for this module - EXACTLY LIKE student
        $topics = DB::table('topics')
            ->where('coursename', $courseId)
            ->where('module', $moduleId)
            ->get();

        foreach ($topics as $topic) {
            // --- CODING COUNT ---
            $coding = DB::table('allocatecodings')
                ->where([
                    'uname' => $uname,
                    'cname' => $cname,
                    'dept' => $dept,
                    'batch' => $batch,
                    'coursename' => $courseId,
                    'module' => $moduleId,
                    'topic' => $topic->id,
                ])
                ->get();
            
            $codingCount = 0;
            
            // Check if collection is not empty
            if ($coding->isNotEmpty()) {
                // If you expect multiple records, you need to loop through them
                foreach ($coding as $record) {
                    if (!empty($record->questionid)) {
                        $ids = explode(',', $record->questionid);
                        $codingCount += count(array_filter($ids));
                    }
                }
            }

            // --- MCQ COUNT ---
            $mcq = DB::table('allocatemcqs')
                ->where([
                    'uname' => $uname,
                    'cname' => $cname,
                    'dept' => $dept,
                    'batch' => $batch,
                    'coursename' => $courseId,
                    'module' => $moduleId,
                    'topic' => $topic->id,
                ])
                ->first();

            $mcqCount = 0;
            if ($mcq && !empty($mcq->questionid)) {
                $ids = explode(',', $mcq->questionid);
                $mcqCount = count(array_filter($ids));
            }

            // Attach counts to topic object
            $topic->coding_count = $codingCount;
            $topic->mcq_count = $mcqCount;
        }

        $html = view('student.course.viewtopics', compact('topics'))->render();

        return response()->json(['html' => $html]);
    }
   
    public function getMcq($id)
    {
        $mcq = DB::table('mcqs')
            ->select('id', 'question', 'option1', 'option2', 'option3', 'option4', 'answer')
            ->where('id', $id)
            ->first();

        if (!$mcq) {
            return response()->json([
                'success' => false,
                'error' => 'Question not found',
            ], 404);
        }

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

    public function checkMCQSubmissions(Request $request)
    {
        $request->validate([
            'course_id' => 'required|exists:courses,id',
            'module_id' => 'required|exists:modules,id',
            'topic_id' => 'required|exists:topics,id',
            'question_ids' => 'required|array'
        ]);

        $student = Session::get('student');
        
        if (!$student) {
            return response()->json([
                'success' => true,
                'submitted' => []
            ]);
        }

        $uname = $student['uname'] ?? null;
        $cname = $student['cname'] ?? null;
        $dept = $student['dept'] ?? null;
        $batch = $student['batch'] ?? null;
        $student_id = $student['id'] ?? null;
        
        $courseId = $request->course_id;
        $moduleId = $request->module_id;
        $topicId = $request->topic_id;
        $questionIds = $request->question_ids;

        $submitted = [];

        // Build query with all required conditions
        $query = DB::table('mcqreports')
            ->where('coursename', $courseId)
            ->where('module', $moduleId)
            ->where('topic', $topicId)
            ->whereIn('questionid', $questionIds);

        // Add student-specific conditions if available
        if ($student_id) {
            $query->where('student_id', $student_id);
        }
        
        if ($uname) {
            $query->where('uname', $uname);
        }
        
        if ($cname) {
            $query->where('cname', $cname);
        }
        
        if ($dept) {
            $query->where('dept', $dept);
        }
        
        if ($batch) {
            $query->where('batch', $batch);
        }

        $submissions = $query->get();

        foreach ($submissions as $submission) {
            $submitted[(string) $submission->questionid] = [
                'selected_answer' => $submission->selectedanswer,
                'correct_answer' => $submission->correctanswer,
                'submitted_at' => $submission->submitedtime
            ];
        }

        return response()->json([
            'success' => true,
            'submitted' => $submitted
        ]);
    }

    public function checkCodingSubmissions(Request $request)
    {
        $request->validate([
            'course_id' => 'required|exists:courses,id',
            'module_id' => 'required|exists:modules,id',
            'topic_id' => 'required|exists:topics,id',
            'question_ids' => 'required|array'
        ]);

        $student = Session::get('student');
        
        if (!$student) {
            return response()->json([
                'success' => true,
                'submitted' => []
            ]);
        }

        $uname = $student['uname'] ?? null;
        $cname = $student['cname'] ?? null;
        $dept = $student['dept'] ?? null;
        $batch = $student['batch'] ?? null;
        $student_id = $student['id'] ?? null;
        
        $courseId = $request->course_id;
        $moduleId = $request->module_id;
        $topicId = $request->topic_id;
        $questionIds = $request->question_ids;

        $submitted = [];

        // Check codingreports table - updated to match your table structure
        $query = DB::table('codingreports')
            ->where('subname', $courseId)  // Changed from course_id to subname
            ->where('unitname', $moduleId) // Changed from module_id to unitname
            ->where('topic', $topicId)     // Changed from topic_id to topic
            ->whereIn('questionid', $questionIds); // Changed from question_id to questionid

        // Add student-specific conditions if available
        if ($student_id) {
            $query->where('student_id', $student_id);
        }
        
        if ($uname) {
            $query->where('uname', $uname);
        }
        
        if ($cname) {
            $query->where('cname', $cname);
        }
        
        if ($dept) {
            $query->where('dept', $dept);
        }
        
        if ($batch) {
            $query->where('batch', $batch);
        }

        $submissions = $query->get();

        foreach ($submissions as $submission) {
            $submitted[(string) $submission->questionid] = [
                'submitted_at' => $submission->solved_date ?? $submission->created_at,
                'start_time' => $submission->start_time,
                'end_time' => $submission->end_time,
                'total_time' => $submission->total_time_seconds,
                'status' => 'submitted'
            ];
        }

        return response()->json([
            'success' => true,
            'submitted' => $submitted
        ]);
    }

    public function submitMCQ(Request $request)
    {
        $request->validate([
            'course_id' => 'required|exists:courses,id',
            'module_id' => 'required|exists:modules,id',
            'topic_id' => 'required|exists:topics,id',
            'question_id' => 'required',
            'selected_answer' => 'required',
            'correct_answer' => 'required'
        ]);

        try {
            $student = Session::get('student');
            
            // ✅ Validate session
            if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
                Log::warning('Student session missing or incomplete', [
                    'has_student' => !empty($student),
                    'session_keys' => $student ? array_keys($student) : []
                ]);
                
                if ($request->ajax()) {
                    return response()->json(['error' => 'Session expired. Please login again.'], 401);
                }
                return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
            }
            
            $uname = $student['uname'];
            $cname = $student['cname'];
            $dept = $student['dept'];
            $batch = $student['batch'];
            $student_id = $student['id'];

            // Get course, module, topic names
            $course = DB::table('courses')->where('id', $request->course_id)->first();
            $module = DB::table('modules')->where('id', $request->module_id)->first();
            $topic = DB::table('topics')->where('id', $request->topic_id)->first();

            // Insert into mcqreports table
            DB::table('mcqreports')->insert([
                'uname' => $uname,
                'cname' => $cname,
                'dept' => $dept,
                'batch' => $batch,
                'student_id' => $student_id,
                'coursename' => $request->course_id,
                'module' => $request->module_id,
                'topic' => $request->topic_id,
                'questionid' => $request->question_id,
                'selectedanswer' => $request->selected_answer,
                'correctanswer' => $request->correct_answer,
                'submitedtime' => now(),
                'created_at' => now(),
                'updated_at' => now()
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Answer submitted successfully!'
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to submit answer: ' . $e->getMessage()
            ], 500);
        }
    }
    
    public function allocatedQuestions(Request $request)
    {
        $request->validate([
            'coursename' => 'required',
            'module' => 'required',
            'topic' => 'required',
        ]);

        $courseId = $request->coursename;
        $moduleId = $request->module;
        $topicId  = $request->topic;

        $student = Session::get('student');

        // ✅ Session validation
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            return redirect()->route('student.login.index')
                ->with('error', 'Session expired. Please login again.');
        }

        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept  = $student['dept'];
        $batch = $student['batch'];

        /* ================================
           ✅ GET LANGUAGE FROM COURSE → PROGRAM
        ================================= */

        // Get course
        $course = DB::table('courses')->where('id', $courseId)->first();
        if (!$course) {
            return redirect()->back()->with('error', 'Course not found');
        }

        // Get program
        $program = DB::table('programs')->where('id', $course->pname)->first();
        if (!$program) {
            return redirect()->back()->with('error', 'Program not found');
        }

        // ✅ FINAL LANGUAGE (html / sql / cpp / python)
        $language = strtolower(trim($program->pname));

        /* ================================
           FETCH CODING QUESTIONS
        ================================= */

        /* ================================
           FETCH CODING / SQL QUESTIONS
        ================================ */
        
        $codingAllocation = DB::table('allocatecodings')->where([
            'uname'      => $uname,
            'cname'      => $cname,
            'dept'       => $dept,
            'batch'      => $batch,
            'coursename' => $courseId,
            'module'     => $moduleId,
            'topic'      => $topicId,
        ])->first();
        
        $codingQuestions = [];
        
        if ($codingAllocation && $codingAllocation->questionid) {
        
            $codingIds = array_filter(explode(',', $codingAllocation->questionid));
        
            if (!empty($codingIds)) {
        
                // ✅ SWITCH TABLE BASED ON LANGUAGE
                if ($language === 'sql') {
                    $codingQuestions = DB::table('sql_codings')
                        ->whereIn('id', $codingIds)
                        ->get();
                } else {
                    $codingQuestions = DB::table('codings')
                        ->whereIn('id', $codingIds)
                        ->get();
                }
            }
        }

        /* ================================
           FETCH MCQ QUESTIONS
        ================================= */

        $mcqAllocation = DB::table('allocatemcqs')->where([
            'uname'      => $uname,
            'cname'      => $cname,
            'dept'       => $dept,
            'batch'      => $batch,
            'coursename' => $courseId,
            'module'     => $moduleId,
            'topic'      => $topicId,
        ])->first();

        $mcqQuestions = [];

        if ($mcqAllocation && $mcqAllocation->questionid) {
            $mcqIds = array_filter(explode(',', $mcqAllocation->questionid));

            if (!empty($mcqIds)) {
                $mcqQuestions = DB::table('mcqs')
                    ->whereIn('id', $mcqIds)
                    ->get();
            }
        }

        /* ================================
           RETURN VIEW
        ================================= */

        return view('student.course.allocatedquestions', [
            'course_id'        => $courseId,
            'module_id'        => $moduleId,
            'topic_id'         => $topicId,
            'coding_questions' => $codingQuestions,
            'mcq_questions'    => $mcqQuestions,
            'language'         => $language,   // ✅ IMPORTANT
            'student'          => $student,
        ]);
    }
    
    public function compiler(Request $request)
    {
        $language = strtolower($request->language);

        $languageMap = [
            'python' => 'python',
            'java' => 'java',
            'c' => 'c',
            'cpp' => 'cpp',
            'c++' => 'cpp',
            'cplusplus' => 'cpp',
            'html' => 'html',
        ];

        $language = $languageMap[$language] ?? 'cpp';

        $id = $request->coding_id; // current coding question id
        $course_id = $request->course_id;
        $fullscreen = $request->fullscreen === 'true';
        
        if (!$id) {
            return redirect()->route('student.course.index')
                ->with('error', 'Question id not There in url.');
        }

        $student = Session::get('student');
            
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            Log::warning('Student session missing or incomplete', [
                'has_student' => !empty($student),
                'session_keys' => $student ? array_keys($student) : []
            ]);
            
            if ($request->ajax()) {
                return response()->json(['error' => 'Session expired. Please login again.'], 401);
            }
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }
        
        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];
        $student_id = $student['id'];

        $question = DB::table('codings')->where('id', $id)->first();
        if (!$question) {
            return redirect()->route('student.course.index')
                ->with('error', 'Question id not found.');
        }
        // Initialize variable
        $answerToShow = null;

        // Check if questionid exists in codingreports
        $report = DB::table('codingreports')
            ->where('questionid', $id)
            ->where('uname', $uname)
            ->where('cname', $cname)
            ->where('dept', $dept)
            ->where('batch', $batch)
            ->where('student_id', $student_id)
            ->where('subname', $course_id)
            ->where('unitname', $question->module)
            ->where('topic', $question->topic)
            ->first();

        if($report) {
            $answerToShow = $question->answer; // show answer
        } else {
            $answerToShow = null; // hide
        }

        $runRoutes = [
            'python' => route('student.course.compiler.run.python'),
            'java' => route('student.course.compiler.run.java'),
            'c' => route('student.course.compiler.run.c'),
            'cpp' => route('student.course.compiler.run.cpp'),
        ];

        return view('student.course.compiler.compiler', [
            'id' => $question->id,
            'title' => $question->title,
            'question' => $question->question,
            'solution' => $question->solution,
            'level' => $question->level,

            'i1' => $question->i1,
            'i2' => $question->i2,
            'i3' => $question->i3,
            'i4' => $question->i4,
            't1' => $question->t1,
            't2' => $question->t2,
            't3' => $question->t3,
            't4' => $question->t4,

            'coursename' => $question->coursename,
            'module' => $question->module,
            'topic' => $question->topic,

            'uname' => $uname,
            'cname' => $cname,
            'dept' => $dept,
            'batch' => $batch,

            'language' => $language,
            'run_route' => $runRoutes[$language] ?? '',
            'store_report_route' => route('student.course.compiler.store.report'),

            'fullscreen' => $fullscreen,
            'course_id' => $course_id,
            'previousAnswer' => $answerToShow, // only set if questionid exists in codingreports
        ]);
    }

    public function compilerHtml(Request $request)
    {
        // Debug: Check what's coming in the request
        // dd($request->all());
        
        $fullscreen = $request->fullscreen === 'true' || $request->fullscreen === true;
        
        // Or if fullscreen is coming as string '1' or '0'
        // $fullscreen = filter_var($request->fullscreen, FILTER_VALIDATE_BOOLEAN);
        
        $student = Session::get('student');
            
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            Log::warning('Student session missing or incomplete', [
                'has_student' => !empty($student),
                'session_keys' => $student ? array_keys($student) : []
            ]);
            
            if ($request->ajax()) {
                return response()->json(['error' => 'Session expired. Please login again.'], 401);
            }
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }
        
        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];
        $student_id = $student['id'];
        $student_name = $student['name'];
        $student_regno = $student['regno'];
        
        $question = DB::table('codings')->where('id', $request->coding_id)->first();
        
        

        if (!$question) abort(404);

        return view('student.course.compiler.html', [
            'qid' => $question->id,
            'title' => $question->title,
            'question' => $question->question,
            'i1' => $question->i1,
            'i2' => $question->i2,
            'i3' => $question->i3,
            'i4' => $question->i4,
            't1' => $question->t1,
            't2' => $question->t2,
            't3' => $question->t3,
            't4' => $question->t4,
            'level' => $question->level,
            
            'course_id' => $question->coursename,
            'module_id' => $question->module,
            'topic_id' => $question->topic,

            'uname' => $student['uname'] ?? '',
            'cname' => $student['cname'] ?? '',
            'dept'  => $student['dept'] ?? '',
            'batch' => $student['batch'] ?? '',
            'student_name' => $student_name,
            'student_regno' => $student_regno,
            'student_id'   => $student_id,


            'fullscreen' => $fullscreen, // Make sure this is boolean true/false
        ]);
    }
    
    public function compilerSQL(Request $request)
    {
        $fullscreen = $request->fullscreen === 'true';

        $student = session('student_data', []);
        $question = DB::table('codings')->where('id', $request->coding_id)->first();

        if (!$question) abort(404);

        return view('student.course.compiler.sql', [
            'qid' => $question->id,
            'title' => $question->title,
            'question' => $question->question,

            'uname' => $student['uname'] ?? '',
            'cname' => $student['cname'] ?? '',
            'dept'  => $student['dept'] ?? '',
            'batch' => $student['batch'] ?? '',

            'fullscreen' => $fullscreen,
        ]);
    }

    public function runPython(Request $request)
    {
        if (class_exists(\Debugbar::class)) {
            \Debugbar::disable();
        }

        $code = $request->input('code', '');
        $user_input = $request->input('user_input', '');

        $codeFile = tempnam(sys_get_temp_dir(), 'code_') . '.py';
        $inputFile = tempnam(sys_get_temp_dir(), 'input_') . '.txt';

        file_put_contents($codeFile, $code);
        file_put_contents($inputFile, $user_input);

        $command = "python3 " . escapeshellarg($codeFile) . " < " . escapeshellarg($inputFile) . " 2>&1";
        $runOutput = shell_exec($command);

        @unlink($codeFile);
        @unlink($inputFile);

        // ✅ PRESERVE "0"
        $output = ($runOutput === null) ? '' : (string) $runOutput;

        return response(rtrim($output, "\r\n"))
            ->header('Content-Type', 'text/plain');
    }
    
    public function runJava(Request $request)
    {
        if (class_exists(\Debugbar::class)) {
            \Debugbar::disable();
        }

        $code = $request->input('code', '');
        $user_input = $request->input('user_input', '');

        if ($code === '') {
            return response("❌ Error: Code cannot be empty.", 400)
                ->header('Content-Type', 'text/plain');
        }

        $tempDir = sys_get_temp_dir();
        $codeFile = $tempDir . '/Main.java';
        $inputFile = tempnam($tempDir, 'input_') . '.txt';

        file_put_contents($codeFile, $code);
        file_put_contents($inputFile, $user_input);

        putenv("PATH=/usr/bin:/bin:" . getenv("PATH"));

        $compileCmd = "javac " . escapeshellarg($codeFile) . " 2>&1";
        $compileOutput = shell_exec($compileCmd);

        if ($compileOutput !== null && $compileOutput !== '') {
            $output = "❌ Compilation Error:\n" . $compileOutput;
        } else {
            $runCmd = "java -cp " . escapeshellarg($tempDir) . " Main < " . escapeshellarg($inputFile) . " 2>&1";
            $runOutput = shell_exec($runCmd);

            // ✅ PRESERVE "0"
            $output = ($runOutput === null) ? '' : (string) $runOutput;
        }

        @unlink($codeFile);
        @unlink($inputFile);
        @unlink($tempDir . '/Main.class');

        return response(rtrim($output, "\r\n"))
            ->header('Content-Type', 'text/plain');
    }

    public function runCpp(Request $request)
    {
        if (class_exists(\Debugbar::class)) {
            \Debugbar::disable();
        }

        $code = $request->input('code', '');
        $user_input = $request->input('user_input', '');

        $codeFile = tempnam(sys_get_temp_dir(), 'code_') . '.cpp';
        $inputFile = tempnam(sys_get_temp_dir(), 'input_') . '.txt';
        $outputFile = tempnam(sys_get_temp_dir(), 'exec_');

        file_put_contents($codeFile, $code);
        file_put_contents($inputFile, $user_input);

        putenv("PATH=/usr/bin:/bin:" . getenv("PATH"));

        $compileCmd = "g++ " . escapeshellarg($codeFile) . " -o " . escapeshellarg($outputFile) . " 2>&1";
        $compileOutput = shell_exec($compileCmd);

        if ($compileOutput !== null && $compileOutput !== '') {
            $output = "❌ Compilation Error:\n" . $compileOutput;
        } else {
            $runCmd = escapeshellarg($outputFile) . " < " . escapeshellarg($inputFile) . " 2>&1";
            $runOutput = shell_exec($runCmd);

            // ✅ PRESERVE "0"
            $output = ($runOutput === null) ? '' : (string) $runOutput;
        }

        @unlink($codeFile);
        @unlink($inputFile);
        @unlink($outputFile);
        @unlink($outputFile . ".exe");

        return response(rtrim($output, "\r\n"))
            ->header('Content-Type', 'text/plain');
    }

    public function runC(Request $request)
    {
        // Disable Laravel Debugbar
        if (class_exists(\Debugbar::class)) {
            \Debugbar::disable();
        }

        $code = $request->input('code', '');
        $user_input = $request->input('user_input', '');

        // Temp files
        $codeFile   = tempnam(sys_get_temp_dir(), 'code_') . '.c';
        $inputFile  = tempnam(sys_get_temp_dir(), 'input_') . '.txt';
        $outputFile = tempnam(sys_get_temp_dir(), 'exec_');

        file_put_contents($codeFile, $code);
        file_put_contents($inputFile, $user_input);

        putenv("PATH=/usr/bin:/bin:" . getenv("PATH"));

        // Compile
        $compileCmd = "gcc " . escapeshellarg($codeFile) . " -o " . escapeshellarg($outputFile) . " 2>&1";
        $compileOutput = shell_exec($compileCmd);

        if ($compileOutput !== null && $compileOutput !== '') {
            // Compilation error
            $output = "❌ Compilation Error:\n" . $compileOutput;
        } else {
            // Execute
            $runCmd = escapeshellarg($outputFile) . " < " . escapeshellarg($inputFile) . " 2>&1";
            $runOutput = shell_exec($runCmd);

            // ✅ CRITICAL FIX: DO NOT USE ?: HERE
            if ($runOutput === null) {
                $output = '';
            } else {
                $output = (string) $runOutput; // preserves "0"
            }
        }

        // Cleanup
        @unlink($codeFile);
        @unlink($inputFile);
        @unlink($outputFile);
        @unlink($outputFile . ".exe");

        // ✅ RETURN RAW STRING (NO FALSY CHECKS)
        return response(rtrim($output, "\r\n"))
            ->header('Content-Type', 'text/plain');
    }

    // ==============================================
    // QUEUE-BASED STORE REPORT (Test Case Verification)
    // ==============================================

    public function storeReport(Request $request)
    {
        try {
            $student = Session::get('student');
            
            // ✅ Validate session
            if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
                Log::warning('Student session missing or incomplete', [
                    'has_student' => !empty($student),
                    'session_keys' => $student ? array_keys($student) : []
                ]);
                
                return response()->json(['error' => 'Session expired. Please login again.'], 401);
            }
            
            // ✅ Get code from editor
            $code = $request->input('code', '');
            $language = $request->input('language', 'cpp');
            $questionId = $request->input('questionid');
            
            if (empty($code)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Code cannot be empty'
                ], 400);
            }
            
            // ✅ Generate unique session ID
            $sessionId = 'report_' . uniqid() . '_' . time();
            
            // ✅ Get test cases for the question
            $testcases = $this->getTestCasesForQuestion($questionId);
            
            if (empty($testcases)) {
                return response()->json([
                    'success' => false,
                    'message' => 'No test cases found for this question'
                ], 400);
            }
            
            // ✅ Store submission in database for tracking
            $submissionId = DB::table('code_submissions')->insertGetId([
                'session_id' => $sessionId,
                'student_id' => $student['id'],
                'question_id' => $questionId,
                'course_id' => $request->subname ?? null,
                'module_id' => $request->unitname ?? null,
                'topic_id' => $request->topic ?? null,
                'language' => $language,
                'code' => $code,
                'code_length' => strlen($code),
                'status' => 'queued',
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'created_at' => now(),
                'updated_at' => now()
            ]);
            
            // ✅ Dispatch test case verification job
            \App\Jobs\ProcessTestcaseVerification::dispatch(
                $code,
                $language,
                $testcases,
                $student['id'],
                $questionId,
                $sessionId
            )->onQueue('testcase_verification');
            
            Log::info('Report submission queued', [
                'session_id' => $sessionId,
                'student_id' => $student['id'],
                'question_id' => $questionId
            ]);
            
            // ✅ Return immediate response with session ID for polling
            return response()->json([
                'success' => true,
                'message' => 'Code submitted for verification. Processing in background.',
                'data' => [
                    'session_id' => $sessionId,
                    'submission_id' => $submissionId,
                    'queue_position' => $this->getQueuePosition(),
                    'estimated_wait_time' => $this->estimateWaitTime(),
                    'poll_url' => route('student.course.check.status', $sessionId)
                ]
            ], 202);
            
        } catch (\Exception $e) {
            Log::error('Failed to queue report submission', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to submit code: ' . $e->getMessage()
            ], 500);
        }
    }

    // ==============================================
    // TEST CASE VERIFICATION ENDPOINT
    // ==============================================

    public function verifyTestCases(Request $request)
{
    try {
        // Debug logging
        Log::info('verifyTestCases called', [
            'request_data' => $request->all(),
            'session_id' => session()->getId(),
            'has_student' => !empty(session('student'))
        ]);
        
        // Start transaction
        DB::beginTransaction();
        
        $student = Session::get('student');
        
        if (!$student || empty($student['uname'])) {
            return response()->json([
                'success' => false,
                'status' => 'unauthorized',
                'message' => 'Session expired. Please login again.'
            ], 401);
        }
        
        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];
        $student_id = $student['id'];
        
        $code = $request->input('code', '');
        $language = strtolower($request->input('language', 'cpp'));
        $questionId = (int) $request->input('question_id');
        $testcaseId = $request->input('testcase_id');
        $userInput = $request->input('user_input', '');
        
        if (empty($code) || empty($questionId)) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid request data'
            ], 400);
        }
        
        // Get test cases
        $testcases = [];
        if ($testcaseId) {
            // Single test case
            $testcase = $this->getSingleTestCase($questionId, $testcaseId);
            if ($testcase) {
                $testcases = [$testcase];
            }
        } else {
            // All test cases
            $testcases = $this->getTestCasesForQuestion($questionId);
        }
        
        if (empty($testcases)) {
            return response()->json([
                'success' => false,
                'message' => 'No test cases found'
            ], 400);
        }
        
        // Generate unique session ID
        $sessionId = 'tc_' . uniqid() . '_' . time();
        
        // Store submission
        $submissionId = DB::table('code_submissions')->insertGetId([
            'session_id' => $sessionId,
            'student_id' => $student_id,
            'question_id' => $questionId,
            'testcase_id' => $testcaseId ?: null,
            'submission_type' => $testcaseId ? 'single_test' : 'full_test',
            'language' => $language,
            'code' => $code,
            'code_length' => strlen($code),
            'user_input' => $userInput,
            'status' => 'queued',
            'ip_address' => $request->ip(),
            'user_agent' => $request->header('User-Agent'),
            'created_at' => now(),
            'updated_at' => now()
        ]);
        
        // Dispatch the job
        \App\Jobs\ProcessTestcaseVerification::dispatch(
            $code,
            $language,
            $testcases,
            $student_id,
            $questionId,
            $sessionId,
            $userInput
        )->onQueue('testcase_verification');
        
        DB::commit();
        
        // Get queue stats
        $queuePosition = $this->getQueuePosition();
        $estimatedWait = $this->estimateWaitTime($queuePosition);
        
        return response()->json([
            'success' => true,
            'message' => 'Test case verification queued successfully',
            'data' => [
                'session_id' => $sessionId,
                'submission_id' => $submissionId,
                'queue_position' => $queuePosition,
                'estimated_wait_seconds' => $estimatedWait,
                'testcase_count' => count($testcases),
                'poll_url' => route('student.course.check.status', $sessionId),
                'result_url' => route('student.course.get.result', $sessionId)
            ]
        ], 202);
        
    } catch (\Exception $e) {
        DB::rollBack();
        
        Log::error('verifyTestCases error', [
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
            'request' => $request->all()
        ]);
        
        return response()->json([
            'success' => false,
            'message' => 'Server error: ' . $e->getMessage()
        ], 500);
    }
}
    // Helper method to get single test case
    private function getSingleTestCase($questionId, $testcaseId)
{
    $question = DB::table('codings')
        ->where('id', $questionId)
        ->select('i1', 'i2', 'i3', 'i4', 't1', 't2', 't3', 't4')
        ->first();
    
    if (!$question) return null;
    
    $inputField = "i{$testcaseId}";
    $outputField = "t{$testcaseId}";
    
    if (!empty($question->$inputField) && !empty($question->$outputField)) {
        return [
            'id' => $testcaseId,
            'input' => trim($question->$inputField),
            'expected' => trim($question->$outputField),
            'description' => "Test case {$testcaseId}"
        ];
    }
    
    return null;
}

    // ==============================================
    // QUEUE STATUS AND RESULT ENDPOINTS
    // ==============================================

    /**
     * Check code submission status
     */
    public function checkCodeStatus(Request $request, $sessionId)
    {
        // Check Redis for results first (fastest)
        if ($result = Redis::get("testcase_result:{$sessionId}")) {
            return response()->json([
                'status' => 'completed',
                'has_result' => true,
                'session_id' => $sessionId,
                'checked_at' => now()->toDateTimeString()
            ]);
        }
        
        // Check for errors
        if ($error = Redis::get("testcase_error:{$sessionId}")) {
            return response()->json([
                'status' => 'error',
                'has_error' => true,
                'session_id' => $sessionId,
                'error' => $error
            ]);
        }
        
        // Check database for submission status
        $submission = DB::table('code_submissions')
            ->where('session_id', $sessionId)
            ->select('status', 'created_at', 'updated_at')
            ->first();
        
        if (!$submission) {
            return response()->json([
                'status' => 'not_found',
                'message' => 'Submission not found'
            ], 404);
        }
        
        $queuePosition = $this->getQueuePosition();
        $estimatedWait = $this->estimateWaitTime($queuePosition);
        
        return response()->json([
            'status' => $submission->status,
            'session_id' => $sessionId,
            'queue_position' => $queuePosition,
            'estimated_wait_seconds' => $estimatedWait,
            'submitted_at' => $submission->created_at,
            'last_updated' => $submission->updated_at,
            'checked_at' => now()->toDateTimeString()
        ]);
    }
    
    /**
     * Get code submission result
     */
    public function getCodeResult(Request $request, $sessionId)
    {
        // Try to get result from Redis first
        if ($resultJson = Redis::get("testcase_result:{$sessionId}")) {
            $result = json_decode($resultJson, true);
            $reportStored = Redis::get("report_stored:{$sessionId}");
            
            // Update database record
            DB::table('code_submissions')
                ->where('session_id', $sessionId)
                ->update([
                    'status' => 'completed',
                    'results' => $resultJson,
                    'report_stored' => (bool)$reportStored,
                    'updated_at' => now()
                ]);
            
            return response()->json([
                'success' => true,
                'status' => 'completed',
                'session_id' => $sessionId,
                'result' => $result,
                'report_stored' => (bool)$reportStored,
                'retrieved_from' => 'redis_cache'
            ]);
        }
        
        // Check for error in Redis
        if ($error = Redis::get("testcase_error:{$sessionId}")) {
            return response()->json([
                'success' => false,
                'status' => 'error',
                'session_id' => $sessionId,
                'error' => $error,
                'retrieved_from' => 'redis_cache'
            ], 500);
        }
        
        // Fallback to database
        $submission = DB::table('code_submissions')
            ->where('session_id', $sessionId)
            ->select('status', 'results', 'error', 'report_stored', 'created_at', 'updated_at')
            ->first();
        
        if (!$submission) {
            return response()->json([
                'success' => false,
                'status' => 'not_found',
                'message' => 'Submission not found'
            ], 404);
        }
        
        if ($submission->status === 'completed' && $submission->results) {
            return response()->json([
                'success' => true,
                'status' => 'completed',
                'session_id' => $sessionId,
                'result' => json_decode($submission->results, true),
                'report_stored' => (bool)$submission->report_stored,
                'retrieved_from' => 'database',
                'processed_at' => $submission->updated_at
            ]);
        }
        
        if ($submission->status === 'failed' && $submission->error) {
            return response()->json([
                'success' => false,
                'status' => 'error',
                'session_id' => $sessionId,
                'error' => $submission->error,
                'retrieved_from' => 'database'
            ], 500);
        }
        
        // Still processing
        $queuePosition = $this->getQueuePosition();
        $estimatedWait = $this->estimateWaitTime($queuePosition);
        
        return response()->json([
            'success' => true,
            'status' => 'processing',
            'session_id' => $sessionId,
            'queue_position' => $queuePosition,
            'estimated_wait_seconds' => $estimatedWait,
            'submitted_at' => $submission->created_at,
            'last_checked' => now()->toDateTimeString()
        ]);
    }

    // ==============================================
    // HELPER METHODS
    // ==============================================

    /**
     * Get test cases for a question
     */
   /**
 * Get test cases for a question
 */
private function getTestCasesForQuestion(int $questionId): array
{
    $cacheKey = "testcases:question:{$questionId}";
    $cacheTime = 3600; // 1 hour
    
    return Cache::remember($cacheKey, $cacheTime, function () use ($questionId) {
        // Try to get from codings table first
        $codingQuestion = DB::table('codings')
            ->where('id', $questionId)
            ->select('i1', 'i2', 'i3', 'i4', 't1', 't2', 't3', 't4')
            ->first();
        
        $testcases = [];
        
        if ($codingQuestion) {
            // Extract test cases from i1-i4 and t1-t4
            for ($i = 1; $i <= 4; $i++) {
                $inputField = "i{$i}";
                $outputField = "t{$i}";
                
                if (!empty($codingQuestion->$inputField) && !empty($codingQuestion->$outputField)) {
                    $testcases[] = [
                        'id' => $i,
                        'input' => trim($codingQuestion->$inputField),
                        'expected' => trim($codingQuestion->$outputField),
                        'description' => "Test case {$i}"
                    ];
                }
            }
        } else {
            // Try to get from courses table or question bank
            $question = DB::table('courses')
                ->where('id', $questionId)
                ->select('test_cases')
                ->first();
            
            if ($question && !empty($question->test_cases)) {
                $testcases = json_decode($question->test_cases, true) ?? [];
            }
        }
        
        // Add default test cases if none found
        if (empty($testcases)) {
            $testcases = [
                [
                    'id' => 1,
                    'input' => '',
                    'expected' => 'Hello World',
                    'description' => 'Default test case'
                ]
            ];
        }
        
        return $testcases;
    });
}
    
    /**
     * Get queue position from Redis
     */
    private function getQueuePosition(): int
{
    try {
        return (int) Redis::llen('queues:testcase_verification');
    } catch (\Exception $e) {
        Log::error('Failed to get queue position', ['error' => $e->getMessage()]);
        return 0;
    }
}
    
    /**
     * Estimate wait time based on queue position
     */
   private function estimateWaitTime(int $queuePosition = null): int
{
    if ($queuePosition === null) {
        $queuePosition = $this->getQueuePosition();
    }
    
    // Average processing time per submission (seconds)
    $avgProcessingTime = 5;
    
    // Number of active workers
    $activeWorkers = 10; // From supervisor config
    
    // Calculate estimated wait
    $estimatedWait = ceil(($queuePosition * $avgProcessingTime) / $activeWorkers);
    
    // Minimum wait time
    return max(5, min($estimatedWait, 300)); // Between 5 and 300 seconds
}

    // ==============================================
    // NOTES MANAGEMENT
    // ==============================================

    public function checkNotes(Request $request)
    {
        $student = Session::get('student');

        // ✅ Session validation
        if (
            !$student ||
            !isset($student['uname'], $student['cname'], $student['dept'], $student['batch'], $student['id'])
        ) {
            Log::warning('Student session missing', ['student' => $student]);
            return response()->json([
                'success' => false,
                'error' => 'Session expired'
            ], 401);
        }

        // ✅ Validate request
        $request->validate([
            'question_id' => 'required|integer'
        ]);

        $existingNote = DB::table('codingnotes')
            ->where('uname', $student['uname'])
            ->where('cname', $student['cname'])
            ->where('dept', $student['dept'])
            ->where('batch', $student['batch'])
            ->where('student_id', $student['id'])
            ->where('question_id', $request->question_id)
            ->first();

        return response()->json([
            'success' => true,
            'exists'  => (bool) $existingNote,
            'notes'   => $existingNote->notes ?? ''
        ]);
    }

    public function storeNotes(Request $request)
    {
        $student = Session::get('student');

        // ✅ Session validation
        if (
            !$student ||
            !isset($student['uname'], $student['cname'], $student['dept'], $student['batch'], $student['id'])
        ) {
            Log::warning('Student session missing', ['student' => $student]);
            return response()->json([
                'success' => false,
                'error' => 'Session expired'
            ], 401);
        }

        // ✅ Validate request
        $request->validate([
            'question_id' => 'required|integer',
            'notes'       => 'required|string'
        ]);

        try {
            DB::table('codingnotes')->updateOrInsert(
                [
                    'uname'        => $student['uname'],
                    'cname'        => $student['cname'],
                    'dept'         => $student['dept'],
                    'batch'        => $student['batch'],
                    'student_id'   => $student['id'],
                    'question_id'  => $request->question_id,
                ],
                [
                    'notes'       => $request->notes,
                    'updated_at'  => now(),
                    'created_at'  => now(),
                ]
            );

            return response()->json([
                'success' => true,
                'message' => 'Notes saved successfully'
            ]);

        } catch (\Exception $e) {
            Log::error('Coding notes save failed', [
                'error' => $e->getMessage(),
                'student' => $student,
            ]);

            return response()->json([
                'success' => false,
                'error' => 'Server error while saving notes'
            ], 500);
        }
    }

    // ==============================================
    // REPORTS
    // ==============================================

    public function mcqReport(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id',
            'module_id' => 'required|integer|exists:modules,id',
            'topic_id' => 'required|integer|exists:topics,id',
        ]);

        $student = Session::get('student');
        
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }

        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];
        $student_id = $student['id'];

        $course_id = $request->course_id;
        $module_id = $request->module_id;
        $topic_id = $request->topic_id;

        // ✅ Fetch course name
        $courseData = DB::table('courses')->where('id', $course_id)->select('coursename')->first();
        $course_name = $courseData ? $courseData->coursename : 'N/A';

        // ✅ Fetch module name
        $moduleData = DB::table('modules')->where('id', $module_id)->select('module')->first();
        $module_name = $moduleData ? $moduleData->module : 'N/A';

        // ✅ Fetch topic name
        $topicData = DB::table('topics')->where('id', $topic_id)->select('topic')->first();
        $topic_name = $topicData ? $topicData->topic : 'N/A';

        // ✅ 1️⃣ Get allocated MCQ questions for this student
        $allocatedMcq = DB::table('allocatemcqs')
            ->where([
                'uname' => $uname,
                'cname' => $cname,
                'dept' => $dept,
                'batch' => $batch,
                'coursename' => $course_id,
                'module' => $module_id,
                'topic' => $topic_id,
            ])
            ->first();

        $totalAllocated = 0;
        $allocatedMcqIds = [];
        
        if ($allocatedMcq && !empty($allocatedMcq->questionid)) {
            $allocatedMcqIds = array_filter(explode(',', $allocatedMcq->questionid));
            $totalAllocated = count($allocatedMcqIds);
        }

        // ✅ 2️⃣ Get completed MCQ questions from mcqreports
        $completedCount = 0;
        $correctCount = 0;
        $incorrectCount = 0;
        $completedQuestions = [];
        $percentageScore = 0;

        if ($totalAllocated > 0) {
            // Get all completed questions
            $completedReports = DB::table('mcqreports')
                ->where([
                    'uname' => $uname,
                    'cname' => $cname,
                    'dept' => $dept,
                    'batch' => $batch,
                    'student_id' => $student_id,
                    'coursename' => $course_id,
                    'module' => $module_id,
                    'topic' => $topic_id,
                ])
                ->whereIn('questionid', $allocatedMcqIds)
                ->select('questionid', 'selectedanswer', 'correctanswer', 'submitedtime')
                ->get();

            $completedCount = $completedReports->count();
            
            // Calculate correct/incorrect
            foreach ($completedReports as $report) {
                $isCorrect = ($report->selectedanswer === $report->correctanswer);
                if ($isCorrect) {
                    $correctCount++;
                } else {
                    $incorrectCount++;
                }
                
                $completedQuestions[] = [
                    'question_id' => $report->questionid,
                    'selected_answer' => $report->selectedanswer,
                    'correct_answer' => $report->correctanswer,
                    'is_correct' => $isCorrect,
                    'submitted_at' => $report->submitedtime,
                ];
            }
            
            // Calculate percentage score
            if ($completedCount > 0) {
                $percentageScore = round(($correctCount / $completedCount) * 100, 2);
            }
        }

        // ✅ Get question details for completed questions
        $questionsData = [];
        if (!empty($completedQuestions)) {
            $questionIds = array_column($completedQuestions, 'question_id');
            $questions = DB::table('mcqs')
                ->whereIn('id', $questionIds)
                ->select('id', 'question', 'level')
                ->get()
                ->keyBy('id');
            
            // Merge question details with completion data
            foreach ($completedQuestions as &$question) {
                if (isset($questions[$question['question_id']])) {
                    $question['details'] = $questions[$question['question_id']];
                }
            }
        }

        return view('student.course.mcqreport', [
            'student' => $student,
            'course_id' => $course_id,
            'module_id' => $module_id,
            'topic_id' => $topic_id,
            'course_name' => $course_name,
            'module_name' => $module_name,
            'topic_name' => $topic_name,
            'total_allocated' => $totalAllocated,
            'completed_count' => $completedCount,
            'correct_count' => $correctCount,
            'incorrect_count' => $incorrectCount,
            'percentage_score' => $percentageScore,
            'completed_questions' => $completedQuestions,
        ]);
    }
    
    public function codingReport(Request $request)
    {
        $request->validate([
            'course_id' => 'required|integer|exists:courses,id',
            'module_id' => 'required|integer|exists:modules,id',
            'topic_id' => 'required|integer|exists:topics,id',
        ]);

        $student = Session::get('student');
        
        // ✅ Validate session
        if (!$student || empty($student['uname']) || empty($student['cname']) || empty($student['dept'])) {
            return redirect()->route('student.login.index')->with('error', 'Session expired. Please login again.');
        }

        $uname = $student['uname'];
        $cname = $student['cname'];
        $dept = $student['dept'];
        $batch = $student['batch'];
        $student_id = $student['id'];
        $regno = $student['regno'];

        $course_id = $request->course_id;
        $module_id = $request->module_id;
        $topic_id = $request->topic_id;

        // ✅ Fetch course name
        $courseData = DB::table('courses')->where('id', $course_id)->select('coursename')->first();
        $course_name = $courseData ? $courseData->coursename : 'N/A';

        // ✅ Fetch module name
        $moduleData = DB::table('modules')->where('id', $module_id)->select('module')->first();
        $module_name = $moduleData ? $moduleData->module : 'N/A';

        // ✅ Fetch topic name
        $topicData = DB::table('topics')->where('id', $topic_id)->select('topic')->first();
        $topic_name = $topicData ? $topicData->topic : 'N/A';

        // ✅ 1️⃣ Get ALL allocated coding questions for this student (multiple records)
        $allocatedCodingRows = DB::table('allocatecodings')
            ->where([
                'uname' => $uname,
                'cname' => $cname,
                'dept' => $dept,
                'batch' => $batch,
                'coursename' => $course_id,
                'module' => $module_id,
                'topic' => $topic_id,
            ])
            ->get();

        $totalAllocated = 0;
        $allocatedCodingIds = [];
        
        foreach ($allocatedCodingRows as $row) {
            if (!empty($row->questionid)) {
                $ids = array_filter(explode(',', $row->questionid));
                $allocatedCodingIds = array_merge($allocatedCodingIds, $ids);
            }
        }
        
        // Remove duplicates
        $allocatedCodingIds = array_unique($allocatedCodingIds);
        $totalAllocated = count($allocatedCodingIds);

        // ✅ 2️⃣ Get completed coding questions from codingreports
        $completedCount = 0;
        $totalTimeSeconds = 0;
        $completedQuestions = [];
        $averageTime = 0;

        if ($totalAllocated > 0) {
            // Get all completed coding reports
            $completedReports = DB::table('codingreports')
                ->where([
                    'uname' => $uname,
                    'cname' => $cname,
                    'dept' => $dept,
                    'batch' => $batch,
                    'student_id' => $student_id,
                    'regno' => $regno,
                    'subname' => $course_id,
                    'unitname' => $module_id,
                    'topic' => $topic_id,
                ])
                ->whereIn('questionid', $allocatedCodingIds)
                ->select('questionid', 'start_time', 'end_time', 'total_time_seconds', 'marks', 'solved_date', 'level')
                ->get();

            $completedCount = $completedReports->count();
            
            // Calculate total time and store completed questions
            foreach ($completedReports as $report) {
                $totalTimeSeconds += $report->total_time_seconds ?? 0;
                
                $completedQuestions[] = [
                    'question_id' => $report->questionid,
                    'start_time' => $report->start_time,
                    'end_time' => $report->end_time,
                    'total_time_seconds' => $report->total_time_seconds,
                    'marks' => $report->marks,
                    'solved_date' => $report->solved_date,
                    'level' => $report->level,
                ];
            }
            
            // Calculate average time
            if ($completedCount > 0) {
                $averageTime = round($totalTimeSeconds / $completedCount, 2);
            }
        }

        // ✅ Get question details for completed coding questions
        $codingQuestionsData = [];
        if (!empty($completedQuestions)) {
            $questionIds = array_column($completedQuestions, 'question_id');
            $questions = DB::table('codings')
                ->whereIn('id', $questionIds)
                ->select('id', 'title', 'level', 'question')
                ->get()
                ->keyBy('id');
            
            // Merge question details with completion data
            foreach ($completedQuestions as &$question) {
                if (isset($questions[$question['question_id']])) {
                    $question['details'] = $questions[$question['question_id']];
                }
            }
        }

        return view('student.course.codingreport', [
            'student' => $student,
            'course_id' => $course_id,
            'module_id' => $module_id,
            'topic_id' => $topic_id,
            'course_name' => $course_name,
            'module_name' => $module_name,
            'topic_name' => $topic_name,
            'total_allocated' => $totalAllocated,
            'completed_count' => $completedCount,
            'total_time_seconds' => $totalTimeSeconds,
            'average_time' => $averageTime,
            'completed_questions' => $completedQuestions,
        ]);
    }
}