<?php

namespace App\Http\Controllers\Admin;

use App\DataTables\ExamGradesDataTable;
use App\DataTables\ExamProgramsDataTable;
use App\DataTables\ExamsDataTable;
use App\Events\NewExamProgram;
use App\Events\NewGrade;
use App\Http\Controllers\Controller;
use App\Models\Division;
use App\Models\ExamProgram;
use App\Models\SemesterExam;
use App\Models\StudentExamGrades;
use App\Models\StudyMaterial;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class ExamsController extends Controller
{

    public function exams(ExamsDataTable $examsDataTable)
    {
        return $examsDataTable->render('admin.exams.exams-index');
    }

    public function showCreateView()
    {

        $divisions = Division::select('divisions.*', 'levels.title as level', 'stages.title as stage')
            ->join('levels', 'levels.id', '=', 'divisions.level_id')
            ->join('stages', 'stages.id', '=', 'levels.stage_id')->get();


        if (Auth::guard('admin')->user()->cannot('manageAsSuper', SemesterExam::class)) {
            foreach ($divisions as $key => $division) {
                if (Auth::guard('admin')->user()->cannot('manageDivision', [SemesterExam::class, $division])) {
                    unset($divisions[$key]);
                }
            }
        }


        $divisionsLevels = [];
        foreach ($divisions as $value) {
            if (!in_array($value->level_id, $divisionsLevels)) {
                $divisionsLevels[] = $value->level_id;
            }
        }

        $studyMaterials = StudyMaterial::select('study_materials.*', 'levels.title as level')
            ->join('levels', 'levels.id', '=', 'study_materials.level_id')
            ->whereIn('study_materials.level_id', $divisionsLevels)->get();

        return view('admin.exams.exams-create', ['divisions' => $divisions, 'studyMaterials' => $studyMaterials]);
    }


    public function create(Request $request)
    {
        $data = ($request->all());
        $validatedData = Validator::make($data, [
            'title' => ['required', 'max:255'],
            'description' => ['max:25500'],
            'division_id' => ['required', 'max:255', 'exists:App\Models\Division,id'],
            'study_material_id' => ['required', 'max:255', 'exists:App\Models\StudyMaterial,id'],
            'quiz_mark' => ['required', 'max:25500'],
            'quiz_type' => ['required'],
            'date' => ['required', 'date'],
        ], [], [])->validate();

        $validatedData['user_id'] = Auth::guard('admin')->user()->id;

        SemesterExam::create($validatedData);
        return back()->with('success', trans('general.record_added_successfully'));
    }



    public function showUpdateView($id)
    {

        Validator::make(['id' => $id], [
            'id' => ['required', 'max:255', 'exists:App\Models\SemesterExam,id'],
        ], [], [])->validate();
        $exam = SemesterExam::find($id);

        $this->authorize('manage', $exam);

        $divisions = Division::select('divisions.*', 'levels.title as level', 'stages.title as stage')
            ->join('levels', 'levels.id', '=', 'divisions.level_id')
            ->join('stages', 'stages.id', '=', 'levels.stage_id')->get();

        if (Auth::guard('admin')->user()->cannot('manageAsSuper', SemesterExam::class)) {
            foreach ($divisions as $key => $division) {
                if (Auth::guard('admin')->user()->cannot('manageDivision', [SemesterExam::class, $division])) {
                    unset($divisions[$key]);
                }
            }
        }

        $divisionsLevels = [];
        foreach ($divisions as $value) {
            if (!in_array($value->level_id, $divisionsLevels)) {
                $divisionsLevels[] = $value->level_id;
            }
        }

        $studyMaterials = StudyMaterial::select('study_materials.*', 'levels.title as level')
            ->join('levels', 'levels.id', '=', 'study_materials.level_id')
            ->whereIn('study_materials.level_id', $divisionsLevels)->get();


        return view('admin.exams.exams-edit', ['exam' => $exam, 'divisions' => $divisions, 'studyMaterials' => $studyMaterials]);
    }

    public function update(Request $request)
    {

        $data = ($request->all());
        $validatedData = Validator::make($data, [
            'id' => ['required', 'max:255', 'exists:App\Models\SemesterExam,id'],
            'title' => ['required', 'max:255'],
            'description' => ['max:25500'],
            'quiz_mark' => ['required', 'max:25500'],
            'quiz_type' => ['required'],
            'division_id' => ['required', 'max:255', 'exists:App\Models\Division,id'],
            'study_material_id' => ['required', 'max:255', 'exists:App\Models\StudyMaterial,id'],
            'date' => ['required', 'date'],
        ], [], [])->validate();
        $validatedData['user_id'] = Auth::guard('admin')->user()->id;

        $exam = SemesterExam::find($validatedData['id']);

        $this->authorize('manage', $exam);

        $exam->title = $validatedData['title'];
        $exam->user_id = $validatedData['user_id'];
        $exam->description = $validatedData['description'];
        $exam->quiz_mark = $validatedData['quiz_mark'];
        $exam->quiz_type = $validatedData['quiz_type'];
        $exam->division_id = $validatedData['division_id'];
        $exam->study_material_id = $validatedData['study_material_id'];
        $exam->date = $validatedData['date'];
        $exam->save();

        return back()->with('success', trans('general.record_updated_successfully'));
    }


    public function delete(Request $request)
    {
        $data = $request->all();
        Validator::make($data, [
            'exam_id' => ['required', 'max:190', 'exists:App\Models\SemesterExam,id'],
        ], [], [])->validate();

        $exam = SemesterExam::find($data['exam_id']);
        $this->authorize('manage', $exam);

        try {
            $exam->delete();
            return back()->with('success', trans('general.record_deleted_successfully'));
        } catch (\Illuminate\Database\QueryException $th) {
            return back()->withErrors(trans('general.record_foreign_key_delete_error'));
        } catch (\Throwable $th) {
            return back()->withErrors(trans('general.record_delete_error'));
        }
    }



    public function showGradesView(ExamGradesDataTable $examGradesDataTable, $exam_id)
    {
        $exam = SemesterExam::find($exam_id);
        $this->authorize('manage', $exam);
        return $examGradesDataTable->with('exam', $exam)->render('admin.exams.grades.exam-grades', ['exam' => $exam]);
    }


    public function setExamGrade(Request $request)
    {
        $data = ($request->all());

        $validatedData = Validator::make($data, [
            'students_grades' => ['required', 'array'],
            'exam_id' => ['required', 'max:255', 'exists:App\Models\SemesterExam,id'],
        ], [], [])->validate();


        $exam = SemesterExam::find($data['exam_id']);
        $this->authorize('manage', $exam);

        foreach ($data['students_grades'] as $key => $value) {
            if ($value) {
                $res = StudentExamGrades::updateOrCreate(
                    [
                        'student_id' => $key,
                        'semester_exam_id' => $validatedData['exam_id'],
                    ],
                    [
                        'student_id' => $key,
                        'grade' => $value,
                        'semester_exam_id' => $validatedData['exam_id'],
                        'user_id' => Auth::guard('admin')->user()->id,
                    ]
                );
                if ($res->wasRecentlyCreated || $res->wasChanged()) {
                    event(new NewGrade($key, $res));
                }
            }
        }

        return back()->with('success', trans('general.grades_updated_successfully'));
    }


    public function examsPrograms(ExamProgramsDataTable $examProgramsDataTable)
    {
        $divisions = Division::select('divisions.*', 'levels.title as level', 'stages.title as stage')
            ->join('levels', 'levels.id', '=', 'divisions.level_id')
            ->join('stages', 'stages.id', '=', 'levels.stage_id')->get();


        if (Auth::guard('admin')->user()->cannot('manageAsSuper', SemesterExam::class)) {
            foreach ($divisions as $key => $division) {
                if (Auth::guard('admin')->user()->cannot('manageDivision', [SemesterExam::class, $division])) {
                    unset($divisions[$key]);
                }
            }
        }


        return $examProgramsDataTable->render('admin.exams.programs.programs-index', ['divisions' => $divisions]);
    }

    public function addExamProgram(Request $request)
    {
        $data = ($request->all());

        $validatedData = Validator::make($data, [
            'title' => ['required', 'max:255'],
            'description' => [ 'max:25500'],
            'division_id' => ['required', 'max:255', 'exists:App\Models\Division,id'],
            'attachments' => ['file', 'max:5120'],
        ], [], [])->validate();

        if (isset($validatedData['attachments'])) {
            $path = $request->file('attachments')->store('attachments');
            $validatedData['attachments'] = $path;
        }

        $res = ExamProgram::create($validatedData);

        event(new NewExamProgram($validatedData['division_id'], $res));


        $data = [
            "code" => 1,
            "data" => [],
            "msg" => trans('general.record_added_successfully')
        ];

        return response($data, 200);
    }

    public function deleteExamProgram(Request $request)
    {
        $data = $request->all();
        Validator::make($data, [
            'exam_program_id' => ['required', 'max:190', 'exists:App\Models\ExamProgram,id'],
        ], [], [])->validate();

        $examProgram = ExamProgram::find($data['exam_program_id']);

        //******* */ 
        $division = Division::find($examProgram->division_id);
        $this->authorize('manageDivision', [SemesterExam::class, $division]);
        //******* */ 

        try {
            $examProgram->delete();
            return back()->with('success', trans('general.record_deleted_successfully'));
        } catch (\Illuminate\Database\QueryException $th) {
            return back()->withErrors(trans('general.record_foreign_key_delete_error'));
        } catch (\Throwable $th) {
            return back()->withErrors(trans('general.record_delete_error'));
        }
    }


    public function getDivisionLevelMaterials(Request $request)
    {
        $division_id = $request->input('division_id');
        if ($division_id) {
            $division = Division::find($division_id);
            $divisionsLevel = $division->level_id;

            $studyMaterials = StudyMaterial::select('study_materials.*', 'levels.title as level')
                ->join('levels', 'levels.id', '=', 'study_materials.level_id')
                ->where('study_materials.level_id', $divisionsLevel)->get();

            $data = [
                "code" => 1,
                "data" => $studyMaterials,
                "msg" => ""
            ];

            return response($data, 200);
        }

        $data = [
            "code" => 1,
            "data" => [],
            "msg" => ""
        ];

        return response($data, 200);
    }
}
