<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\JadwalPelajaran;
use App\Models\Kelas;
use App\Models\MataPelajaran;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Illuminate\View\View;

class JadwalController extends Controller
{
    public function index(): View
    {
        $guru = User::query()
            ->with('guruProfile')
            ->withCount('jadwalMengajar')
            ->where('role', 'guru')
            ->orderBy('name')
            ->paginate(10);

        return view('admin.jadwal', [
            'pageMode' => 'teacher-list',
            'guru' => $guru,
        ]);
    }

    public function guru(User $guru): View
    {
        return $this->guruScheduleView($guru);
    }

    public function create(Request $request): RedirectResponse|View
    {
        $guruId = $request->query('guru_id');
        $guru = $guruId ? User::where('role', 'guru')->find($guruId) : null;

        if (! $guru) {
            return redirect()
                ->route('admin.jadwal.index')
                ->withErrors(['guru' => 'Pilih guru terlebih dahulu sebelum menambah jadwal.']);
        }

        return $this->createForGuru($guru);
    }

    public function createForGuru(User $guru): View
    {
        return $this->guruScheduleView($guru)->with([
            'showModal' => true,
            'formMode' => 'create',
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $this->validateJadwal($request);

        JadwalPelajaran::create($validated);

        return redirect()
            ->route('admin.jadwal.guru', $validated['guru_id'])
            ->with('success', 'Jadwal berhasil ditambahkan.');
    }

    public function edit(Request $request, JadwalPelajaran $jadwal): View
    {
        $guru = $jadwal->guru;
        abort_unless($guru instanceof User, 404);

        return $this->editForGuru($guru, $jadwal);
    }

    public function editForGuru(User $guru, JadwalPelajaran $jadwal): View
    {
        $this->ensureGuru($guru);
        abort_unless((int) $jadwal->guru_id === (int) $guru->id, 404);

        return $this->guruScheduleView($guru)->with([
            'showModal' => true,
            'formMode' => 'edit',
            'selectedJadwal' => $jadwal,
        ]);
    }

    public function update(Request $request, JadwalPelajaran $jadwal): RedirectResponse
    {
        $validated = $this->validateJadwal($request, $jadwal);

        $jadwal->update($validated);

        return redirect()
            ->route('admin.jadwal.guru', $jadwal->guru_id)
            ->with('success', 'Jadwal berhasil diperbarui.');
    }

    public function destroy(JadwalPelajaran $jadwal): RedirectResponse
    {
        $guruId = $jadwal->guru_id;
        $jadwal->delete();

        return redirect()
            ->route('admin.jadwal.guru', $guruId)
            ->with('success', 'Jadwal berhasil dihapus.');
    }

    private function guruScheduleView(User $guru): View
    {
        $this->ensureGuru($guru);

        $jadwal = JadwalPelajaran::query()
            ->with(['mataPelajaran', 'guru.guruProfile'])
            ->where('guru_id', $guru->id)
            ->orderByRaw("FIELD(hari, 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu')")
            ->orderBy('jam_mulai')
            ->paginate(10);

        return view('admin.jadwal', [
            'pageMode' => 'teacher-schedule',
            'jadwal' => $jadwal,
            'kelas' => Kelas::orderBy('nama_kelas')->get(),
            'mataPelajaran' => MataPelajaran::orderBy('nama_mapel')->get(),
            'selectedGuru' => $guru->load('guruProfile'),
            'formMode' => 'create',
            'selectedJadwal' => null,
        ]);
    }

    private function ensureGuru(User $guru): void
    {
        abort_unless($guru->role === 'guru', 404);
    }

    private function validateJadwal(Request $request, ?JadwalPelajaran $jadwal = null): array
    {
        if ($jadwal) {
            $request->merge(['guru_id' => $jadwal->guru_id]);
        }

        $validated = $request->validate([
            'mata_pelajaran_id' => ['required', 'exists:mata_pelajaran,id'],
            'guru_id' => [
                'required',
                Rule::exists('users', 'id')->where('role', 'guru'),
            ],
            'hari' => [
                'required',
                Rule::in(['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu']),
            ],
            'jam_mulai' => ['required', 'date_format:H:i'],
            'jam_selesai' => ['required', 'date_format:H:i', 'after:jam_mulai'],
            'kelas' => ['required', 'string', 'max:50', 'exists:kelas,nama_kelas'],
        ]);

        $duplicateExists = JadwalPelajaran::query()
            ->where('guru_id', $validated['guru_id'])
            ->where('kelas', $validated['kelas'])
            ->where('mata_pelajaran_id', $validated['mata_pelajaran_id'])
            ->where('hari', $validated['hari'])
            ->where('jam_mulai', $validated['jam_mulai'])
            ->where('jam_selesai', $validated['jam_selesai'])
            ->when($jadwal, fn ($query) => $query->whereKeyNot($jadwal->id))
            ->exists();

        if ($duplicateExists) {
            throw ValidationException::withMessages([
                'jam_mulai' => 'Jadwal identik untuk guru, kelas, mata pelajaran, hari, dan jam tersebut sudah ada.',
            ]);
        }

        return $validated;
    }
}
