<?php

namespace App\Http\Controllers\Result;

use auth;
use App\Models\Result\Exam;
use Illuminate\Http\Request;
use App\Models\Academic\Group;
use App\Models\Academic\Shift;
use App\Models\Result\MarkHead;
use App\Models\Academic\Section;
use App\Models\Result\ExamRecord;
use App\Traits\ReportExportTrait;
use App\Models\Student\StudentInfo;
use App\Http\Controllers\Controller;
use App\Models\Academic\AcademicYear;
use App\Models\Academic\StudentClass;
use App\Models\Result\MarkHeadAssign;
use App\Models\StudentInfoSubjectClass;
use App\Models\Academic\TeacherEnrollment;
use App\Services\ExamResult\MarksEntryService;

class MarksEntryController extends Controller
{

    use ReportExportTrait;

    protected $marksEntryService;

    public function __construct(MarksEntryService $marksEntryService)
    {
        $this->marksEntryService = $marksEntryService;
    }

    public function index()
    {
        $data = [
            'exam_id' => '',
            'shift_id' => '',
            'section_id' => '',
            'group_id' => '',
            'student_class_id' => '',
            'subject_id' => '',

            'studentClasses' => StudentClass::pluck('class_name', 'id'),
            'groups' => Group::pluck('group_name', 'id'),
            'sections' => Section::pluck('section_name', 'id'),
            'academicYears' => AcademicYear::pluck('year', 'id'),
            'markHeads' => MarkHead::pluck('short_name', 'id'),
            'exams' => Exam::orderBy('id', 'desc')->select('id', 'exam_name', 'year')->get(),
            'shifts' => Shift::select('id', 'shift_name')->get(),
            'marks' => []
        ];

        return view('pages.result.mark_entry.index', $data);
    }

    public function search_student_marks_list(Request $request)
    {
        $exam_id = $request->exam_id;
        $shift_id = $request->shift_id;
        $section_id = $request->section_id;
        $group_id = $request->group_id;
        $subject_id = $request->subject_id;
        $student_class_id = $request->student_class_id;

        $academic_year = Exam::find($exam_id)->year ?? null;

        $marks = ExamRecord::where('exam_records.class_id', $student_class_id)
                   ->where('exam_records.exam_id', $exam_id)
                   ->where('exam_records.year', $academic_year);

        if (!empty($shift_id)) {
            $marks->where('exam_records.shift_id', $shift_id);
        }

        if (!empty($section_id)) {
            $marks->where('exam_records.section_id', $section_id);
        }

        if (!empty($group_id)) {
            $marks->where('exam_records.group_id', $group_id);
        }

        if (!empty($subject_id)) {
            $marks->where('exam_records.subject_id', $subject_id);
        }

        $highest_marks = $marks->max('total_marks');

        $marks = $marks->with(['exam', 'markHead', 'student', 'studentClass', 'section', 'group', 'subject', 'academicYear'])
                    ->join('student_infos', 'student_infos.id', '=', 'exam_records.student_id')
                    ->orderBy('student_infos.class_roll', 'ASC')
                    ->select('exam_records.*') 
                    ->get();

        $assignedMarksHead = MarkHeadAssign::where('exam_id', $exam_id)->where('student_class_id', $student_class_id)->where('subject_id', $subject_id)->first();

        $studentClasses = StudentClass::pluck('class_name','id');
        $groups = Group::pluck('group_name', 'id');
        $sections = Section::pluck('section_name','id');
        $academicYears = AcademicYear::pluck('year','id');

        $exams = Exam::orderBy('id', 'desc')->select('id', 'exam_name', 'year')->get();
        $shifts = Shift::select('id', 'shift_name')->get();
        $markHeads = MarkHead::all();

        return view('pages.result.mark_entry.index',
            compact(
                'studentClasses',
                'markHeads',
                'marks',
                'highest_marks',
                'exams',
                'studentClasses',
                'groups',
                'shifts',
                'sections',
                'academicYears',
                'exam_id',
                'academic_year',
                'student_class_id',
                'section_id',
                'group_id',
                'shift_id',
                'subject_id',
                'assignedMarksHead'
            )
        );
    }

    public function create(Request $request)
    {
        $data = [
            'exam_id' => getCurrentActiveExamId(),
            'academic_year' => getDefaultAcademicYearID(),
            'shift_id' => '',
            'section_id' => '',
            'group_id' => '',
            'student_class_id' => '',
            'subject_id' => '',

            // Get from query string
            'prev_exam_id' => $request->query('prev_exam_id'),
            'prev_shift_id' => $request->query('prev_shift_id'),
            'prev_student_class_id' => $request->query('prev_student_class_id'),
            'prev_section_id' => $request->query('prev_section_id'),
            'prev_group_id' => $request->query('prev_group_id'),
            'prev_subject_id' => $request->query('prev_subject_id'),
    
            'studentClasses' => StudentClass::pluck('class_name', 'id'),
            'groups' => Group::pluck('group_name', 'id'),
            'shifts' => Shift::select('id', 'shift_name')->get(),
            'sections' => Section::pluck('section_name', 'id'),
            'exams' => Exam::orderBy('id', 'desc')->select('id','exam_name','year')->get()

        ];    
        // dd($data);    
        return view('pages.result.mark_entry.create', $data);
    }

    public function getStudentsByClass(Request $request)
    {
        $exam_id = $request->exam_id;
        $exam = Exam::where('id', $exam_id)->first();
        $academic_year = $exam->academic_year->id;
        $shift_id = $request->shift_id;
        $section_id = $request->section_id;
        $group_id = $request->group_id;
        $subject_id = $request->subject_id;
        $student_class_id = $request->student_class_id;
        $students = StudentInfo::where('student_class_id', $student_class_id)->where('status','active');
        if (!empty($shift_id)) {
            $students->where('shift_id', $shift_id);
        }

        if (!empty($section_id)) {
            $students->where('section_id', $section_id);
        }

        if (!empty($group_id)) {
            $students->where('group_id', $group_id)
             ->whereHas('StudentInfoSubjectClass', function ($q) use ($subject_id, $student_class_id) {
                 if (!empty($subject_id)) {
                     $q->where('subject_id', $subject_id);
                 }
                 if (!empty($student_class_id)) {
                     $q->where('student_class_id', $student_class_id);
                 }
             });
        }

        $students = $students->with(['examRecords' => function ($query) use ($exam_id, $subject_id, $academic_year) {
            $query->where('exam_id', $exam_id)->where('year', $academic_year);

            if (!empty($subject_id)) {
                $query->where('subject_id', $subject_id);
            }
        }])->orderBy('class_roll','ASC')->get();


        $studentClasses = StudentClass::pluck('class_name', 'id');
        $groups = Group::pluck('group_name', 'id');
        $shifts = Shift::select('id', 'shift_name')->get();
        $assignedMarksHead = MarkHeadAssign::where('exam_id', $exam_id)->where('student_class_id', $student_class_id)->where('subject_id', $subject_id)->first();

        $markHeads = MarkHead::all();
        $sections = Section::pluck('section_name','id');
        $exams = Exam::orderBy('id', 'desc')->select('id','exam_name','year')->get();
        return view('pages.result.mark_entry.create', compact('students','exams', 'studentClasses', 'groups', 'shifts', 'sections', 'markHeads', 'exam_id', 'academic_year', 'student_class_id', 'section_id', 'group_id', 'shift_id', 'subject_id', 'assignedMarksHead'));
    }
    public function store(Request $request) {
        try {
            // dd($request->all(), 'store');
            $student_ids = $request->student_id;
            $marks = $request->marks;
            $head_ids = $request->head_id;

            $exam_id = $request->exam_id;
            $student_class_id = $request->student_class_id;
            $subject_id = $request->subject_id;
            
            $exam = Exam::find($exam_id);
            $year = $exam->year ?? null;

            foreach ($student_ids as $id) {
                $headWiseMarks = [];
                $total_marks = 0;
                $hasValidMarks = false;

                // Loop through marks for this specific student
                if (isset($marks[$id])) {
                    for ($j = 0; $j < count($marks[$id]); $j++) {
                        $currentMark = $marks[$id][$j];
                        
                        // FIX: Allow '0' but ignore null/empty strings
                        if ($currentMark !== null && $currentMark !== '') {
                            $headWiseMarks[$head_ids[$id][$j]] = $currentMark;
                            $total_marks += (float)$currentMark;
                            $hasValidMarks = true;
                        }
                    }
                }

                // Only proceed if marks were actually entered
                if ($hasValidMarks) {
                    // Fetch student info once per student
                    $student_info = StudentInfo::find($id);
                    if (!$student_info) continue;

                    // Update existing record or create new one
                    ExamRecord::updateOrCreate(
                        [
                            'student_id' => $id,
                            'exam_id'    => $exam_id,
                            'year'       => $year,
                            'class_id'   => $student_class_id,
                            'subject_id' => $subject_id,
                        ],
                        [
                            'branch_id'       => $student_info->branch_id,
                            'shift_id'        => $student_info->shift_id,
                            'section_id'      => $student_info->section_id,
                            'group_id'        => $student_info->group_id,
                            'head_wise_marks' => json_encode($headWiseMarks),
                            'mark_head_id'    => json_encode(array_keys($headWiseMarks)),
                            'total_marks'     => $total_marks,
                        ]
                    );
                }
            }

            return redirect()->route('marks.create', [
                'prev_exam_id'          => $exam_id,
                'prev_student_class_id' => $student_class_id,
                // Pass other params as needed
            ])->with('success', 'Mark Entry successfully.');

        } catch (\Exception $e) {
            return redirect()->back()->with('error', 'Mark Entry Failed: ' . $e->getMessage());
        }
    }


    public function storeOLD(Request $request){
        try{
            // dd($request->all(), 'store');
            $student_id = $request->student_id;
            $marks = $request->marks;
            $head_id = $request->head_id;

            $exam_id = $request->exam_id;
            $student_class_id = $request->student_class_id;
            $section_id = $request->section_id;
            $shift_id = $request->shift_id;
            $subject_id = $request->subject_id;
            $group_id = $request->group_id;
            $year = Exam::find($exam_id)->year ?? null;
            // dd($marks);
            foreach ($student_id as $key => $id) {
                $headWiseMarks = [];
                $total_marks = 0;
                for ($j = 0; $j < count($marks[$id]); $j++) {
                    if(!empty($marks[$id][$j])){
                        $headWiseMarks[$head_id[$id][$j]] = $marks[$id][$j];
                        $total_marks += $marks[$id][$j];
                    }
                }

                // Check if record exists for the current student with given exam and other parameters
                $record = ExamRecord::where('student_id', $id)
                    ->where('exam_id', $exam_id)
                    ->where('year', $year)
                    ->where('class_id', $student_class_id)
                    ->where('subject_id', $subject_id)->first();

                $student_info = StudentInfo::where('id', $id)->first();
                $section_id = $student_info->section_id;
                $shift_id = $student_info->shift_id;
                $branch_id = $student_info->branch_id;
                $group_id = $student_info->group_id;

                // Update existing record or create new one
                if(!empty($headWiseMarks)){
                    if ($record) {

                        $record_data = [
                            'branch_id' => $branch_id,
                            'shift_id' => $shift_id,
                            'section_id' => $section_id ?? null,
                            'head_wise_marks' => json_encode($headWiseMarks),
                            'mark_head_id' => json_encode(array_keys($headWiseMarks)),
                            'total_marks' => $total_marks,
                        ];

                        $record->update($record_data);

                    } else {

                        $record_data = [
                            'branch_id' => $branch_id,
                            'exam_id' => $exam_id,
                            'year' => $year,
                            'class_id' => $student_class_id,
                            'section_id' => $section_id ?? null,
                            'shift_id' => $shift_id,
                            'subject_id' => $subject_id,
                            'group_id' => $group_id,
                            'student_id' => $id,
                            'head_wise_marks' => json_encode($headWiseMarks),
                            'mark_head_id' => json_encode(array_keys($headWiseMarks)),
                            'total_marks' => $total_marks,
                        ];
                        ExamRecord::create($record_data);
                    }
                }

            }

            return redirect()->route('marks.create', [
                'prev_exam_id' => $exam_id,
                'prev_shift_id' => $shift_id,
                'prev_student_class_id' => $student_class_id,
                'prev_section_id' => $section_id,
                'prev_group_id' => $group_id,
                'prev_subject_id' => $subject_id,
            ])
            ->with('success', 'Mark Entry successfully.');
            
        }catch(\Exception $e){
            return redirect()->route('student_by_class')
                            ->with('error','Mark Entry Failed!');
        }
    }

    public function edit($recoard_id){

        $check_recoard = ExamRecord::where('id',$recoard_id)->first();

        $exam_id = $check_recoard->exam_id;
        $student_class_id = $check_recoard->class_id;
        $subject_id = $check_recoard->subject_id;

        $markHeads = MarkHead::all();
        $assignedMarksHead = MarkHeadAssign::where('exam_id', $exam_id)->where('student_class_id', $student_class_id)->where('subject_id', $subject_id)->first();
        $students = StudentInfo::where('id', $check_recoard->student_id)->first();

        return view('pages.result.mark_entry.edit',compact('markHeads', 'students', 'check_recoard', 'assignedMarksHead'));
    }

    public function update(Request $request, $exam_id){

        try{

            $student_id = $request->student_id;
            $marks = $request->marks;
            $head_id = $request->head_id;

            $record = ExamRecord::where('id', $exam_id)->first();

            $student_info = StudentInfo::where('id', $student_id)->first();
            $section_id = $student_info->pluck('section_id');
            $shift_id = $student_info->pluck('shift_id');
            $branch_id = $student_info->pluck('branch_id');

            $headWiseMarks = [];
            $total_marks = 0;
            if ($record) {
                for ($j = 0; $j < count($marks[$student_id]); $j++) {
                    if(!empty($marks[$student_id][$j])){
                        $headWiseMarks[$head_id[$student_id][$j]] = $marks[$student_id][$j];
                        $total_marks += $marks[$student_id][$j];
                    }
                }

                if (!empty($headWiseMarks)) {
                    ExamRecord::where('id', $exam_id)->update([
                        'branch_id' => $branch_id,
                        'shift_id' => $shift_id,
                        'section_id' => $section_id ?? null,
                        'head_wise_marks' => json_encode($headWiseMarks),
                        'mark_head_id' => json_encode(array_keys($headWiseMarks)),
                        'total_marks' => $total_marks,
                    ]);
                }
            }

            return redirect()->route('marks.index')->with('success','Mark Updated successfully.');
        }catch(\Exception $e){
            return redirect()->route('marks.index')->with('error','Mark Entry Failed!');
        }
    }


    public function destroy(Request $request){

        $delete_recoard = ExamRecord::where('id',$request->marks_id)->delete();
        return response()->json(['success' => true, 'message' => 'Exam recoards deleted successfully!']);
    }

    public function getMarksSheetByClass(Request $request)
    {
        $data = $this->marksEntryService->getRelatedData();
        list($data['students'], $data['highest_marks_array'], $data['assignedMarksHead'], $data['publish_date'], $data['subjects_assigns']) = $this->marksEntryService->getMarksSheetByClass($request);
        $data['exam_id'] = $request->exam_id;
        $data['shift_id'] = $request->shift_id;
        $data['student_class_id'] = $request->student_class_id;
        $data['section_id'] = $request->section_id;
        $data['group_id'] = $request->group_id;

        $data['exam'] = Exam::where('id', $request->exam_id)->first();
        return view('pages.result.marks_sheet.mark_sheet', $data);
    }

    public function downloadMarksSheet(Request $request)
    {
        $data = $this->marksEntryService->getRelatedData();
        list($data['students'], $data['highest_marks_array'], $data['assignedMarksHead'], $data['publish_date'], $data['subjects_assigns']) = $this->marksEntryService->getMarksSheetByClass($request);

        $columns = ['student_name', 'class_roll', 'total_marks'];

        $options = [
            'filename' => 'marks-sheet',
            'title' => 'Marks Sheet',
            'orientation' => 'portrait',
            'view' => 'pages.result.marks_sheet.mark_sheet_pdf',
            'paper_size' => 'a4'
        ];

        $data['request'] = $request;
        return $this->generateExport('pdf', $data, ['columns' => $columns], $options);
    }

    //teacher marks entry

    public function teacherMarksEntry(){
        $user_id = auth()->user()->id;
        $my_subjects = TeacherEnrollment::where('teacher_id',$user_id)->get();
        $exam = Exam::where('is_published', 1)->orderBy('id','desc')->first();
        return view('pages.result.mark_entry.teacher-marks-entry',compact('my_subjects','exam'));
    }

    public function teacherMarksEntryCreate(Request $request){
        $request->validate([
            'exam' => 'required',
            'related_id' => 'required',
        ]);
        $relatedId = $request->input('related_id');
        // If you want to split the related_id into its parts:
        list($teacher_id, $student_class_id, $subject_id, $section_id, $shift_id, $branch_id) = explode(',', $relatedId);
        ///open
        $exam_id = $request->input('exam');
        $exam = Exam::where('id', $exam_id)->first();
        $academic_year = $exam->academic_year->year;
        $shift_id = $shift_id;
        $section_id = $section_id;
        $group_id = null;
        $subject_id = $subject_id;
        $student_class_id = $student_class_id;
        $students = StudentInfo::where('student_class_id', $student_class_id);
        if (!empty($shift_id)) {
            $students->where('shift_id', $shift_id);
        }
        if (!empty($section_id)) {
            $students->where('section_id', $section_id);
        }
        if (!empty($group_id)) {
            $students->where('group_id', $group_id);
        }
        $students = $students->with(['examRecords' => function ($query) use ($exam_id, $subject_id, $academic_year) {
            $query->where('exam_id', $exam_id)->where('year', $academic_year);

            if (!empty($subject_id)) {
                $query->where('subject_id', $subject_id);
            }
        }])->orderBy('class_roll','ASC')->get();
        $studentClasses = StudentClass::pluck('class_name', 'id');
        $groups = Group::pluck('group_name', 'id');
        $shifts = Shift::pluck('shift_name', 'id');
        $assignedMarksHead = MarkHeadAssign::where('exam_id', $exam_id)->where('student_class_id', $student_class_id)->where('subject_id', $subject_id)->first();

        $markHeads = MarkHead::all();
        $sections = Section::pluck('section_name','id');
        $academicYears = AcademicYear::pluck('year','id');
        
        $exam = Exam::where('is_published', 1)->orderBy('id','desc')->first();
        $user_id = auth()->user()->id;
        $my_subjects = TeacherEnrollment::where('teacher_id',$user_id)->get();
        return view('pages.result.mark_entry.teacher-marks-entry', compact('my_subjects','relatedId','students','exam', 'studentClasses', 'groups', 'shifts', 'sections', 'academicYears', 'markHeads', 'exam_id', 'academic_year', 'student_class_id', 'section_id', 'group_id', 'shift_id', 'subject_id', 'assignedMarksHead'));
    }

    
    public function teacherMarksStore(Request $request){

        try{

            $student_id = $request->student_id;
            $marks = $request->marks;
            $head_id = $request->head_id;

            $examId = $request->exam_id;
            $student_class_id = $request->student_class_id;
            $section_id = $request->section_id;
            $shift_id = $request->shift_id;
            $subject_id = $request->subject_id;
            $group_id = $request->group_id;
            $year = $request->academic_year;

            foreach ($student_id as $key => $id) {
                $headWiseMarks = [];
                $total_marks = 0;
                for ($j = 0; $j < count($marks[$id]); $j++) {
                    if(!empty($marks[$id][$j])){
                        $headWiseMarks[$head_id[$id][$j]] = $marks[$id][$j];
                        $total_marks += $marks[$id][$j];
                    }
                }

                // Check if record exists for the current student with given exam and other parameters
                $record = ExamRecord::where('student_id', $id)
                    ->where('exam_id', $examId)
                    ->where('year', $year)
                    ->where('class_id', $student_class_id)
                    ->where('subject_id', $subject_id)->first();

                $student_info = StudentInfo::where('id', $id)->first();
                $section_id = $student_info->section_id;
                $shift_id = $student_info->shift_id;
                $branch_id = $student_info->branch_id;

                // Update existing record or create new one
                if(!empty($headWiseMarks)){
                    if ($record) {

                        $record_data = [
                            'branch_id' => $branch_id,
                            'shift_id' => $shift_id,
                            'section_id' => $section_id ?? null,
                            'head_wise_marks' => json_encode($headWiseMarks),
                            'mark_head_id' => json_encode(array_keys($headWiseMarks)),
                            'total_marks' => $total_marks,
                        ];

                        $record->update($record_data);

                    } else {

                        $record_data = [
                            'branch_id' => $branch_id,
                            'exam_id' => $examId,
                            'year' => $year,
                            'class_id' => $student_class_id,
                            'section_id' => $section_id ?? null,
                            'shift_id' => $shift_id,
                            'subject_id' => $subject_id,
                            'group_id' => $group_id,
                            'student_id' => $id,
                            'head_wise_marks' => json_encode($headWiseMarks),
                            'mark_head_id' => json_encode(array_keys($headWiseMarks)),
                            'total_marks' => $total_marks,
                        ];

                        ExamRecord::create($record_data);
                    }
                }

            }

            return redirect()->route('teacher.marks.entry')
                            ->with('success','Mark Entry successfully.');
        }catch(\Exception $e){
            return redirect()->route('teacher.marks.entry')
                            ->with('error','Mark Entry Failed!');
        }
    }

}   
