<?php

declare(strict_types=1);

namespace App\Tests\Unit\Scolarite\Application\Command\DeleteHomework;

use App\Administration\Domain\Model\SchoolClass\ClassId;
use App\Administration\Domain\Model\Subject\SubjectId;
use App\Administration\Domain\Model\User\UserId;
use App\Scolarite\Application\Command\DeleteHomework\DeleteHomeworkCommand;
use App\Scolarite\Application\Command\DeleteHomework\DeleteHomeworkHandler;
use App\Scolarite\Domain\Exception\DevoirDejaSupprimeException;
use App\Scolarite\Domain\Exception\HomeworkNotFoundException;
use App\Scolarite\Domain\Exception\NonProprietaireDuDevoirException;
use App\Scolarite\Domain\Model\Homework\Homework;
use App\Scolarite\Domain\Model\Homework\HomeworkId;
use App\Scolarite\Domain\Model\Homework\HomeworkStatus;
use App\Scolarite\Infrastructure\Persistence\InMemory\InMemoryHomeworkRepository;
use App\Shared\Domain\Clock;
use App\Shared\Domain\Tenant\TenantId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class DeleteHomeworkHandlerTest extends TestCase
{
    private const string TENANT_ID = '550e8400-e29b-41d4-a716-446655440001';

    private InMemoryHomeworkRepository $homeworkRepository;
    private Clock $clock;
    private HomeworkId $existingHomeworkId;

    protected function setUp(): void
    {
        $this->homeworkRepository = new InMemoryHomeworkRepository();
        $this->clock = new class implements Clock {
            public function now(): DateTimeImmutable
            {
                return new DateTimeImmutable('2026-03-12 10:00:00');
            }
        };

        $this->seedHomework();
    }

    #[Test]
    public function itDeletesHomeworkSuccessfully(): void
    {
        $handler = $this->createHandler();

        $homework = $handler(new DeleteHomeworkCommand(
            tenantId: self::TENANT_ID,
            homeworkId: (string) $this->existingHomeworkId,
            teacherId: '550e8400-e29b-41d4-a716-446655440010',
        ));

        self::assertSame(HomeworkStatus::DELETED, $homework->status);
    }

    #[Test]
    public function itThrowsWhenHomeworkNotFound(): void
    {
        $handler = $this->createHandler();

        $this->expectException(HomeworkNotFoundException::class);

        $handler(new DeleteHomeworkCommand(
            tenantId: self::TENANT_ID,
            homeworkId: (string) HomeworkId::generate(),
            teacherId: '550e8400-e29b-41d4-a716-446655440010',
        ));
    }

    #[Test]
    public function itThrowsWhenHomeworkAlreadyDeleted(): void
    {
        $homework = $this->homeworkRepository->get($this->existingHomeworkId, TenantId::fromString(self::TENANT_ID));
        $homework->supprimer(new DateTimeImmutable('2026-03-12'));
        $this->homeworkRepository->save($homework);

        $handler = $this->createHandler();

        $this->expectException(DevoirDejaSupprimeException::class);

        $handler(new DeleteHomeworkCommand(
            tenantId: self::TENANT_ID,
            homeworkId: (string) $this->existingHomeworkId,
            teacherId: '550e8400-e29b-41d4-a716-446655440010',
        ));
    }

    #[Test]
    public function itThrowsWhenNotOwner(): void
    {
        $handler = $this->createHandler();

        $this->expectException(NonProprietaireDuDevoirException::class);

        $handler(new DeleteHomeworkCommand(
            tenantId: self::TENANT_ID,
            homeworkId: (string) $this->existingHomeworkId,
            teacherId: '550e8400-e29b-41d4-a716-446655440099',
        ));
    }

    private function seedHomework(): void
    {
        $homework = Homework::creer(
            tenantId: TenantId::fromString(self::TENANT_ID),
            classId: ClassId::fromString('550e8400-e29b-41d4-a716-446655440020'),
            subjectId: SubjectId::fromString('550e8400-e29b-41d4-a716-446655440030'),
            teacherId: UserId::fromString('550e8400-e29b-41d4-a716-446655440010'),
            title: 'Exercices',
            description: 'Description',
            dueDate: new DateTimeImmutable('2026-04-15'),
            now: new DateTimeImmutable('2026-03-10 10:00:00'),
        );

        $this->existingHomeworkId = $homework->id;
        $this->homeworkRepository->save($homework);
    }

    private function createHandler(): DeleteHomeworkHandler
    {
        return new DeleteHomeworkHandler(
            $this->homeworkRepository,
            $this->clock,
        );
    }
}
