using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudDb.Model.ProcessMaps;
using Microsoft.EntityFrameworkCore;

namespace AsbCloudInfrastructure.Repository;

public class ProcessMapPlanRepository<TDto, TEntity> : CrudWellRelatedRepositoryBase<TDto, TEntity>,
    IProcessMapPlanRepository<TDto>
    where TDto : ProcessMapPlanBaseDto
    where TEntity : ProcessMapBase
{
    private readonly IWellService wellService;

    public ProcessMapPlanRepository(IAsbCloudDbContext context, IWellService wellService)
	   : base(context, dbSet =>
		  dbSet
			 .Include(p => p.WellSectionType)
			 .Include(p => p.Well))
    {
	   this.wellService = wellService;
    }

    public async Task<IEnumerable<TDto>> GetAsync(IEnumerable<ProcessMapPlanRequest> requests, CancellationToken cancellationToken)
    {
	   var query = BuildQuery(requests);

	   var entities = await query.ToArrayAsync(cancellationToken);

	   return entities.Select(Convert);
    }

    public Task<int> RemoveByWellAsync(int idWell)
    {
	   var query = GetQuery().Where(x => x.IdWell == idWell);

	   dbSet.RemoveRange(query);

	   return dbContext.SaveChangesAsync(CancellationToken.None);
    }

    private IQueryable<TEntity> BuildQuery(IEnumerable<ProcessMapPlanRequest> requests)
    {
	   var query = GetQuery();

	   foreach (var request in requests)
	   {
		  query = query.Where(p => p.IdWell == request.IdWell);

		  if (request.IdWellSectionType is not null)
			 query = query.Where(p => p.IdWellSectionType == request.IdWellSectionType);

		  if (request.UpdateFrom is not null)
		  {
			 var timezone = wellService.GetTimezone(request.IdWell);
			 var updateFromUtc = request.UpdateFrom?.ToUtcDateTimeOffset(timezone.Hours);

			 query = query.Where(p => p.LastUpdate >= updateFromUtc);
		  }
	   }

	   return query.OrderBy(e => e.DepthStart)
		  .ThenBy(e => e.Id)
		  .AsNoTracking();
    }
}