using System;
using NodePipeline.Abstractions.Interfaces;
using NodePipeline.Abstractions.Interfaces.Nodes;
using NodePipeline.Abstractions.Models.Validation;

namespace NodePipeline.Abstractions.Validators;

public sealed class NumberRangeValidator<T> : NodeFieldValidatorBase<T> where T : struct, IComparable<T>
{
    private readonly T? _max;
    private readonly T? _min;

    public NumberRangeValidator(IPipelineLocalizationProvider localizer, T? min, T? max)
        : base(localizer)
    {
        if (min.HasValue && max.HasValue)
        {
            _min = min.Value.CompareTo(max.Value) < 0 ? min : max;
            _max = min.Value.CompareTo(max.Value) > 0 ? min : max;
        }
        else
        {
            _min = min;
            _max = max;
        }
    }

    public override NodeFieldValidationResult Validate(INodeField<T> nodeField)
    {
        var value = nodeField.Value;
        if (_min.HasValue && _max.HasValue)
        {
            if (value.CompareTo(_min.Value) < 0 || value.CompareTo(_max.Value) > 0)
                return new NodeFieldValidationResult(ValidationResult.HasErrors,
                    Localizer.GetLocalizedString("IntValueRangeError", Culture, _min.Value, _max.Value));

            return SuccessResult;
        }

        if (_min.HasValue && value.CompareTo(_min.Value) < 0)
            return new NodeFieldValidationResult(ValidationResult.HasErrors,
                Localizer.GetLocalizedString("IntValueMinError", Culture, _min.Value));
        if (_max.HasValue && value.CompareTo(_max.Value) > 0)
            return new NodeFieldValidationResult(ValidationResult.HasErrors,
                Localizer.GetLocalizedString("IntValueMaxError", Culture, _max.Value));

        return SuccessResult;
    }
}