<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Infrastructure\Service;

use App\Administration\Domain\Model\SchoolClass\AcademicYearId;
use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\Subject\SubjectId;
use App\Administration\Domain\Model\TeacherAssignment\TeacherAssignment;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryTeacherAssignmentRepository;
use App\Administration\Infrastructure\Service\RepositoryTeacherAssignmentChecker;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

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

    private InMemoryTeacherAssignmentRepository $repository;
    private RepositoryTeacherAssignmentChecker $checker;

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

    #[Test]
    public function estAffecteReturnsTrueWhenActiveAssignmentExists(): void
    {
        $this->createAndSaveAssignment();

        self::assertTrue($this->checker->estAffecte(
            UserId::fromString(self::TEACHER_ID),
            ClassId::fromString(self::CLASS_ID),
            SubjectId::fromString(self::SUBJECT_ID),
            AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            TenantId::fromString(self::TENANT_ID),
        ));
    }

    #[Test]
    public function estAffecteReturnsFalseWhenNoAssignment(): void
    {
        self::assertFalse($this->checker->estAffecte(
            UserId::fromString(self::TEACHER_ID),
            ClassId::fromString(self::CLASS_ID),
            SubjectId::fromString(self::SUBJECT_ID),
            AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            TenantId::fromString(self::TENANT_ID),
        ));
    }

    #[Test]
    public function estAffecteReturnsFalseWhenAssignmentRemoved(): void
    {
        $assignment = $this->createAndSaveAssignment();
        $assignment->retirer(new DateTimeImmutable('2026-03-01 10:00:00'));
        $this->repository->save($assignment);

        self::assertFalse($this->checker->estAffecte(
            UserId::fromString(self::TEACHER_ID),
            ClassId::fromString(self::CLASS_ID),
            SubjectId::fromString(self::SUBJECT_ID),
            AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            TenantId::fromString(self::TENANT_ID),
        ));
    }

    #[Test]
    public function estAffecteReturnsFalseForDifferentSubject(): void
    {
        $this->createAndSaveAssignment();

        self::assertFalse($this->checker->estAffecte(
            UserId::fromString(self::TEACHER_ID),
            ClassId::fromString(self::CLASS_ID),
            SubjectId::fromString('550e8400-e29b-41d4-a716-446655440099'),
            AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            TenantId::fromString(self::TENANT_ID),
        ));
    }

    private function createAndSaveAssignment(): TeacherAssignment
    {
        $assignment = TeacherAssignment::creer(
            tenantId: TenantId::fromString(self::TENANT_ID),
            teacherId: UserId::fromString(self::TEACHER_ID),
            classId: ClassId::fromString(self::CLASS_ID),
            subjectId: SubjectId::fromString(self::SUBJECT_ID),
            academicYearId: AcademicYearId::fromString(self::ACADEMIC_YEAR_ID),
            createdAt: new DateTimeImmutable('2026-02-12 10:00:00'),
        );

        $this->repository->save($assignment);

        return $assignment;
    }
}
