<?php

namespace App\Modules\Timetable\Model;

use App\Facades\General;
use App\Models\Tenant;
use App\Modules\Staff\Model\Staff;
use App\Modules\Student\Model\Section;
use App\Modules\Student\Model\StudentClass;
use App\Modules\Student\Model\Subject;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Yajra\DataTables\Facades\DataTables;

class Timetable extends Tenant
{

    use SoftDeletes;

    protected $fillable = ['account_id',
        'class_id',
        'section_id',
        'teacher_id',
        'subject_id',
        'week_day',
        'start_time',
        'end_time',
        'is_online',
        'grace_period',
        'remark',
        'created_by',
        'updated_by'];

    /**
     * @return BelongsTo
     */
    public function studentClass()
    {
        return $this->belongsTo(StudentClass::class, 'class_id')->withDefault();
    }

    /**
     * @return BelongsTo
     */
    public function section()
    {
        return $this->belongsTo(Section::class, 'section_id')->withDefault();
    }

    /**
     * @return BelongsTo
     */
    public function teacher()
    {
        return $this->belongsTo(Staff::class, 'teacher_id')->withDefault();
    }

    /**
     * @return BelongsTo
     */
    public function subject()
    {
        return $this->belongsTo(Subject::class, 'subject_id')->withDefault();
    }

    public static function getScheduledEvents($request)
    {

        $options          = array();
        $options["where"] = [];
        if ($request->has('class_id') && $request->class_id > 0) {
            $options["where"] += ["class_id" => $request->class_id];
        }
        if ($request->has('division_id') && $request->division_id > 0) {
            $options["where"] += ["section_id" => $request->division_id];
        }

        if (General::isSchoolTeacher()){
            $options["where"] += ["teacher_id" => Auth::user()->staff->id];
        }

        if (General::isSchoolStudent()){
            $options["where"] += ["class_id" => Auth::user()->student->class_id];
            $options["where"] += ["section_id" => Auth::user()->student->section_id];
        }

        $timetable = new Timetable();
        $results   = $timetable->find($options);

        $arr = [];
        foreach ($results as $key => $result) {

            $arr[$key]['id']          = $result->id;
            $arr[$key]['title']       = view('timetable::eventTitle', compact('result'))->render();
            $arr[$key]['description'] = 'Description';
            $arr[$key]['start']       = $result->start_time;
            $arr[$key]['end']         = $result->end_time;
            $arr[$key]['teacher_id']  = $result->teacher_id;
            $arr[$key]['dow']         = '"' . self::getDowByWeekDay(trim($result->week_day)) . '"';

        }


        return $arr;
    }

    /**
     * Return the day of week by week day name
     *
     * @param $weekDay
     * @return false|int|string
     */
    public static function getDowByWeekDay($weekDay)
    {

        $weekDays = Config::get('school.WeekDaysWithDow');
        return array_search($weekDay, $weekDays);
    }

    /**
     * Return the day name of week by day of week
     *
     * @param $dow
     * @return mixed
     */
    public static function getWeekDayByDow($dow)
    {

        $weekDays = Config::get('school.WeekDaysWithDow');
        $dow      = str_replace('"', '', $dow);

        return $weekDays[$dow];
    }

    /**
     * Add / Update the timetable into the resource
     *
     * @param $request
     * @param int $timetable
     * @return Timetable|Builder|Model|int|object|null
     */
    public static function addUpdateTimetable($request, $timetable = 0)
    {
        $timetable = (new Timetable())->findById($timetable);
        $insert    = false;

        if ($timetable == null) {
            $timetable = new Timetable();
            $insert    = true;
        }

        $timetable->fill($request->all());
        if ($insert == true) {
            $timetable->created_by = Auth::user()->id;
        } else {
            $timetable->updated_by = Auth::user()->id;
        }
        if (isset($request->is_online)) {
            $timetable->is_online = ($timetable->is_online == 'on' ? 1 : 0);
        }
        if (isset($request->dow)) {
            $timetable->week_day = self::getWeekDayByDow($request->dow);
        }

        $timetable->account_id = Config::get('account.id');
        $timetable->save();

        return $timetable;
    }

    /**
     * Return the availability of teacher class
     *
     * @param $request
     * @return JsonResponse
     * @throws Exception
     */
    public static function getDatatableTeacherAvailability($request)
    {

        $options            = array();
        $options['object']  = true;
        $options['orderBy'] = "start_time";
        $options['where']   = ['teacher_id' => $request->teacher_id, 'week_day' => $request->week_day];

        $timetable = new Timetable();
        $model     = $timetable->find($options);
        return DataTables::eloquent($model)
            ->addColumn('class', function (Timetable $timetable) {
                return $timetable->studentClass->title . ' - ' . $timetable->section->title;
            })
            ->addColumn('time', function ($timetable) {

                return (Carbon::parse($timetable->start_time))->format('H:i a') . ' - ' .
                    (Carbon::parse($timetable->end_time))->format('H:i a');
            })
            ->rawColumns(['class'])
            ->setRowClass(function ($timetable) {
                return $timetable->is_online == 1 ? 'is-online' : '';
            })
            ->make(true);
    }

    public static function validateTeacherAvailability($request, $timetableId=0)
    {
        if (isset($request->dow)){
            $request->week_day = self::getWeekDayByDow($request->dow);
        }

        $options           = array();
        $options['object'] = true;
        $options['where']  = ['teacher_id' => $request->teacher_id, 'week_day' => $request->week_day];
        if ($timetableId > 0){
            $options['whereNotIn']  = ['id' => [$timetableId]];
        }

        $timetable     = new Timetable();
        $checkSchedule = $timetable->find($options)
            ->where(function ($query) use ($request) {
                $query->whereBetween('start_time', [$request->start_time, $request->end_time]);
                $query->orWhereBetween('end_time', [$request->start_time, $request->end_time]);
            })
            ->get()->count();

        if ($checkSchedule > 0) {
            return false;
        } else {
            return true;
        }

    }

}
