using FluentValidation;
using PARR.API.Contracts.V1.Requests;
using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.Job;
using PARR.Core.Repositories.Interfaces.Unit;
using PARR.Domain.Entities.Job;

namespace PARR.API.Validators
{
    public class JobRequestValidator : AbstractValidator<JobRequest>
    {
        private readonly ITnkRepository tnkService;
        private readonly IJobGroupRepository jobGroupService;
        private readonly IJobRepository jobRepository;
        private readonly IUnitFieldRepository unitFieldService;
        private JobGroup? jobGroup;

        public JobRequestValidator(
            ITnkRepository tnkService,
            IJobGroupRepository jobGroupService,
            IJobRepository jobService,
            IUnitFieldRepository unitFieldService
            )
        {
            this.tnkService = tnkService;
            this.jobGroupService = jobGroupService;
            this.jobRepository = jobService;
            this.unitFieldService = unitFieldService;

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

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

            RuleFor(t => t.TnkId)
                .MustAsync(async (entity, value, c) => await IsTnkExist(entity))
                .WithMessage("Указан несуществующий Id ТНК({PropertyValue})");

            RuleFor(t => t.GroupId)
                .MustAsync(async (entity, value, c) => await IsGroupExist(entity))
                .WithMessage("Указан несуществующий Id группы работ({PropertyValue})");

            RuleForEach(t => t.UnitFilters)
                .NotNull().NotEmpty();

            RuleForEach(t => t.UnitFilters)
                .MustAsync(async (entity, value, c) => await IsUnitFiltersCorrect(entity))
                .WithMessage("Неверно заданы параметры фильтров. Внимательнее, пожалуйста!");

            RuleFor(t => t.MinValueRelationships)
                .GreaterThanOrEqualTo(0);

            RuleFor(t => t.MaxValueRelationships)
                .GreaterThanOrEqualTo(t => t.MinValueRelationships);

            RuleFor(t => t.ResponseAreaMask)
                .NotNull().NotEmpty();
        }

        private async Task<bool> IsUnitFiltersCorrect(JobRequest entity)
        {
            foreach (var unitFilter in entity.UnitFilters)
            {
                if (string.IsNullOrEmpty(unitFilter.UnitFilterMask))
                    return false;

                //if (unitFilter.FieldFilters == null || !unitFilter.FieldFilters.Any())
                //    return false;

                if (unitFilter.FieldFilters != null && unitFilter.FieldFilters.Any())
                    foreach (var fieldFilter in unitFilter.FieldFilters)
                    {
                        var fieldId = fieldFilter.FieldId;
                        if (await unitFieldService.GetAsync(fieldId) == null)
                            return false;
                    }

                if (unitFilter.RelationshipFilters != null && unitFilter.RelationshipFilters.Any())
                    foreach (var relationshipFilter in unitFilter.RelationshipFilters!)
                    {
                        var fieldId = relationshipFilter.FieldId;
                        if (await unitFieldService.GetAsync(fieldId) == null)
                            return false;
                    }
            }

            return true;
        }

        private async Task<bool> IsGroupExist(JobRequest entity)
        {
            jobGroup = await jobGroupService.GetAsync(entity.GroupId);

            return jobGroup != null;
        }


        private async Task<bool> IsTnkExist(JobRequest entity)
        {
            return await tnkService.GetAsync(entity.TnkId) != null;
        }
    }
}