<?php

namespace App\Services\School;

use App\Models\Guardian;
use App\Models\Student;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;

class ParentScopeService
{
    public const SESSION_KEY = 'parent_active_student_id';

    public function guardian(?User $user = null): ?Guardian
    {
        $user ??= auth()->user();

        return $user?->guardian;
    }

    /**
     * @return Collection<int, Student>
     */
    public function linkedStudents(?User $user = null): Collection
    {
        $guardian = $this->guardian($user);

        if (! $guardian) {
            return collect();
        }

        return $guardian->students()
            ->with(['classes.academicYear', 'academicYear'])
            ->orderBy('first_name')
            ->get();
    }

    public function activeStudentId(?Request $request = null, ?User $user = null): ?int
    {
        $students = $this->linkedStudents($user);
        if ($students->isEmpty()) {
            return null;
        }

        $request ??= request();
        $requestedId = $request->integer('student_id');

        if ($requestedId && $students->contains('id', $requestedId)) {
            session([self::SESSION_KEY => $requestedId]);

            return $requestedId;
        }

        $sessionId = session(self::SESSION_KEY);
        if ($sessionId && $students->contains('id', (int) $sessionId)) {
            return (int) $sessionId;
        }

        $firstId = $students->first()->id;
        session([self::SESSION_KEY => $firstId]);

        return $firstId;
    }

    public function activeStudent(?Request $request = null, ?User $user = null): ?Student
    {
        $studentId = $this->activeStudentId($request, $user);

        return $studentId
            ? $this->linkedStudents($user)->firstWhere('id', $studentId)
            : null;
    }

    public function setActiveStudent(int $studentId, ?User $user = null): void
    {
        abort_unless(
            $this->linkedStudents($user)->contains('id', $studentId),
            403,
        );

        session([self::SESSION_KEY => $studentId]);
    }

    public function authorizeStudent(Student $student, ?User $user = null): void
    {
        abort_unless(
            $this->linkedStudents($user)->contains('id', $student->id),
            403,
        );
    }
}
