<?php

namespace App\Http\Controllers\Admin\School;

use App\Http\Controllers\Admin\PageController;
use App\Models\DisciplinaryRecord;
use App\Models\SchoolClass;
use App\Models\Student;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class DisciplineController extends PageController
{
    public function index(): RedirectResponse
    {
        return redirect()->route('school.cases.index');
    }

    public function indexLegacy(): View
    {
        $records = $this->scopedQuery()
            ->with(['student', 'recordedBy'])
            ->latest('incident_date')
            ->paginate(20);

        return $this->page('admin.discipline.index', [
            'crumbTitle' => 'Disciplinary',
            'crumbSub' => 'Incidents & warnings',
            'records' => $records,
        ]);
    }

    public function create(): View
    {
        return $this->page('admin.discipline.create', [
            'crumbTitle' => 'Disciplinary',
            'crumbSub' => 'Log incident',
            'students' => $this->visibleStudents(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $this->validateRecord($request);
        $validated['recorded_by'] = auth()->user()?->staff_id;

        DisciplinaryRecord::query()->create($validated);

        return $this->redirectWithSuccess('school.discipline.index', 'Incident recorded.');
    }

    public function edit(DisciplinaryRecord $record): View
    {
        $this->authorizeRecord($record);

        return $this->page('admin.discipline.edit', [
            'crumbTitle' => 'Disciplinary',
            'crumbSub' => 'Edit incident',
            'record' => $record,
            'students' => $this->visibleStudents(),
        ]);
    }

    public function update(Request $request, DisciplinaryRecord $record): RedirectResponse
    {
        $this->authorizeRecord($record);

        $record->update($this->validateRecord($request));

        return $this->redirectWithSuccess('school.discipline.index', 'Incident updated.');
    }

    public function destroy(DisciplinaryRecord $record): RedirectResponse
    {
        $this->authorizeRecord($record);

        $record->delete();

        return $this->redirectWithSuccess('school.discipline.index', 'Incident removed.');
    }

    private function scopedQuery()
    {
        $query = DisciplinaryRecord::query();

        if ($this->isTeacherOnly()) {
            $staffId = auth()->user()?->staff_id;
            $classIds = SchoolClass::query()
                ->where('class_teacher_id', $staffId)
                ->pluck('id');

            $studentIds = Student::query()
                ->whereHas('classes', fn ($q) => $q->whereIn('classes.id', $classIds))
                ->pluck('id');

            $query->where(function ($builder) use ($staffId, $studentIds) {
                $builder->where('recorded_by', $staffId)
                    ->orWhereIn('student_id', $studentIds);
            });
        }

        return $query;
    }

    private function visibleStudents()
    {
        $query = Student::query()->where('status', 'active')->orderBy('last_name');

        if ($this->isTeacherOnly()) {
            $staffId = auth()->user()?->staff_id;
            $classIds = SchoolClass::query()
                ->where('class_teacher_id', $staffId)
                ->pluck('id');

            $query->whereHas('classes', fn ($q) => $q->whereIn('classes.id', $classIds));
        }

        return $query->get();
    }

    private function isTeacherOnly(): bool
    {
        $user = auth()->user();

        if ($user === null) {
            return false;
        }

        return $user->hasRole('Teacher')
            && ! $user->hasAnyRole(['Super Admin', 'Administrator', 'Registrar']);
    }

    private function authorizeRecord(DisciplinaryRecord $record): void
    {
        if (! $this->isTeacherOnly()) {
            return;
        }

        $visible = $this->scopedQuery()->whereKey($record->id)->exists();

        abort_unless($visible, 403);
    }

    /**
     * @return array<string, mixed>
     */
    private function validateRecord(Request $request): array
    {
        return $request->validate([
            'student_id' => ['required', 'exists:students,id'],
            'incident_date' => ['required', 'date'],
            'category' => ['nullable', 'string', 'max:100'],
            'description' => ['required', 'string'],
            'action_taken' => ['nullable', 'string', 'max:255'],
            'status' => ['nullable', 'string', 'max:30'],
        ]);
    }
}
