<?php

declare(strict_types=1);

namespace App\Tests\Unit\Administration\Domain\Model\User;

use App\Administration\Domain\Event\DroitImageModifie;
use App\Administration\Domain\Model\User\Email;
use App\Administration\Domain\Model\User\ImageRightsStatus;
use App\Administration\Domain\Model\User\Role;
use App\Administration\Domain\Model\User\User;
use App\Administration\Domain\Model\User\UserId;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class UserImageRightsTest extends TestCase
{
    private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440002';
    private const string SCHOOL_NAME = 'École Alpha';
    private const string MODIFIER_ID = '550e8400-e29b-41d4-a716-446655440099';

    #[Test]
    public function newUserHasNotSpecifiedImageRights(): void
    {
        $user = $this->createStudent();

        self::assertSame(ImageRightsStatus::NOT_SPECIFIED, $user->imageRightsStatus);
        self::assertNull($user->imageRightsUpdatedAt);
        self::assertNull($user->imageRightsUpdatedBy);
    }

    #[Test]
    public function modifierDroitImageSetsAuthorized(): void
    {
        $user = $this->createStudent();
        $at = new DateTimeImmutable('2026-02-18 10:00:00');
        $modifierId = UserId::fromString(self::MODIFIER_ID);

        $user->modifierDroitImage(ImageRightsStatus::AUTHORIZED, $modifierId, $at);

        self::assertSame(ImageRightsStatus::AUTHORIZED, $user->imageRightsStatus);
        self::assertEquals($at, $user->imageRightsUpdatedAt);
        self::assertTrue($user->imageRightsUpdatedBy->equals($modifierId));
    }

    #[Test]
    public function modifierDroitImageSetsRefused(): void
    {
        $user = $this->createStudent();
        $at = new DateTimeImmutable('2026-02-18 10:00:00');
        $modifierId = UserId::fromString(self::MODIFIER_ID);

        $user->modifierDroitImage(ImageRightsStatus::REFUSED, $modifierId, $at);

        self::assertSame(ImageRightsStatus::REFUSED, $user->imageRightsStatus);
    }

    #[Test]
    public function modifierDroitImageRecordsDroitImageModifieEvent(): void
    {
        $user = $this->createStudent();
        $user->pullDomainEvents();
        $at = new DateTimeImmutable('2026-02-18 10:00:00');
        $modifierId = UserId::fromString(self::MODIFIER_ID);

        $user->modifierDroitImage(ImageRightsStatus::AUTHORIZED, $modifierId, $at);

        $events = $user->pullDomainEvents();
        self::assertCount(1, $events);
        self::assertInstanceOf(DroitImageModifie::class, $events[0]);

        /** @var DroitImageModifie $event */
        $event = $events[0];
        self::assertTrue($user->id->equals($event->userId));
        self::assertSame(ImageRightsStatus::AUTHORIZED, $event->nouveauStatut);
        self::assertSame(ImageRightsStatus::NOT_SPECIFIED, $event->ancienStatut);
    }

    #[Test]
    public function modifierDroitImageTracksOldStatus(): void
    {
        $user = $this->createStudent();
        $modifierId = UserId::fromString(self::MODIFIER_ID);

        $user->modifierDroitImage(ImageRightsStatus::AUTHORIZED, $modifierId, new DateTimeImmutable());
        $user->pullDomainEvents();

        $user->modifierDroitImage(ImageRightsStatus::REFUSED, $modifierId, new DateTimeImmutable());

        $events = $user->pullDomainEvents();
        /** @var DroitImageModifie $event */
        $event = $events[0];
        self::assertSame(ImageRightsStatus::AUTHORIZED, $event->ancienStatut);
        self::assertSame(ImageRightsStatus::REFUSED, $event->nouveauStatut);
    }

    #[Test]
    public function reconstitutePreservesImageRightsData(): void
    {
        $at = new DateTimeImmutable('2026-02-18 10:00:00');
        $modifierId = UserId::fromString(self::MODIFIER_ID);

        $user = User::reconstitute(
            id: UserId::generate(),
            email: new Email('eleve@example.com'),
            roles: [Role::ELEVE],
            tenantId: TenantId::fromString(self::TENANT_ID),
            schoolName: self::SCHOOL_NAME,
            statut: \App\Administration\Domain\Model\User\StatutCompte::EN_ATTENTE,
            dateNaissance: null,
            createdAt: new DateTimeImmutable(),
            hashedPassword: null,
            activatedAt: null,
            consentementParental: null,
            imageRightsStatus: ImageRightsStatus::AUTHORIZED,
            imageRightsUpdatedAt: $at,
            imageRightsUpdatedBy: $modifierId,
        );

        self::assertSame(ImageRightsStatus::AUTHORIZED, $user->imageRightsStatus);
        self::assertEquals($at, $user->imageRightsUpdatedAt);
        self::assertTrue($user->imageRightsUpdatedBy->equals($modifierId));
    }

    private function createStudent(): User
    {
        return User::creer(
            email: new Email('eleve@example.com'),
            role: Role::ELEVE,
            tenantId: TenantId::fromString(self::TENANT_ID),
            schoolName: self::SCHOOL_NAME,
            dateNaissance: new DateTimeImmutable('2012-06-15'),
            createdAt: new DateTimeImmutable('2026-01-15 10:00:00'),
        );
    }
}
