<?php

namespace App\Services\Grading\Validation;

use InvalidArgumentException;

class ScoreValueValidator
{
    public const DEFAULT_MAX_POINTS = 100.0;

    public function normalizeNullable(mixed $value, float|int|null $maxPoints = self::DEFAULT_MAX_POINTS, string $label = 'Score'): ?float
    {
        if ($value === null || (is_string($value) && trim($value) === '')) {
            return null;
        }

        $max = $this->normalizeMaxPoints($maxPoints, $label);

        if (!is_numeric($value)) {
            throw new InvalidArgumentException("{$label} must be numeric.");
        }

        $score = (float) $value;
        if ($score < 0 || $score > $max) {
            throw new InvalidArgumentException("{$label} must be between 0 and {$max}.");
        }

        return $score;
    }

    public function normalizeMaxPoints(float|int|null $maxPoints = self::DEFAULT_MAX_POINTS, string $label = 'Score'): float
    {
        $max = $maxPoints === null ? self::DEFAULT_MAX_POINTS : (float) $maxPoints;
        if ($max <= 0) {
            throw new InvalidArgumentException("{$label} max points must be greater than 0.");
        }
        return $max;
    }

    public function inferStatus(?float $score, bool $missingAllowed = false): string
    {
        if ($score !== null) {
            return 'scored';
        }

        return $missingAllowed ? 'excused' : 'pending';
    }
}
