<?php

declare(strict_types=1);

namespace App\Administration\Domain\Model\Subject;

use App\Administration\Domain\Exception\SubjectCodeInvalideException;

use function assert;
use function preg_match;
use function strtoupper;
use function trim;

/**
 * Value Object représentant le code court d'une matière.
 *
 * Contraintes :
 * - Entre 2 et 10 caractères
 * - Lettres majuscules et chiffres uniquement
 * - Exemple: "MATH", "FR", "HG", "EPS"
 */
final class SubjectCode
{
    private const int MIN_LENGTH = 2;
    private const int MAX_LENGTH = 10;
    private const string PATTERN = '/^[A-Z0-9]{2,10}$/';

    public function __construct(
        /** @var non-empty-string */
        public private(set) string $value {
            set(string $value) {
                $normalized = strtoupper(trim($value));

                if (preg_match(self::PATTERN, $normalized) !== 1) {
                    throw SubjectCodeInvalideException::pourFormat($value, self::MIN_LENGTH, self::MAX_LENGTH);
                }

                // After validation, $normalized is guaranteed to be non-empty (MIN_LENGTH >= 2)
                assert($normalized !== '');
                $this->value = $normalized;
            }
        },
    ) {
    }

    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}
