<?php

declare(strict_types=1);

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

use App\Administration\Domain\Model\GradingConfiguration\GradingMode;
use App\Scolarite\Domain\Model\GradingMode as ScolariteGradingMode;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

final class GradingModeTest extends TestCase
{
    #[Test]
    public function itHasCorrectValues(): void
    {
        self::assertSame('numeric_20', GradingMode::NUMERIC_20->value);
        self::assertSame('numeric_10', GradingMode::NUMERIC_10->value);
        self::assertSame('letters', GradingMode::LETTERS->value);
        self::assertSame('competencies', GradingMode::COMPETENCIES->value);
        self::assertSame('no_grades', GradingMode::NO_GRADES->value);
    }

    #[Test]
    public function numeric20HasCorrectScale(): void
    {
        self::assertSame(20, GradingMode::NUMERIC_20->scaleMax());
    }

    #[Test]
    public function numeric10HasCorrectScale(): void
    {
        self::assertSame(10, GradingMode::NUMERIC_10->scaleMax());
    }

    #[Test]
    public function nonNumericModesHaveNullScale(): void
    {
        self::assertNull(GradingMode::LETTERS->scaleMax());
        self::assertNull(GradingMode::COMPETENCIES->scaleMax());
        self::assertNull(GradingMode::NO_GRADES->scaleMax());
    }

    #[Test]
    public function numericModesUseNumericGrading(): void
    {
        self::assertTrue(GradingMode::NUMERIC_20->estNumerique());
        self::assertTrue(GradingMode::NUMERIC_10->estNumerique());
    }

    #[Test]
    public function nonNumericModesDoNotUseNumericGrading(): void
    {
        self::assertFalse(GradingMode::LETTERS->estNumerique());
        self::assertFalse(GradingMode::COMPETENCIES->estNumerique());
        self::assertFalse(GradingMode::NO_GRADES->estNumerique());
    }

    #[Test]
    public function modesRequiringAverageCalculation(): void
    {
        self::assertTrue(GradingMode::NUMERIC_20->calculeMoyenne());
        self::assertTrue(GradingMode::NUMERIC_10->calculeMoyenne());
        self::assertTrue(GradingMode::LETTERS->calculeMoyenne());
        self::assertFalse(GradingMode::COMPETENCIES->calculeMoyenne());
        self::assertFalse(GradingMode::NO_GRADES->calculeMoyenne());
    }

    #[Test]
    public function labelsAreInFrench(): void
    {
        self::assertSame('Notes /20', GradingMode::NUMERIC_20->label());
        self::assertSame('Notes /10', GradingMode::NUMERIC_10->label());
        self::assertSame('Lettres (A-E)', GradingMode::LETTERS->label());
        self::assertSame('Compétences', GradingMode::COMPETENCIES->label());
        self::assertSame('Sans notes', GradingMode::NO_GRADES->label());
    }

    #[Test]
    public function administrationAndScolariteEnumsAreInSync(): void
    {
        $adminValues = array_map(
            static fn (GradingMode $m) => $m->value,
            GradingMode::cases(),
        );
        $scolariteValues = array_map(
            static fn (ScolariteGradingMode $m) => $m->value,
            ScolariteGradingMode::cases(),
        );

        self::assertSame(
            $adminValues,
            $scolariteValues,
            'Les enums GradingMode des contextes Administration et Scolarité doivent rester synchronisées.',
        );
    }
}
