<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Application\Query\HasStudentsInClass;

use App\Administration\Application\Query\HasStudentsInClass\HasStudentsInClassHandler;
use App\Administration\Application\Query\HasStudentsInClass\HasStudentsInClassQuery;
use App\Administration\Domain\Model\ClassAssignment\ClassAssignment;
use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryClassAssignmentRepository;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class HasStudentsInClassHandlerTest extends TestCase
{
    private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
    private const string CLASS_ID = '550e8400-e29b-41d4-a716-446655440020';
    private const string ACADEMIC_YEAR_ID = '550e8400-e29b-41d4-a716-446655440040';

    private InMemoryClassAssignmentRepository $repository;

    protected function setUp(): void
    {
        $this->repository = new InMemoryClassAssignmentRepository();
    }

    #[Test]
    public function returnsZeroWhenNoStudentsAssigned(): void
    {
        $handler = new HasStudentsInClassHandler($this->repository);

        $query = new HasStudentsInClassQuery(
            classId: self::CLASS_ID,
        );

        $result = ($handler)($query);

        self::assertSame(0, $result);
    }

    #[Test]
    public function returnsCountOfAssignedStudents(): void
    {
        $this->addAssignment('550e8400-e29b-41d4-a716-446655440010');
        $this->addAssignment('550e8400-e29b-41d4-a716-446655440011');

        $handler = new HasStudentsInClassHandler($this->repository);

        $result = ($handler)(new HasStudentsInClassQuery(classId: self::CLASS_ID));

        self::assertSame(2, $result);
    }

    #[Test]
    public function isConsistentAcrossMultipleCalls(): void
    {
        $this->addAssignment('550e8400-e29b-41d4-a716-446655440010');

        $handler = new HasStudentsInClassHandler($this->repository);

        $result1 = ($handler)(new HasStudentsInClassQuery(classId: self::CLASS_ID));
        $result2 = ($handler)(new HasStudentsInClassQuery(classId: self::CLASS_ID));

        self::assertSame($result1, $result2);
        self::assertSame(1, $result1);
    }

    private function addAssignment(string $studentId): void
    {
        $assignment = ClassAssignment::affecter(
            tenantId: TenantId::fromString(self::TENANT_ID),
            studentId: UserId::fromString($studentId),
            classId: ClassId::fromString(self::CLASS_ID),
            academicYearId: AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            assignedAt: new DateTimeImmutable('2026-02-21 10:00:00'),
        );
        $this->repository->save($assignment);
    }
}
