<?php

declare(strict_types=1);

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

use App\Administration\Application\Query\GetStudentsForParent\GetStudentsForParentHandler;
use App\Administration\Application\Query\GetStudentsForParent\GetStudentsForParentQuery;
use App\Administration\Application\Query\GetStudentsForParent\StudentForParentDto;
use App\Administration\Domain\Model\StudentGuardian\RelationshipType;
use App\Administration\Domain\Model\StudentGuardian\StudentGuardian;
use App\Administration\Domain\Model\User\Email;
use App\Administration\Domain\Model\User\Role;
use App\Administration\Domain\Model\User\User;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Domain\Repository\UserRepository;
use App\Administration\Infrastructure\Persistence\InMemory\InMemoryStudentGuardianRepository;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class GetStudentsForParentHandlerTest extends TestCase
{
    private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
    private const string STUDENT_1_ID = '550e8400-e29b-41d4-a716-446655440002';
    private const string STUDENT_2_ID = '550e8400-e29b-41d4-a716-446655440003';
    private const string GUARDIAN_ID = '550e8400-e29b-41d4-a716-446655440004';

    private InMemoryStudentGuardianRepository $repository;
    private GetStudentsForParentHandler $handler;
    private User $studentUser;

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

        $tenantId = TenantId::fromString(self::TENANT_ID);
        $now = new DateTimeImmutable('2026-02-10 10:00:00');

        $this->studentUser = User::creer(
            email: new Email('student@example.com'),
            role: Role::ELEVE,
            tenantId: $tenantId,
            schoolName: 'École Test',
            dateNaissance: null,
            createdAt: $now,
        );

        $userRepository = $this->createMock(UserRepository::class);
        $userRepository->method('get')->willReturn($this->studentUser);

        $this->handler = new GetStudentsForParentHandler($this->repository, $userRepository);
    }

    #[Test]
    public function returnsEmptyWhenNoStudentsLinked(): void
    {
        $result = ($this->handler)(new GetStudentsForParentQuery(
            guardianId: self::GUARDIAN_ID,
            tenantId: self::TENANT_ID,
        ));

        self::assertSame([], $result);
    }

    #[Test]
    public function returnsStudentsForParent(): void
    {
        $this->repository->save(StudentGuardian::lier(
            studentId: UserId::fromString(self::STUDENT_1_ID),
            guardianId: UserId::fromString(self::GUARDIAN_ID),
            relationshipType: RelationshipType::FATHER,
            tenantId: TenantId::fromString(self::TENANT_ID),
            createdAt: new DateTimeImmutable(),
        ));
        $this->repository->save(StudentGuardian::lier(
            studentId: UserId::fromString(self::STUDENT_2_ID),
            guardianId: UserId::fromString(self::GUARDIAN_ID),
            relationshipType: RelationshipType::FATHER,
            tenantId: TenantId::fromString(self::TENANT_ID),
            createdAt: new DateTimeImmutable(),
        ));

        $result = ($this->handler)(new GetStudentsForParentQuery(
            guardianId: self::GUARDIAN_ID,
            tenantId: self::TENANT_ID,
        ));

        self::assertCount(2, $result);
        self::assertContainsOnlyInstancesOf(StudentForParentDto::class, $result);
        self::assertSame(self::STUDENT_1_ID, $result[0]->studentId);
        self::assertSame(self::STUDENT_2_ID, $result[1]->studentId);
    }

    #[Test]
    public function dtoContainsCorrectData(): void
    {
        $this->repository->save(StudentGuardian::lier(
            studentId: UserId::fromString(self::STUDENT_1_ID),
            guardianId: UserId::fromString(self::GUARDIAN_ID),
            relationshipType: RelationshipType::MOTHER,
            tenantId: TenantId::fromString(self::TENANT_ID),
            createdAt: new DateTimeImmutable(),
        ));

        $result = ($this->handler)(new GetStudentsForParentQuery(
            guardianId: self::GUARDIAN_ID,
            tenantId: self::TENANT_ID,
        ));

        self::assertSame(RelationshipType::MOTHER->value, $result[0]->relationshipType);
        self::assertSame('Mère', $result[0]->relationshipLabel);
        self::assertSame($this->studentUser->firstName, $result[0]->firstName);
        self::assertSame($this->studentUser->lastName, $result[0]->lastName);
    }
}
