<?php

declare(strict_types=1);

namespace App\Tests\Unit\Scolarite\Domain\Model\Homework;

use App\Scolarite\Domain\Exception\PieceJointeInvalideException;
use App\Scolarite\Domain\Model\Homework\HomeworkAttachment;
use App\Scolarite\Domain\Model\Homework\HomeworkAttachmentId;
use DateTimeImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class HomeworkAttachmentTest extends TestCase
{
    #[Test]
    public function createsValidAttachment(): void
    {
        $id = HomeworkAttachmentId::generate();
        $uploadedAt = new DateTimeImmutable('2026-03-12 10:00:00');

        $attachment = new HomeworkAttachment(
            id: $id,
            filename: 'exercices.pdf',
            filePath: 'homework/abc123/exercices.pdf',
            fileSize: 500_000,
            mimeType: 'application/pdf',
            uploadedAt: $uploadedAt,
        );

        self::assertTrue($attachment->id->equals($id));
        self::assertSame('exercices.pdf', $attachment->filename);
        self::assertSame('homework/abc123/exercices.pdf', $attachment->filePath);
        self::assertSame(500_000, $attachment->fileSize);
        self::assertSame('application/pdf', $attachment->mimeType);
        self::assertEquals($uploadedAt, $attachment->uploadedAt);
    }

    #[Test]
    public function acceptsJpegMimeType(): void
    {
        $attachment = $this->createAttachmentWithMimeType('image/jpeg');

        self::assertSame('image/jpeg', $attachment->mimeType);
    }

    #[Test]
    public function acceptsPngMimeType(): void
    {
        $attachment = $this->createAttachmentWithMimeType('image/png');

        self::assertSame('image/png', $attachment->mimeType);
    }

    #[Test]
    public function rejectsInvalidMimeType(): void
    {
        $this->expectException(PieceJointeInvalideException::class);
        $this->expectExceptionMessageMatches('/text\/plain/');

        $this->createAttachmentWithMimeType('text/plain');
    }

    #[Test]
    public function rejectsFileTooLarge(): void
    {
        $this->expectException(PieceJointeInvalideException::class);
        $this->expectExceptionMessageMatches('/taille maximum/');

        new HomeworkAttachment(
            id: HomeworkAttachmentId::generate(),
            filename: 'big.pdf',
            filePath: 'homework/abc/big.pdf',
            fileSize: 11 * 1024 * 1024, // 11 Mo
            mimeType: 'application/pdf',
            uploadedAt: new DateTimeImmutable(),
        );
    }

    #[Test]
    public function acceptsExactMaxSize(): void
    {
        $attachment = new HomeworkAttachment(
            id: HomeworkAttachmentId::generate(),
            filename: 'max.pdf',
            filePath: 'homework/abc/max.pdf',
            fileSize: 10 * 1024 * 1024, // Exactement 10 Mo
            mimeType: 'application/pdf',
            uploadedAt: new DateTimeImmutable(),
        );

        self::assertSame(10 * 1024 * 1024, $attachment->fileSize);
    }

    private function createAttachmentWithMimeType(string $mimeType): HomeworkAttachment
    {
        return new HomeworkAttachment(
            id: HomeworkAttachmentId::generate(),
            filename: 'test.file',
            filePath: 'homework/abc/test.file',
            fileSize: 1000,
            mimeType: $mimeType,
            uploadedAt: new DateTimeImmutable(),
        );
    }
}
