<?php

declare(strict_types=1);

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

use App\Administration\Application\Query\GetParentsForStudent\GetParentsForStudentHandler;
use App\Administration\Application\Query\GetParentsForStudent\GetParentsForStudentQuery;
use App\Administration\Application\Query\GetParentsForStudent\GuardianForStudentDto;
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 GetParentsForStudentHandlerTest extends TestCase
{
    private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';
    private const string STUDENT_ID = '550e8400-e29b-41d4-a716-446655440002';
    private const string GUARDIAN_1_ID = '550e8400-e29b-41d4-a716-446655440003';
    private const string GUARDIAN_2_ID = '550e8400-e29b-41d4-a716-446655440004';

    private InMemoryStudentGuardianRepository $repository;
    private GetParentsForStudentHandler $handler;
    private User $guardianUser;

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

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

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

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

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

    #[Test]
    public function returnsEmptyWhenNoParentsLinked(): void
    {
        $result = ($this->handler)(new GetParentsForStudentQuery(
            studentId: self::STUDENT_ID,
            tenantId: self::TENANT_ID,
        ));

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

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

        $result = ($this->handler)(new GetParentsForStudentQuery(
            studentId: self::STUDENT_ID,
            tenantId: self::TENANT_ID,
        ));

        self::assertCount(2, $result);
        self::assertContainsOnlyInstancesOf(GuardianForStudentDto::class, $result);
    }

    #[Test]
    public function dtoContainsCorrectData(): void
    {
        $createdAt = new DateTimeImmutable('2026-02-10 10:00:00');
        $this->repository->save(StudentGuardian::lier(
            studentId: UserId::fromString(self::STUDENT_ID),
            guardianId: UserId::fromString(self::GUARDIAN_1_ID),
            relationshipType: RelationshipType::TUTOR_F,
            tenantId: TenantId::fromString(self::TENANT_ID),
            createdAt: $createdAt,
        ));

        $result = ($this->handler)(new GetParentsForStudentQuery(
            studentId: self::STUDENT_ID,
            tenantId: self::TENANT_ID,
        ));

        self::assertSame(self::GUARDIAN_1_ID, $result[0]->guardianId);
        self::assertSame(RelationshipType::TUTOR_F->value, $result[0]->relationshipType);
        self::assertSame('Tutrice', $result[0]->relationshipLabel);
        self::assertEquals($createdAt, $result[0]->linkedAt);
        self::assertSame($this->guardianUser->firstName, $result[0]->firstName);
        self::assertSame($this->guardianUser->lastName, $result[0]->lastName);
        self::assertSame((string) $this->guardianUser->email, $result[0]->email);
    }
}
