<?php

declare(strict_types=1);

namespace App\Scolarite\Infrastructure\Api\Resource;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Patch;
use ApiPlatform\Metadata\Post;
use App\Scolarite\Domain\Model\Evaluation\Evaluation;
use App\Scolarite\Infrastructure\Api\Processor\CreateEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Processor\DeleteEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Processor\UpdateEvaluationProcessor;
use App\Scolarite\Infrastructure\Api\Provider\EvaluationCollectionProvider;
use App\Scolarite\Infrastructure\Api\Provider\EvaluationItemProvider;
use DateTimeImmutable;
use Symfony\Component\Validator\Constraints as Assert;

#[ApiResource(
    shortName: 'Evaluation',
    operations: [
        new GetCollection(
            uriTemplate: '/evaluations',
            provider: EvaluationCollectionProvider::class,
            name: 'get_evaluation_list',
        ),
        new Get(
            uriTemplate: '/evaluations/{id}',
            provider: EvaluationItemProvider::class,
            name: 'get_evaluation',
        ),
        new Post(
            uriTemplate: '/evaluations',
            processor: CreateEvaluationProcessor::class,
            validationContext: ['groups' => ['Default', 'create']],
            name: 'create_evaluation',
        ),
        new Patch(
            uriTemplate: '/evaluations/{id}',
            provider: EvaluationItemProvider::class,
            processor: UpdateEvaluationProcessor::class,
            validationContext: ['groups' => ['Default', 'update']],
            name: 'update_evaluation',
        ),
        new Delete(
            uriTemplate: '/evaluations/{id}',
            provider: EvaluationItemProvider::class,
            processor: DeleteEvaluationProcessor::class,
            name: 'delete_evaluation',
        ),
    ],
)]
final class EvaluationResource
{
    #[ApiProperty(identifier: true)]
    public ?string $id = null;

    #[Assert\NotBlank(message: 'La classe est requise.', groups: ['create'])]
    #[Assert\Uuid(message: 'L\'identifiant de la classe doit être un UUID valide.', groups: ['create'])]
    public ?string $classId = null;

    #[Assert\NotBlank(message: 'La matière est requise.', groups: ['create'])]
    #[Assert\Uuid(message: 'L\'identifiant de la matière doit être un UUID valide.', groups: ['create'])]
    public ?string $subjectId = null;

    public ?string $teacherId = null;

    #[Assert\NotBlank(message: 'Le titre est requis.', groups: ['create', 'update'])]
    #[Assert\Length(max: 255, maxMessage: 'Le titre ne peut pas dépasser 255 caractères.')]
    public ?string $title = null;

    public ?string $description = null;

    #[Assert\NotBlank(message: 'La date d\'évaluation est requise.', groups: ['create', 'update'])]
    public ?string $evaluationDate = null;

    #[Assert\Range(min: 1, max: 100, notInRangeMessage: 'Le barème doit être compris entre 1 et 100.')]
    public ?int $gradeScale = null;

    #[Assert\Range(min: 0.1, max: 10, notInRangeMessage: 'Le coefficient doit être compris entre 0.1 et 10.')]
    public ?float $coefficient = null;

    public ?string $status = null;

    public ?string $className = null;

    public ?string $subjectName = null;

    public ?DateTimeImmutable $createdAt = null;

    public ?DateTimeImmutable $updatedAt = null;

    public ?DateTimeImmutable $gradesPublishedAt = null;

    public static function fromDomain(
        Evaluation $evaluation,
        ?string $className = null,
        ?string $subjectName = null,
    ): self {
        $resource = new self();
        $resource->id = (string) $evaluation->id;
        $resource->classId = (string) $evaluation->classId;
        $resource->subjectId = (string) $evaluation->subjectId;
        $resource->teacherId = (string) $evaluation->teacherId;
        $resource->title = $evaluation->title;
        $resource->description = $evaluation->description;
        $resource->evaluationDate = $evaluation->evaluationDate->format('Y-m-d');
        $resource->gradeScale = $evaluation->gradeScale->maxValue;
        $resource->coefficient = $evaluation->coefficient->value;
        $resource->status = $evaluation->status->value;
        $resource->className = $className;
        $resource->subjectName = $subjectName;
        $resource->createdAt = $evaluation->createdAt;
        $resource->updatedAt = $evaluation->updatedAt;
        $resource->gradesPublishedAt = $evaluation->gradesPublishedAt;

        return $resource;
    }
}
