using FluentValidation;
using Microsoft.EntityFrameworkCore;
using PARR.API.Contracts.V1.Requests;
using PARR.DAL.Contracts;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Schedule;
using PARR.DAL.Services.Interfaces.Unit;

namespace PARR.API.Validators
{
    public class JobGroupValidator : AbstractValidator<JobGroupRequest>
    {
        public JobGroupValidator(
            IJobGroupTypeService jobGroupTypeService,
            IUnitFieldService unitFieldService,
            IScheduleExcludeTypeService scheduleExcludeTypeService,
            IScheduleExcludeTypeCalendarService scheduleExcludeTypeCalendarService
            )
        {
            RuleFor(t => t.Name)
                .NotNull().NotEmpty();

            RuleFor(t => t.ShortDescription)
                .NotNull().NotEmpty();

            RuleFor(t => t.FullDescription)
                .NotNull().NotEmpty();

            RuleFor(t => t.Solution)
                .NotNull().NotEmpty();

            RuleFor(t => t.TemplateDuration)
                .NotNull().NotEmpty();

            RuleFor(t => t.GroupTypeId)
                .MustAsync(async (entity, value, c) => await jobGroupTypeService.GetAsync(value) != null)
                .WithMessage("Указан несуществующий Id типа");

            //Проверяем существует ли такой GroupingUnitFieldId в unitField
            RuleFor(t => t.GroupingUnitFieldId)
                .MustAsync(async (entity, value, c) =>
                {
                    if (!value.HasValue)
                    {
                        return true;
                    }

                    return await unitFieldService.GetAsync(value.Value) != null;
                })
                .WithMessage("Указано несуществующий Id поля");


            RuleFor(t => t.GroupingUnitFieldId)
                .MustAsync(async (entity, value, c) =>
                {
                    var groupingJobType = await jobGroupTypeService.Get().FirstAsync(t => t.Code == JobGroupTypesEnum.Group);

                    // Если это сгруппированный тип, то у него обязательно должно быть заполнено поле GroupingUnitFieldId
                    if (entity.GroupTypeId == groupingJobType.Id)
                        return value.HasValue;

                    return true;
                })
                .WithMessage("Не указано поле для группировки");

            RuleFor(t => t.ScheduleExcludeTypeId)
                .NotNull()
                .NotEmpty()
                .MustAsync(async (entity, value, c) => await scheduleExcludeTypeService.GetAsync(value) != null)
                .WithMessage("Некорректное значение");

            RuleFor(t => t.ScheduleExcludeTypeCalendarId)
                .MustAsync(async (entity, value, c) =>
                {
                    // Если выбрано "Нет исключений", то это поле должно быть пустое, иначе, должно быть валидное значение
                    var type = await scheduleExcludeTypeService.GetAsync(entity.ScheduleExcludeTypeId);
                    if (type == null)
                        return false;

                    if (type.Code == ScheduleExcludeTypeEnum.None.ToString())
                    {
                        // ScheduleExcludeTypeCalendarId должно быть null 
                        return value == null;
                    }

                    // Тип любой кроме "Нет исключений", значение обязательно
                    if (!value.HasValue)
                        return false;

                    return await scheduleExcludeTypeCalendarService.GetAsync(value.Value) != null;
                })
                .WithMessage("Некорректное значение");


        }
    }
}
