<?php

namespace App\GraphQL\Mutations;

use App\Models\Course;
use App\Models\Hall;
use App\Models\Instructor;
use App\Models\Lecture;
use App\Models\Semester;
use App\Models\Subject;

final class SetLecturesHallAndInstructor
{
    /**
     * @param null $_
     * @param array{}  $args
     * @throws \Exception
     */
    public function __invoke($_, array $args)
    {
        if (array_key_exists('hall_id', $args) && $args['hall_id']) {
            $hall = Hall::findOrFail($args['hall_id']);
        }
        if (array_key_exists('instructor_id', $args) && $args['instructor_id']) {
            $instructor = Instructor::findOrFail($args['instructor_id']);
        }
        if (@$args['subject_id']) {
            $subject = Subject::findOrFail(@$args['subject_id']);
        }

        $start_week = @$args['start_week'];
        $end_week = @$args['end_week'];

        $start_time = @$args['start_time'];
        $end_time = @$args['end_time'];
        $day = @$args['day'];

        foreach (idsToModels(@$args['lectures'], Lecture::class)->get() as $lecture) {

            $old_lecture = $lecture;

            $start_week = $start_week ?? ($lecture->start_week ?? 1);
            $end_week = $end_week ?? ($lecture->end_week ?? 22);


            if (isset($subject) && $subject !== null) {
                $old_course = $lecture->course;
                $group = $old_course->group;
                $new_course = Course::where('group_id', $group->id)->where('subject_id', $subject->id)->get()->first();

                if (!$new_course) {
                    $new_course = Course::create([
                        'group_id' => $group->id,
                        'subject_id' => $subject->id,
                        'hours' => $subject->hours,
                        'start_semester' => Semester::active()->id,
                    ]);
                }

                $new_lecture = Lecture::create([
                    'course_id' => $new_course->id,
                    'hall_id' => $hall->id ?? $lecture->hall_id,
                    'instructor_id' => $instructor->id ?? $lecture->instructor_id,
                    'start_time' => $start_time ?? $lecture->start_time,
                    'end_time' => $end_time ?? $lecture->end_time,
                    'semester_id' => Semester::active()->id,
                    'day' => $day ?? $lecture->day,
                    'start_week' => $start_week,
                    'end_week' => $end_week,
                ]);
            } else if (($start_time !== null && $end_time !== null) || $day !== null) {
                if ($old_lecture) {
                    $old_lecture->update([
                        'start_time' => $lecture->start_time,
                        'end_time' => $lecture->end_time,
                        'day' => $lecture->day,
                    ]);
                }

                $lecture->update([
                    'hall_id' => $hall->id ?? $lecture->hall_id,
                    'instructor_id' => $instructor->id ?? $lecture->instructor_id,
                    'start_time' => $start_time ?? $lecture->start_time,
                    'end_time' => $end_time ?? $lecture->end_time,
                    'day' => $day ?? $lecture->day,
                    'start_week' => $start_week ?? $lecture->start_week,
                    'end_week' => $end_week ?? $lecture->end_week,
                ]);
            } else {
                $lecture->update([
                    'hall_id' => $hall->id ?? $lecture->hall_id,
                    'instructor_id' => $instructor->id ?? $lecture->instructor_id,
                ]);
            }
        }
        return true;
    }

    public function removeConflicts($lecture)
    {
        $course = Course::find($lecture->course_id);
        $group = $course->group_id;

        $courses = Course::where('group_id', $group)->pluck('id');
        $lectures = Lecture::whereIn('course_id', $courses)
            ->where('day', $lecture->day)
            ->where('start_time', '<=', $lecture->start_time)
            ->where('end_time', '>=', $lecture->end_time)
            ->where(function ($query) use ($lecture) {
                $query->where(
                    function ($query) use ($lecture) {

                        $query->where('start_week', '>=', $lecture->end_week)
                            ->where('start_week', '<=', $lecture->start_week);
                    }
                )->orWhere(
                    function ($query) use ($lecture) {
                        $query->where('end_week', '>=', $lecture->end_week)
                            ->where('end_week', '<=', $lecture->start_week);
                    }
                );
            })
            ->where('id', '!=', $lecture->id)
            ->get();

        foreach ($lectures as $old_lecture) {
            if ($old_lecture->start_week <= $lecture->start_week && $old_lecture->end_week >= $lecture->start_week) {
                $old_lecture->start_week = $lecture->end_week + 1;
                $old_lecture->save();
            }
            if ($old_lecture->start_week <= $lecture->end_week && $old_lecture->end_week >= $lecture->end_week) {
                $old_lecture->end_week = $lecture->start_week - 1;
                $old_lecture->save();
            }
        }
    }
}
