using Microsoft.EntityFrameworkCore;
using PARR.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.Job;
using PARR.Core.Repositories.Interfaces.Unit;


namespace PARR.TemplateGeneratorWorker.Services
{
    internal class ValidatorService : IValidatorService
    {
        private readonly ILogger<ValidatorService> logger;
        private readonly IJobRepository jobService;
        private readonly IUnitRepository unitService;
        private readonly ITemplateRepository templateService;
        private readonly IUnitInValueRepository unitInValueRepo;

        public ValidatorService(
            ILogger<ValidatorService> logger,
            IJobRepository jobService,
            IUnitRepository unitService,
            ITemplateRepository templateService,
            IUnitInValueRepository unitInValueRepo
            )
        {
            this.logger = logger;
            this.jobService = jobService;
            this.unitService = unitService;
            this.templateService = templateService;
            this.unitInValueRepo = unitInValueRepo;
        }

        public async Task<bool> IsValidAsync(Guid jobId, Guid unitId, int? index, List<(Guid UnitId, Guid UnitFieldValueId)>? unitsInTemplate = null)
        {
            // 1. Проверяем JobId
            var job = await jobService
                .Get().AsNoTracking()
                .FirstOrDefaultAsync(t => t.Id == jobId);

            if (job == null)
            {
                logger.LogError("Не найдена регламентная работа JobId: {JobId}", jobId);
                return false;
            }

            // 2. Проверяем UnitId (основной юнит шаблона)
            var unit = await unitService
                .Get().AsNoTracking()
                .FirstOrDefaultAsync(t => t.Id == unitId);

            if (unit == null)
            {
                logger.LogError("Не найден элемент конфигурации UnitId: {UnitId}", unitId);
                return false;
            }

            // 3. Проверяем уникальность (JobId, UnitId, Index)
            var existingTemplate = await templateService
                .Get().AsNoTracking()
                .FirstOrDefaultAsync(t => t.JobId == jobId && t.UnitId == unitId && t.Index == index);

            if (existingTemplate != null)
            {
                logger.LogError("Шаблон с JobId={JobId}, UnitId={UnitId}, Index={Index} уже существует.", jobId, unitId, index);
                return false;
            }

            if (unitsInTemplate != null && unitsInTemplate.Any())
            {
                var pairsToCheck = unitsInTemplate.Distinct().ToList();
                var unitIdsToCheck = pairsToCheck.Select(p => p.UnitId).Distinct().ToList();
                var valueIdsToCheck = pairsToCheck.Select(p => p.UnitFieldValueId).Distinct().ToList();

                // Загружаем только те связи, которые относятся к проверяемым ID
                var existingLinks = await unitInValueRepo.Get()
                    .AsNoTracking()
                    .Where(uiv => unitIdsToCheck.Contains(uiv.UnitId) && valueIdsToCheck.Contains(uiv.ValueId))
                    .Select(uiv => new { uiv.UnitId, uiv.ValueId })
                    .ToListAsync();

                // Формируем HashSet существующих пар для быстрой проверки в памяти
                var existingPairsSet = existingLinks
                    .Select(x => (x.UnitId, UnitFieldValueId: x.ValueId))
                    .ToHashSet();

                // Проверяем, что каждая запрошенная пара реально существует в БД
                var allPairsValid = pairsToCheck.All(p => existingPairsSet.Contains((p.UnitId, p.UnitFieldValueId)));

                if (!allPairsValid)
                {
                    logger.LogError("Не все пары (UnitId, UnitFieldValueId) из UnitsInTemplate являются валидными связями в UnitInValue.");
                    return false;
                }
            }

            return true;
        }
    }
}