using FluentValidation;
using IWS5.Core.DTO.IAdmin.Schedules;
using IWS5.DatabaseAccess.Interfaces.IAdmin;

namespace IWS5.Services.Validators.IAdmin;

public class ScheduleTaskRequestValidator : AbstractValidator<ScheduleTaskRequestDTO>
{
    private const int TaskType_FileExecute = 1;
    private const int TaskType_SqlScript = 2;
    private const int TaskType_Email = 3;

    public ScheduleTaskRequestValidator(IScheduleTaskRepository scheduleTaskRepository)
    {
        RuleFor(x => x.TaskName)
            .NotEmpty().WithMessage("Task name is required.")
            .MaximumLength(255).WithMessage("Task name must not exceed 255 characters.");

        RuleFor(x => x.TaskTypeId)
            .GreaterThan(0).WithMessage("TaskTypeId must be a positive number.")
            .Must(id =>
            {
                try
                {
                    var type = scheduleTaskRepository.GetTaskTypeByIdAsync(id).GetAwaiter().GetResult();
                    return type != null;
                }
                catch
                {
                    return false;
                }
            })
            .WithMessage("Invalid TaskTypeId. The specified task type does not exist in the database.");

        RuleFor(x => x.CommandText)
            .MaximumLength(4000).WithMessage("Command text must not exceed 4000 characters.");

        RuleFor(x => x.ExecutablePath)
            .MaximumLength(1024).WithMessage("Executable path must not exceed 1024 characters.");

        RuleFor(x => x.SortOrder)
            .GreaterThanOrEqualTo(0).WithMessage("Sort order must be non-negative.");

        When(x => x.OnSuccessActionId.HasValue, () =>
        {
            RuleFor(x => x.OnSuccessActionId!.Value)
                .GreaterThan(0).WithMessage("OnSuccessActionId must be a positive number.")
                .Must(actionId =>
                {
                    try
                    {
                        var action = scheduleTaskRepository
                            .GetTaskActionTypeByIdAsync(actionId)
                            .GetAwaiter()
                            .GetResult();

                        return action != null;
                    }
                    catch
                    {
                        return false;
                    }
                })
                .WithMessage("Invalid OnSuccessActionId. The specified action type does not exist.");
        });

        When(x => x.OnFailureActionId.HasValue, () =>
        {
            RuleFor(x => x.OnFailureActionId!.Value)
                .GreaterThan(0).WithMessage("OnFailureActionId must be a positive number.")
                .Must(actionId =>
                {
                    try
                    {
                        var action = scheduleTaskRepository
                            .GetTaskActionTypeByIdAsync(actionId)
                            .GetAwaiter()
                            .GetResult();

                        return action != null;
                    }
                    catch
                    {
                        return false;
                    }
                })
                .WithMessage("Invalid OnFailureActionId. The specified action type does not exist.");
        });

        When(x => x.TaskTypeId == TaskType_SqlScript, () =>
        {
            RuleFor(x => x.CommandText)
                .NotEmpty().WithMessage("CommandText is required for SQL tasks.")
                .Must(cmd =>
                {
                    var t = cmd?.TrimStart();
                    return !string.IsNullOrWhiteSpace(t) &&
                           (t.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase) ||
                            t.StartsWith("EXEC", StringComparison.OrdinalIgnoreCase));
                })
                .WithMessage("SQL command must start with SELECT or EXEC.");
        });

        When(x => x.TaskTypeId == TaskType_FileExecute, () =>
        {
            RuleFor(x => x.ExecutablePath)
                .NotEmpty().WithMessage("ExecutablePath is required for FileExecute tasks.");
        });

        When(x => x.TaskTypeId == TaskType_Email, () =>
        {
            RuleFor(x => x.CommandText)
                .NotEmpty().WithMessage("CommandText must contain email content or template.");
        });
    }
}