using FluentValidation;
using Microsoft.AspNetCore.Mvc.Filters;

namespace PARR.API.Infrastructure.Filters
{
    /// <summary>
    /// Фильтр для автоматического применения валидации реквестов.
    /// </summary>
    public class AsyncValidationFilter : IAsyncActionFilter
    {
        /// <summary>
        /// Фильтр для автоматического применения валидации реквестов.
        /// Выполняется до срабатывания метода в контроллере.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        /// <exception cref="ValidationException"></exception>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            foreach (var argument in context.ActionArguments.Values)
            {
                if (argument == null)
                    continue;

                // Динамически ищем валидатор в DI для типа текущего аргумента
                var validatorType = typeof(IValidator<>).MakeGenericType(argument.GetType());
                var validator = context.HttpContext.RequestServices.GetService(validatorType) as IValidator;

                if (validator is IValidator validatorInstance)
                {
                    var validationContext = new ValidationContext<object>(argument);
                    
                    // Запуск асинхронной валидации 
                    var validationResult = await validator.ValidateAsync(validationContext, context.HttpContext.RequestAborted);

                    if (!validationResult.IsValid)
                    {
                        throw new ValidationException(validationResult.Errors);
                    }
                }
            }

            await next();
        }
    }
}