<?php

namespace App\Http\Controllers;

use DateTime;
use DateInterval;
use DatePeriod;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Session;

use App\Models\Attendance;
use App\Models\ClassRoom;
use App\Models\ClassRoomActivity;
use App\Models\Exam;
use App\Models\ExamResult;
use App\Models\Notice;
use App\Models\PresentScheduleRel;
use App\Models\Schedule;
use App\Models\ScheduleSubjectRel;
use App\Models\Student;
use App\Models\Subject;
use App\Models\Teacher;
use App\Models\User;

use Yajra\DataTables\Facades\DataTables;

class TeacherController extends Controller
{
  function backToLoginIfUserIsNull($request)
  {
    if ($request) {
      return redirect()->route('login');
    }
  }

  public function helloworld(Request $request)
  {
    return view('helloworld');
  }

  public function returnToLogin()
  {
    return redirect()
      ->route('login')
      ->with('success', 'sorry but the session timeouted');
  }

  public function checkAnyNull($itemsToCheck)
  {
    $result = false;

    foreach ($itemsToCheck as $itemToCheck) {
      $result = $result || is_null($itemToCheck);
    }

    return $result;
  }

  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index(Request $request)
  {
    try {
      $dashboard_permission = ['admin', 'teacher', 'debug'];
      // $dashboard_permission = array(0 => 'admin', 1 => 'teacher', 2 => "debug");
      $teachers = Teacher::orderBy('id', 'desc')->paginate(10);

      Session::forget('status');

      if (array_search($request->user()->role, $dashboard_permission) > -1) {
        return view('teachers.index', compact('request', 'teachers'));
      } else {
        // not teacher or admin, not permitted
        return view('teachers.not_permitted');
      }
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      $message = $e->getMessage();
      $request->session()->put('status', $message);

      return 'list teacher failed';
    }
  }

  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create(Request $request)
  {
    try {
      return view('teachers.create', compact('request'));
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'add new teacher failed';
    }
  }

  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    try {
      $validatedData = $request->validate([
        'firstName' => 'required',
        'lastName' => 'required',
        'dateOfBirth' => 'required',
        'gender' => 'required',
        'email' => 'required',
        'contact' => 'required',
        'skills' => 'required',
        'password' => 'required',
      ]);

      DB::beginTransaction();
      // Teacher::create($request->post());
      $user = new User();
      $user->name = join(', ', [
        $validatedData['firstName'],
        $validatedData['lastName'],
      ]);
      $user->email = $validatedData['email'];
      $user->password = $validatedData['password'];
      $user->role = 'teacher';
      $user->save();

      // NOTE: save user to get user_id, referenced by student
      $new_user_id = $user->id;

      $teacher = new Teacher();
      $teacher->firstName = $validatedData['firstName'];
      $teacher->lastName = $validatedData['lastName'];
      $teacher->dateOfBirth = $validatedData['dateOfBirth'];
      $teacher->gender = $validatedData['gender'];
      $teacher->email = $validatedData['email'];
      // $teacher->subject_id = join(',', $validatedData['subject_id']);
      $teacher->contact = $validatedData['contact'];
      $teacher->skills = $validatedData['skills'];
      $teacher->user_id = $new_user_id;

      if ($request->avatarAction == 'NO_CHANGE') {
        // $teacher->avatar = NULL;
      } elseif ($request->avatarAction == 'CLEAR') {
        // NOTE: user intent clear avatar
        $teacher->avatar = null;
      } elseif ($request->avatarAction == 'UPDATE_AVATAR') {
        // NOTE: user intent change avatar
        $avatarFileName =
          str_replace('@', '_', str_replace('.', '_', $teacher->email)) .
          '.' .
          $request->avatar->getClientOriginalExtension();

        $request->avatar->move(public_path('avatars'), $avatarFileName);

        $teacher->avatar = $avatarFileName;
      }

      $teacher->save();

      DB::commit();
      Session::forget('status');

      return redirect()
        ->route('teachers.index')
        ->with('success', 'Teacher has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers.create', compact('request'));
    }
  }

  /**
   * Display the specified resource.
   *
   * @param  \App\Teacher  $Teacher
   * @return \Illuminate\Http\Response
   */
  public function show(Teacher $teacher, Request $request)
  {
    try {
      $teacher_id = $teacher->id;
      $teacher = Teacher::with(['schedules'])
        ->where('id', '=', $teacher->id)
        ->get()[0];

      return view('teachers.show', compact('teacher', 'request'));
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      dd($e);

      return 'show student failed';
    }
  }

  /**
   * Show the form for editing the specified resource.
   *
   * @param  \App\Teacher  $Teacher
   * @return \Illuminate\Http\Response
   */
  public function edit(Teacher $teacher, Request $request)
  {
    try {
      $teacher_id = $teacher->id;
      $schedules = Schedule::select()->get();
      $teacher_selected_subject_records = Schedule::with(['teachers'])
        ->whereRelation('teachers', 'teachers.id', '=', $teacher_id)
        ->get();

      $teacher_selected_subject_id = [];
      foreach (
        $teacher_selected_subject_records
        as $teacher_selected_subject_record
      ) {
        array_push(
          $teacher_selected_subject_id,
          $teacher_selected_subject_record->id
        );
      }

      return view(
        'teachers.edit',
        compact(
          'request',
          'teacher',
          'teacher_selected_subject_id',
          'schedules'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'edit student failed';
    }
  }

  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \App\Teacher  $Teacher
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, Teacher $teacher)
  {
    try {
      $pattern = '/schedules_schedule_id_(\d+)/i';
      $request_all = $request->all();

      $validatedData = $request->validate([
        'firstName' => 'required',
        'lastName' => 'required',
        'dateOfBirth' => 'required',
        'gender' => 'required',
        'email' => 'required',
        'contact' => 'required',
        'skills' => 'required',
      ]);

      DB::beginTransaction();

      $teacher = Teacher::find($teacher->id);
      $user_id = $teacher->user_id;
      $user = User::find($user_id);

      $teacher->firstName = $validatedData['firstName'];
      $teacher->lastName = $validatedData['lastName'];
      $teacher->dateOfBirth = $validatedData['dateOfBirth'];
      $teacher->gender = $validatedData['gender'];
      $teacher->email = $validatedData['email'];
      $teacher->contact = $validatedData['contact'];
      $teacher->skills = $validatedData['skills'];

      // $teacher->fill($request->post())->save();
      $user->name = join(', ', [
        $validatedData['firstName'],
        $validatedData['lastName'],
      ]);

      if ($request['password']) {
        $user->password = $request['password'];
      }

      if ($request->avatarAction == 'NO_CHANGE') {
      } elseif ($request->avatarAction == 'CLEAR') {
        // NOTE: user intent clear avatar
        $teacher->avatar = null;
      } elseif ($request->avatarAction == 'UPDATE_AVATAR') {
        // NOTE: user intent change avatar
        $avatarFileName =
          str_replace('@', '_', str_replace('.', '_', $teacher->email)) .
          '.' .
          $request->avatar->getClientOriginalExtension();

        $request->avatar->move(public_path('avatars'), $avatarFileName);

        $teacher->avatar = $avatarFileName;
      }

      // NOTE: update student applied subject
      $applied_subjects = $teacher->schedules;
      foreach ($applied_subjects as $key) {
        $teacher->schedules()->detach($key->id);
      }

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $schedule = Schedule::find($m[1]);
            if (is_null($schedule)) {
            } else {
              $teacher->schedules()->attach($schedule->id);
            }
          }
        }
      }

      $teacher->save();
      $user->save();

      DB::commit();

      Session::forget('status');

      return redirect()
        ->route('teachers.index')
        ->with('success', 'teacher Has Been updated successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers.edit', compact('teacher', 'request'));
    }
  }

  public function getTeacherScheduleJson()
  {
    try {
      $teacher = Teacher::find(1);
      $schedules = $teacher->schedules;

      return dd($schedules[0]->subject);
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'getTeacherScheduleJson failed';
    }
  }

  /**
   * Remove the specified resource from storage.
   *
   * @param  \App\Teacher  $Teacher
   * @return \Illuminate\Http\Response
   */
  public function destroy(Teacher $teacher)
  {
    try {
      DB::beginTransaction();
      $teacher_id = $teacher->id;
      // $teacher->delete();

      $teacher = Teacher::find($teacher_id);
      $user_id = $teacher->user_id;
      $user = User::find($user_id);

      $teacher->delete();
      if ($user) {
        $user->delete();
      }

      DB::commit();
      return redirect()
        ->route('teachers.index')
        ->with('success', 'Teacher has been deleted successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      return 'delete teacher failed';
    }
  }

  public function getTeachersJson(Request $request)
  {
    try {
      $arr = [];

      if (is_null($request->query('q'))) {
        // NOTE: return all records
        $teachers = teacher::all();
      } else {
        // NOTE: request with query word
        $q_word = $request->query('q');
        $teachers = teacher::where('email', 'LIKE', '%' . $q_word . '%')->get();
      }

      foreach ($teachers as $row) {
        array_push($arr, [
          // "name" => $row->name,
          'id' => $row->id,
          'teacherId' => $row->teacherId,
          'firstName' => $row->firstName,
          'lastName' => $row->lastName,
          'dateOfBirth' => $row->dateOfBirth,
          'gender' => $row->gender,
          'email' => $row->email,
          'contact' => $row->contact,
          'skills' => $row->skills,
        ]);
      }
      return response()->json($arr);
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'getTeachersJson failed';
    }
  }

  public function dtGetTeachers()
  {
    $teachers = Teacher::select([
      'id',
      'firstName',
      'lastName',
      'gender',
      'email',
    ]);

    return DataTables::eloquent($teachers)->toJson();
  }

  public function showClassrooms(Request $request)
  {
    $email_to_find = $request->user()->email;
    $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

    return view(
      'teachers.showClassrooms',
      compact('request', 'current_teacher')
    );
  }

  public function showInfo(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      // $current_student = $current_teacher;

      $schedules = Schedule::with(['subjects'])->get();

      $teacher_selected_subject_records = Schedule::whereRelation(
        'teachers',
        'teachers.id',
        '=',
        $current_teacher->id
      )->get();

      $teacher_selected_subject_id = [];
      foreach (
        $teacher_selected_subject_records
        as $teacher_selected_subject_record
      ) {
        array_push(
          $teacher_selected_subject_id,
          $teacher_selected_subject_record->id
        );
      }

      return view(
        'teachers.showInfo',
        compact(
          'request',
          'current_teacher',
          'schedules',
          'teacher_selected_subject_id'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return redirect('/err_route');
    }
  }

  public function showApplicableSchedules(Request $request)
  {
    try {
      if (TeacherController::checkAnyNull([$request->user()])) {
        return TeacherController::returnToLogin();
      }

      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];
      $schedules = $current_teacher->schedules;

      return view(
        'teachers.showApplicableSchedules',
        compact('request', 'current_teacher', 'schedules')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function showSchedules(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];
      $schedules = $current_teacher->schedules;

      return view(
        'teachers.showSchedules',
        compact('request', 'current_teacher', 'schedules')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function teacherShowNotifications(Request $request)
  {
    return view('helloworld');
  }

  public function showNotices(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.showNotices',
        compact('request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function showDashboard(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $teacherId = $current_teacher->id;

      $num_of_schedule = Schedule::with(['teachers'])
        ->whereRelation('teachers', 'teachers.id', '=', $current_teacher->id)
        ->count();
      $num_of_student = Student::count();
      $num_of_teacher = Teacher::count();
      $num_of_exam = Exam::with(['teachers'])
        ->whereRelation('teachers', 'teachers.id', '=', $current_teacher->id)
        ->count();

      return view(
        'teachers.showDashboard',
        compact(
          'request',
          'num_of_student',
          'num_of_teacher',
          'num_of_exam',
          'num_of_schedule',
          'current_teacher',
          'teacherId'
        )
      );
    } catch (\Exception $e) {
      return redirect()->route('login');
    }
  }

  public function teacherUpdateSubject(Request $request)
  {
    try {
      $pattern = '/schedules_schedule_id_(\d)+/i';

      $request_all = $request->all();

      $email_to_find = $request->user()->email;
      $teacher = Teacher::where('email', '=', $email_to_find)->get()[0];
      $teacher_id = $teacher->id;

      $teacher = Teacher::find($teacher_id);

      $applied_subjects = $teacher->schedules;
      foreach ($applied_subjects as $key) {
        $teacher->schedules()->detach($key->id);
      }

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $schedule = Schedule::find($m[1]);
            if (is_null($schedule)) {
            } else {
              $teacher->schedules()->attach($schedule->id);
            }
          }
        }
      }

      Session::forget('status');

      return redirect()
        ->route('teacherShowDashboard')
        ->with('success', 'update subject selection done');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers.showDashboard', compact('request'));
    }
  }

  public function updateSubject(Request $request, string $id)
  {
    try {
      $request_all = $request->all();

      $subject = Subject::find($id);
      $subject->subjectTitle = $request_all['subjectTitle'];
      $subject->syllabusDetails = $request_all['syllabusDetails'];
      $subject->save();

      return redirect()
        ->route('teacherShowSubject')
        ->with('success', 'update subject selection done');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $subject = Subject::find($id);
      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers.EditSubject', compact('request', 'subject'));
    }
  }

  public function showSubjects(Request $request)
  {
    try {
      if (TeacherController::checkAnyNull([$request->user()])) {
        return TeacherController::returnToLogin();
      }

      $email_to_find = $request->user()->email;

      $subjects = Subject::select(['id', 'subjectTitle'])
        ->where('deleted', '=', 'false')
        ->get();

      $schedules = Schedule::with(['subjects'])->get();

      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];
      $current_teacher_id = $current_teacher->id;

      $teacher_selected_subject_records = Schedule::whereRelation(
        'teachers',
        'teachers.id',
        '=',
        $current_teacher->id
      )->get();

      $teacher_selected_subject_id = [];
      foreach (
        $teacher_selected_subject_records
        as $teacher_selected_subject_record
      ) {
        array_push(
          $teacher_selected_subject_id,
          $teacher_selected_subject_record->id
        );
      }

      Session::forget('status');

      return view(
        'teachers.showSubjects',
        compact(
          'request',
          'subjects',
          'current_teacher',
          'schedules',
          'teacher_selected_subject_id'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return 'teacherShowSubjects failed';
    }
  }

  public function showApplySubjects(Request $request)
  {
    try {
      // TODO: remove me
      if (TeacherController::checkAnyNull([$request->user()])) {
        return TeacherController::returnToLogin();
      }

      $email_to_find = $request->user()->email;

      $subjects = Subject::select(['id', 'subjectTitle'])
        ->where('deleted', '=', 'false')
        ->get();

      $schedules = Schedule::with(['subjects'])->get();

      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];
      $current_teacher_id = $current_teacher->id;

      $teacher_selected_subject_records = Schedule::whereRelation(
        'teachers',
        'teachers.id',
        '=',
        $current_teacher->id
      )->get();

      $teacher_selected_subject_id = [];
      foreach (
        $teacher_selected_subject_records
        as $teacher_selected_subject_record
      ) {
        array_push(
          $teacher_selected_subject_id,
          $teacher_selected_subject_record->id
        );
      }

      Session::forget('status');

      return view(
        'teachers.showSubjects',

        compact(
          'request',
          'subjects',
          'current_teacher',
          'schedules',
          'teacher_selected_subject_id'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return 'teacherShowSubjects failed';
    }
  }

  public function viewSubject(Request $request, string $id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $subject = Subject::find($id);
      return view(
        'teachers.ViewSubject',
        compact('request', 'current_teacher', 'subject')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'show student failed';
    }
  }

  public function editSubject(Request $request, string $id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $subject = Subject::find($id);
      return view(
        'teachers.EditSubject',
        compact('request', 'current_teacher', 'subject')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'show student failed';
    }
  }

  public function listSubject(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.ListSubject',
        compact('request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'list subject failed';
    }
  }

  public function listStudent(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.ListStudent',
        compact('request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'list student failed';
    }
  }

  public function viewStudent(Request $request, string $student_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $student = Student::with(['schedules'])
        ->where('id', '=', $student_id)
        ->get()[0];

      return view(
        'teachers.ViewStudent',
        compact('request', 'student', 'current_teacher')
      );
    } catch (\Exception $e) {
      // dd($e);
      return 'show student failed';
    }
  }

  public function viewSchedule(Request $request, string $id)
  {
    try {
      $schedule = Schedule::find($id);

      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.ViewSchedule',
        compact('schedule', 'request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'show schedule failed';
    }
  }

  public function updateSchedule(Request $request, string $id)
  {
    try {
      $validatedData = $request->validate([
        'class_room_id' => 'required',
        'description' => 'required',
        'subject_id' => 'required',
        'subject' => 'required', //TODO: rename to "name"
        'startTime' => 'required',
        'endTime' => 'required',
      ]);

      DB::beginTransaction();

      $schedule = Schedule::find($id);
      $schedule->startTime = $validatedData['startTime'];
      $schedule->endTime = $validatedData['endTime'];
      $schedule->description = $validatedData['description'];
      $schedule->subject = $validatedData['subject'];
      $schedule->save();

      $class_room_id = $validatedData['class_room_id'];
      $startTime = $validatedData['startTime'];
      $endTime = $validatedData['endTime'];
      $begin = new DateTime($startTime);
      $end = new DateTime($endTime);
      $interval = DateInterval::createFromDateString('1 day');
      $period = new DatePeriod($begin, $interval, $end);
      $arr = [];
      foreach ($period as $dt) {
        array_push($arr, $dt->format('Y-m-d'));
      }
      array_push($arr, $end->format('Y-m-d'));

      // TODO: some checking here

      // delete existing booking schedule-classroom
      $deleted = ClassRoomActivity::where(
        'schedule_id',
        $schedule->id
      )->delete();

      foreach ($arr as $day) {
        $class_room_activity = new ClassRoomActivity();
        $class_room_activity->class_room_id = $class_room_id;
        $class_room_activity->schedule_id = $schedule->id;
        $class_room_activity->date_epoch = strtotime($day);
        $class_room_activity->save();
      }

      // $schedule->fill($request->post())->save();

      DB::commit();

      Session::forget('status');

      return redirect()
        ->route('teachersListSchedule')
        ->with('success', 'Schedule Has Been updated successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();

      $schedule = Schedule::find($id);
      $message = $e->getMessage();
      $request->session()->put('status', $message);

      return view('teachers/editSchedule', compact('request', 'schedule'));
    }
  }

  public function EditSchedule(Request $request, string $id)
  {
    try {
      $schedule = Schedule::find($id);
      // dd($schedule->classrooms);
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.EditSchedule',
        compact('schedule', 'request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'show schedule failed';
    }
  }

  public function destroySchedule(Request $request, string $id)
  {
    try {
      $schedule = Schedule::find($id);
      $schedule->delete();

      return redirect()
        ->route('teachersListSchedule')
        ->with('success', 'Schedule has been deleted successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'delete schedule failed';
    }
  }

  public function listSchedule(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view(
        'teachers.ListSchedule',
        compact('request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'list student failed';
    }
  }

  public function editStudent(Request $request, string $student_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $student = Student::with(['schedules'])
        ->where('id', '=', $student_id)
        ->get()[0];

      $teacher_id = $current_teacher->id;
      // $schedules = Schedule::select()->get();
      $teacher = Teacher::with(['schedules'])
        ->where('id', '=', $teacher_id)
        ->get()[0];
      $schedules = $teacher->schedules;

      $student_selected_subject_records = Schedule::with(['students'])
        ->whereRelation('students', 'students.id', '=', $student_id)
        ->get();
      $student_selected_subject_id = [];
      foreach (
        $student_selected_subject_records
        as $student_selected_subject_record
      ) {
        array_push(
          $student_selected_subject_id,
          $student_selected_subject_record->id
        );
      }

      return view(
        'teachers.EditStudent',
        compact(
          'request',
          'student',
          'current_teacher',
          'schedules',
          'student_selected_subject_id'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function createStudent(Request $request)
  {
    $email_to_find = $request->user()->email;
    $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

    return view('teachers.AddStudent', compact('request', 'current_teacher'));
  }

  public function createSchedule(Request $request)
  {
    $email_to_find = $request->user()->email;
    $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

    return view('teachers.AddSchedule', compact('request', 'current_teacher'));
  }

  public function storeSchedule(Request $request)
  {
    try {
      $validatedData = $request->validate([
        'class_room_id' => 'required',
        'subject_id' => 'required',
        'subject' => 'required', //TODO: rename field, change it to "name"
        'startTime' => 'required',
        'endTime' => 'required',
        'description' => 'required',
      ]);

      // Schedule::create($request->post());
      DB::beginTransaction();

      $schedule = new Schedule();

      // TODO: need review
      $schedule->day = '1';
      // TODO: need review

      $schedule->startTime = $validatedData['startTime'];
      $schedule->endTime = $validatedData['endTime'];
      $schedule->description = $validatedData['description'];
      $schedule->subject = $validatedData['subject']; //TODO: rename field, change it to "name"
      $schedule->save();
      $newScheduleId = $schedule->id;

      $class_room_id = $validatedData['class_room_id'];
      $startTime = $validatedData['startTime'];
      $endTime = $validatedData['endTime'];

      // // get the days in between startTime and endTime
      $begin = new DateTime($startTime);
      $end = new DateTime($endTime);
      $interval = DateInterval::createFromDateString('1 day');
      $period = new DatePeriod($begin, $interval, $end);

      $arr = [];
      foreach ($period as $dt) {
        array_push($arr, $dt->format('Y-m-d'));
      }
      array_push($arr, $end->format('Y-m-d'));

      foreach ($arr as $day) {
        $class_room_activity = new ClassRoomActivity();
        $class_room_activity->class_room_id = $class_room_id;
        $class_room_activity->schedule_id = $newScheduleId;
        $class_room_activity->date_epoch = strtotime($day);
        $class_room_activity->save();
      }

      $schedule_subject_rel = new ScheduleSubjectRel();
      $schedule_subject_rel->subject_id = $validatedData['subject_id'];
      $schedule_subject_rel->schedule_id = $newScheduleId;
      $schedule_subject_rel->save();

      DB::commit();

      Session::forget('status');

      return redirect()
        ->route('teachersListSchedule')
        ->with('success', 'Schedule has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();
      // dd($e);
      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers.AddSchedule', compact('request'));
    }
  }

  public function storeStudent(Request $request)
  {
    // create
    try {
      $validatedData = $request->validate([
        'firstName' => 'required',
        'lastName' => 'required',
        'dateOfBirth' => 'required',
        'gender' => 'required',
        'email' => 'required',
        'address' => 'required',
        'password' => 'required',
      ]);

      DB::beginTransaction();
      $user = new User();
      $user->name = join(', ', [
        $validatedData['firstName'],
        $validatedData['lastName'],
      ]);
      $user->email = $validatedData['email'];
      $user->password = $validatedData['password'];
      $user->role = 'student';
      $user->save();

      // NOTE: save user to get user_id, referenced by student
      $new_user_id = $user->id;

      $student = new Student();
      $student->firstName = $validatedData['firstName'];
      $student->lastName = $validatedData['lastName'];
      $student->dateOfBirth = $validatedData['dateOfBirth'];
      $student->gender = $validatedData['gender'];
      $student->email = $validatedData['email'];
      $student->address = $validatedData['address'];
      $student->user_id = $new_user_id;

      if ($request->avatarAction == 'NO_CHANGE') {
        $student->avatar = null;
      } elseif ($request->avatarAction == 'CLEAR') {
        // NOTE: user intent clear avatar
        $student->avatar = null;
      } elseif ($request->avatarAction == 'UPDATE_AVATAR') {
        // NOTE: user intent change avatar
        $avatarFileName =
          str_replace('@', '_', str_replace('.', '_', $student->email)) .
          '.' .
          $request->avatar->getClientOriginalExtension();

        $request->avatar->move(public_path('avatars'), $avatarFileName);

        $student->avatar = $avatarFileName;
      }

      $student->save();

      DB::commit();

      Session::forget('status');
      return redirect()
        ->route('teachersListStudent')
        ->with('success', 'Student has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();

      // dd($e);

      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('students.create', compact('request'));
      // return 'save student failed';
    }
  }

  public function updateStudent(Request $request, string $student_id)
  {
    try {
      $validatedData = $request->validate([
        'firstName' => 'required',
        'lastName' => 'required',
        'dateOfBirth' => 'required',
        'gender' => 'required',
        'email' => 'required',
        'address' => 'required',
      ]);
      $pattern = '/schedules_schedule_id_(\d+)/i';
      $request_all = $request->all();

      DB::beginTransaction();

      $student = Student::find($student_id);
      $user_id = $student->user_id;
      $user = User::find($user_id);

      $student->firstName = $validatedData['firstName'];
      $student->lastName = $validatedData['lastName'];
      $student->dateOfBirth = $validatedData['dateOfBirth'];
      $student->gender = $validatedData['gender'];
      $student->email = $validatedData['email'];
      $student->address = $validatedData['address'];

      $user->name = join(', ', [
        $validatedData['firstName'],
        $validatedData['lastName'],
      ]);

      $student->schedules()->detach();
      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $schedule = Schedule::find($m[1]);
            if (is_null($schedule)) {
            } else {
              $student->schedules()->attach($schedule->id);
            }
          }
        }
      }

      if ($request['password']) {
        $user->password = $request['password'];
      }

      if ($request->avatar) {
        // process avatar
        $avatarFileName =
          str_replace('@', '_', str_replace('.', '_', $student->email)) .
          '.' .
          $request->avatar->getClientOriginalExtension();

        $request->avatar->move(public_path('avatars'), $avatarFileName);

        $student->avatar = $avatarFileName;
      } else {
        $student->avatar = null;
      }

      $student->save();
      $user->save();

      DB::commit();

      return redirect()
        ->route('teachersListStudent')
        ->with('success', 'Student has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();

      // dd($e);

      $student = Student::find($student_id);
      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teachers/EditStudent', compact('request', 'student'));
    }
  }

  public function applySubject(Teacher $teacher, Request $request, string $id)
  {
    try {
      $pattern = '/schedules_schedule_id_(\d+)/i';

      $request_all = $request->all();

      $email_to_find = $request->user()->email;
      $teacher = Teacher::where('email', '=', $email_to_find)->get()[0];
      $teacher_id = $teacher->id;

      $teacher = Teacher::find($teacher_id);

      // clear all applied subject
      $applied_subjects = $teacher->schedules;
      foreach ($applied_subjects as $key) {
        $teacher->schedules()->detach($key->id);
      }

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $schedule = Schedule::find($m[1]);
            if (is_null($schedule)) {
            } else {
              $teacher->schedules()->attach($schedule->id);
            }
          }
        }
      }

      Session::forget('status');

      return redirect()
        ->route('teacherShowApplySubjects')
        ->with('success', 'subjects application success !');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();
      // dd($e);
      $message = $e->getMessage();
      $request->session()->put('status', $message);
      return view('teacher_dashboard', compact('teacher', 'request'));
      // return 'update student failed';
    }
  }

  public function updateInfo(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $teacher = Teacher::where('email', '=', $email_to_find)->get()[0];
      $teacher_id = $teacher->id;

      $pattern = '/schedules_schedule_id_(\d+)/i';

      $request_all = $request->all();

      $validatedData = $request->validate([
        'firstName' => 'required',
        'lastName' => 'required',
        'dateOfBirth' => 'required',
        'gender' => 'required',
        'email' => 'required',
        'contact' => 'required',
      ]);

      DB::beginTransaction();

      $teacher = Teacher::find($teacher_id);
      $user_id = $teacher->user_id;
      $user = User::find($user_id);

      $teacher->firstName = $validatedData['firstName'];
      $teacher->lastName = $validatedData['lastName'];
      $teacher->dateOfBirth = $validatedData['dateOfBirth'];
      $teacher->gender = $validatedData['gender'];
      $teacher->email = $validatedData['email'];
      $teacher->contact = $validatedData['contact'];

      $user->name = join(', ', [
        $validatedData['firstName'],
        $validatedData['lastName'],
      ]);

      // NOTE: update subject selection
      $teacher->schedules()->detach();

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $schedule = Schedule::find($m[1]);
            if (is_null($schedule)) {
              // TODO: comment here
            } else {
              $teacher->schedules()->attach($schedule);
            }
          }
        }
      }

      if ($request['password']) {
        $user->password = $request['password'];
      }

      if ($request->avatarAction == 'NO_CHANGE') {
      } elseif ($request->avatarAction == 'CLEAR') {
        // NOTE: user intent clear avatar
        $teacher->avatar = null;
      } elseif ($request->avatarAction == 'UPDATE_AVATAR') {
        // NOTE: user intent change avatar
        $avatarFileName =
          str_replace('@', '_', str_replace('.', '_', $teacher->email)) .
          '.' .
          $request->avatar->getClientOriginalExtension();

        $request->avatar->move(public_path('avatars'), $avatarFileName);

        $teacher->avatar = $avatarFileName;
      }

      $teacher->save();
      $user->save();

      DB::commit();

      Session::forget('status');

      return redirect()
        ->route('teacherInfo')
        ->with('success', 'Teacher information has Been updated successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      DB::rollback();
      // dd($e);

      $message = $e->getMessage();
      $request->session()->put('status', $message);

      return redirect()
        ->route('teacherShowDashboard')
        ->with('success', 'Student Has Been updated successfully');
    }
  }

  public function viewClassRoom(Request $request, string $id)
  {
    $classroom_id = $id;
    $email_to_find = $request->user()->email;
    $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

    $classroom = ClassRoom::find($classroom_id);
    return view(
      'teachers.ViewClassRoom',
      compact('request', 'classroom', 'current_teacher')
    );
  }

  public function showExams(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $teacher_id = $current_teacher->id;

      $exams = Exam::where('teacher_id', '=', $teacher_id);

      return view(
        'teachers.showExams',
        compact('exams', 'request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'sorry but show exam failed';
    }
  }

  public function updateExamResult(
    Request $request,
    string $teacher_id,
    string $exam_id
  ) {
    try {
      $pattern = '/exam_result.student_id_(\d+)/i';
      $request_all = $request->all();

      DB::beginTransaction();

      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['exams'])
        ->where('email', $email_to_find)
        ->get()[0];

      $exam = Exam::with(['exam_results'])
        ->where('id', '=', $exam_id)
        ->get()[0];

      // $exam->exam_results()->detach();

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value) {
            $student_id = $m[1];
            // $student = Student::with(['exam_results'])
            //     ->where('id','=',$student_id)
            //     ->get();

            $exam_result = ExamResult::updateOrCreate(
              [
                'student_id' => $student_id,
                'teacher_id' => $teacher_id,
                'exam_id' => $exam_id,
              ],
              [
                'exam_id' => $exam_id,
                'result' => $value,
                'remarks' => 'default remarks',
              ]
            );
          } else {
            // NOTE: if the value is empty for reasons
            $student_id = $m[1];
            // $student = Student::with(['exam_results'])
            //     ->where('id','=',$student_id)
            //     ->get();

            $exam_result = ExamResult::updateOrCreate(
              [
                'student_id' => $student_id,
                'teacher_id' => $teacher_id,
                'exam_id' => $exam_id,
              ],
              [
                'exam_id' => $exam_id,
                'result' => 0,
                'remarks' => 'value is empty, default to 0 marks',
              ]
            );
          }
        }
      }

      DB::commit();

      return redirect()->route('teacherShowExamResult', [$teacher_id]);
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      DB::rollback();
    }
  }

  public function showExamResult(Request $request, string $teacher_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $test_teacher = Teacher::with(['exams'])
        ->where('id', '=', $teacher_id)
        ->get()[0];

      $exams = $test_teacher->exams;
      $exam_results = ExamResult::where('teacher_id', '=', $teacher_id)->get();

      return view(
        'teachers.showExamResults',
        compact('request', 'current_teacher', 'exams', 'exam_results')
      );
    } catch (\Exception $e) {
      return route('teacherShowDashboard');
    }
  }

  public function showAttendances(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $teacher_id = $current_teacher->id;

      return view(
        'teachers.show.attendances.index',
        compact('request', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return route('teacherShowDashboard');
    }
  }

  public function dtGetAttendancesByTeacherId(
    Request $request,
    string $teacher_id
  ) {
    try {
      $attendances = Attendance::with(['teachers'])->whereHas(
        'teachers',
        function ($q) use ($teacher_id) {
          $q->where('teacher_id', '=', $teacher_id);
        }
      );

      return DataTables::eloquent($attendances)->toJson();
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      return 'sorry but list exam failed';
    }
  }

  public function dtGetExamsByTeacherId(Request $request, string $teacher_id)
  {
    try {
      $exams = Exam::with(['teachers', 'subject'])->whereHas(
        'teachers',
        function ($q) use ($teacher_id) {
          $q->where('teacher_id', '=', $teacher_id);
        }
      );

      return DataTables::eloquent($exams)->toJson();
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'sorry but list exam failed';
    }
  }

  public function dtGetExamResultsByTeacherId(
    Request $request,
    string $teacher_id
  ) {
    try {
      // $exams = Exam::select(['id',
      // 'date',
      // 'remarks',
      // 'subject_id']);
      $exams = ExamResult::with(['teachers'])->whereHas('teachers', function (
        $q
      ) use ($teacher_id) {
        $q->where('teacher_id', '=', $teacher_id);
      });

      return DataTables::eloquent($exams)->toJson();
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'sorry but list exam failed';
    }
  }

  public function dtGetSchedulesByTeacherId(
    Request $request,
    string $teacher_id
  ) {
    try {
      $schedules = Schedule::with([
        'teachers',
        'classrooms',
        'subjects',
      ])->whereHas('teachers', function ($q) use ($teacher_id) {
        $q->where('teacher_id', '=', $teacher_id);
      });

      return DataTables::eloquent($schedules)->toJson();
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function showStudentAttendance(Request $request, string $schedule_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];

      $schedules = Schedule::with(['students'])
        ->where('id', '=', $schedule_id)
        ->get();

      $present_schedule_records = PresentScheduleRel::where(
        'schedule_id',
        '=',
        $schedule_id
      )->get();

      $present_student_ids = [];
      foreach ($present_schedule_records as $record) {
        array_push($present_student_ids, $record->student_id);
      }

      $students = $schedules[0]->students;

      return view(
        'teachers.showStudentAttendance',
        compact([
          'request',
          'current_teacher',
          'students',
          'schedule_id',
          'present_student_ids',
        ])
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function showExamResultsById(Request $request, string $exam_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules', 'exams'])
        ->where('email', $email_to_find)
        ->get()[0];

      $exam = Exam::with(['students'])
        ->where('id', '=', $exam_id)
        ->get()[0];

      // NOTE: all student involved in exam
      $students_with_exam = $exam->students;

      // NOTE: student with exam result in db
      $current_exam_results = ExamResult::where(
        'exam_id',
        '=',
        $exam_id
      )->get();

      // NOTE: array to be printed in form
      $student_with_exam_result = [];

      foreach ($students_with_exam as $student) {
        $student_id_to_check = $student->id;

        // NOTE: initialize with default value
        $student_with_exam_result[$student_id_to_check] = 0;

        for ($x = 0; $x < count($current_exam_results); $x++) {
          if ($current_exam_results[$x]->student_id == $student_id_to_check) {
            // NOTE: student with result currently in db
            $student_with_exam_result[$student_id_to_check] =
              $current_exam_results[$x]->result;
            break;
          }
        }
      }

      return view(
        'teachers.showExamResultsById',
        compact(
          'request',
          'current_teacher',
          'students_with_exam',
          'exam_id',
          'current_exam_results',
          'student_with_exam_result'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function updateAttendance(
    Request $request,
    string $teacher_id,
    string $schedule_id
  ) {
    try {
      $pattern = '/present_student_id_(\d+)/i';
      $request_all = $request->all();

      $schedule = Schedule::find($schedule_id);
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];

      // $schedules = $current_teacher->schedules;
      $schedule->presentStudent()->detach();

      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $student = Student::find($m[1]);
            if (is_null($schedule)) {
              // NOTE: no action performed when check box empty
            } else {
              $schedule->presentStudent()->attach($student);
            }
          }
        }
      }

      return redirect()->route('teacherShowApplicableSchedules');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function ViewExam(Request $request, string $exam_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $exam = Exam::find($exam_id);
      $exam_with_students = Exam::with(['students'])
        ->where('id', '=', $exam_id)
        ->get()[0]->students;

      $subject = Subject::find($exam->subject_id);

      return view(
        'teachers.ViewExam',
        compact(
          'request',
          'current_teacher',
          'exam',
          'subject',
          'exam_with_students'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);

      return 'show student failed';
    }
  }

  public function viewAttendance(Request $request, string $attendance_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $attendance = Attendance::find($attendance_id);

      return view(
        'teachers.ViewAttendance',
        compact('request', 'attendance', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function viewNotice(Request $request, string $notice_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $notice = Notice::find($notice_id);

      return view(
        'teachers.ViewNotice',
        compact('request', 'notice', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function editNotice(Request $request, string $notice_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $notice = Notice::find($notice_id);

      return view(
        'teachers.EditNotice',
        compact('request', 'notice', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      return route('teacherShowDashboard');
    }
  }

  public function editAttendance(Request $request, string $attendance_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $attendance = Attendance::find($attendance_id);

      return view(
        'teachers.EditAttendance',
        compact('request', 'attendance', 'current_teacher')
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      return route('teacherShowDashboard');
    }
  }

  public function updateNotice(Request $request, string $notice_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $teacher_id = $current_teacher->id;

      $request_all = $request->all();
      $notice = Notice::find($notice_id);
      $notice->from = $current_teacher->email;
      $notice->to = $request_all['to'];
      $notice->subject = $request_all['subject'];
      $notice->content = $request_all['content'];
      $notice->save();

      return redirect()->route('teacherShowNotices');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      return route('teacherShowDashboard');
    }
  }

  public function dtGetTeacherNotices(Request $request, string $teacher_id)
  {
    try {
      $teacher = Teacher::find($teacher_id);
      $notices = Notice::select()->where('from', '=', $teacher->email);

      return DataTables::eloquent($notices)->toJson();
    } catch (\Exception $e) {
      throw $e;
    }
  }

  public function destroyNotice(Request $request, string $notice_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];
      $teacher_id = $current_teacher->id;

      $notice = Notice::find($notice_id);
      $notice->delete();

      return redirect()
        ->route('teacherShowNotices')
        ->with('success', 'Notice has been deleted successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      return 'delete notice failed';
    }
  }

  public function createExam(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view('teachers.AddExam', compact('request', 'current_teacher'));
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function editExam(Request $request, string $exam_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $exam = Exam::with(['students'])
        ->where('id', '=', $exam_id)
        ->get()[0];

      $students_with_exam = $exam->students;
      $students = Student::all();

      $exam_student_involved_id = [];
      foreach ($students_with_exam as $student) {
        array_push($exam_student_involved_id, $student->id);
      }

      $subject_selected = Subject::find($exam->subject_id);
      // dd($subject_selected);

      return view(
        'teachers.EditExam',
        compact(
          'request',
          'exam',
          'current_teacher',
          'students',
          'exam_student_involved_id',
          'subject_selected'
        )
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function storeExam(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      DB::beginTransaction();

      $exam = new Exam();
      // NOTE: save to get exam_id
      $exam->fill($request->post())->save();

      $exam_id = $exam->id;
      $teacher_id = $current_teacher->id;

      $teacher = Teacher::find($teacher_id);
      $teacher->exams()->attach($exam);

      DB::commit();

      return redirect()
        ->route('teacherShowExams')
        ->with('success', 'Exam has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      DB::rollback();

      return 'add exam failed';
    }
  }

  public function destroyExam(Request $request, string $exam_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      DB::beginTransaction();

      $exam = Exam::find($exam_id);
      $exam->delete();

      DB::commit();

      return redirect()
        ->route('teacherShowExams')
        ->with('success', 'Exam has been deleted successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      DB::rollback();

      return 'delete exam failed';
    }
  }

  public function updateExam(Request $request, string $exam_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      $pattern = '/exam.student_id_(\d+)/i';
      $request_all = $request->all();

      DB::beginTransaction();

      $exam = Exam::find($exam_id);
      $exam->fill($request->post())->save();

      $exam->students()->detach();
      foreach ($request_all as $key => $value) {
        if (preg_match($pattern, $key, $m) == 1) {
          if ($value == 'on') {
            $student = Student::find($m[1]);
            if (is_null($student)) {
            } else {
              $exam->students()->attach($student->id);
            }
          }
        }
      }

      DB::commit();

      return redirect()
        ->route('teacherShowExams')
        ->with('success', 'Exam Has Been updated successfully');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      DB::rollback();
    }
  }

  public function getUnreadNoticeCount(Request $request, string $teacher_id)
  {
    try {
      $already_read_notices = DB::select(
        'select notice_id from `notice_teacher_rel` where teacher_id = ?',
        [$teacher_id]
      );

      $already_read_ids = [];
      foreach ($already_read_notices as $already_read_notice) {
        array_push($already_read_ids, $already_read_notice->notice_id);
      }

      dd($already_read_ids);

      $all_unread_notices = Notice::select(['id', 'date', 'subject', 'content'])
        ->whereNotIn('id', $already_read_ids)
        ->count();

      return json_encode(['unread' => $all_unread_notices]);
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }

  public function createNotice(Request $request)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      return view('teachers.AddNotice', compact('request', 'current_teacher'));
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }
    }
  }

  public function storeNotice(Request $request)
  {
    try {
      $validatedData = $request->validate([
        'date' => 'required',
        'to' => 'required',
        'subject' => 'required',
        'content' => 'required',
      ]);

      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::where('email', $email_to_find)->get()[0];

      DB::beginTransaction();

      $notice = new Notice();
      $notice->fill($validatedData);
      $notice->from = $current_teacher->email;
      $notice->save();

      DB::commit();

      return redirect()
        ->route('teacherShowNotices')
        ->with('success', 'Notice has been created successfully.');
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
      DB::rollback();

      return 'add notice failed';
    }
  }

  public function dtGetTeacherSimpleSchedules(
    Request $request,
    string $teacher_id
  ) {
    $schedules = Schedule::with(['classrooms', 'subjects', 'teachers'])
      ->whereRelation('teachers', 'teachers.id', '=', $teacher_id)
      ->orderBy('id', 'desc')
      ->limit(10)
      ->get();

    return response()->json($schedules);
  }

  public function dtGetTeacherSimpleExams(Request $request, string $teacher_id)
  {
    $exams = Exam::with(['subject', 'teachers'])
      ->whereRelation('teachers', 'teachers.id', '=', $teacher_id)
      ->orderBy('id', 'desc')
      ->limit(10)
      ->get();

    return response()->json($exams);
  }

  public function viewStudentAttendance(Request $request, string $schedule_id)
  {
    try {
      $email_to_find = $request->user()->email;
      $current_teacher = Teacher::with(['schedules'])
        ->where('email', $email_to_find)
        ->get()[0];

      $schedules = Schedule::with(['students'])
        ->where('id', '=', $schedule_id)
        ->get();

      $present_schedule_records = PresentScheduleRel::where(
        'schedule_id',
        '=',
        $schedule_id
      )->get();

      $present_student_ids = [];
      foreach ($present_schedule_records as $record) {
        array_push($present_student_ids, $record->student_id);
      }

      $students = $schedules[0]->students;

      return view(
        'teachers.viewStudentAttendance',
        compact([
          'request',
          'current_teacher',
          'students',
          'schedule_id',
          'present_student_ids',
        ])
      );
    } catch (\Exception $e) {
      if (is_null($request->user())) {
        return redirect()->route('login');
      }

      // dd($e);
    }
  }
}
