using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data.Manuals;
using AsbCloudApp.Repositories;
using AsbCloudDb.Model;
using AsbCloudDb.Model.Manuals;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace AsbCloudInfrastructure.Repository;

public class ManualDirectoryRepository : CrudRepositoryBase<ManualDirectoryDto, ManualDirectory>, IManualDirectoryRepository
{
   public ManualDirectoryRepository(IAsbCloudDbContext context) : base(context)
   {
   }

   public async Task<IEnumerable<ManualDirectoryDto>> GetTreeAsync(CancellationToken cancellationToken)
   {
      var directories = await dbContext.ManualDirectories
         .Include(m => m.Manuals)
         .Include(m => m.Parent)
         .AsNoTracking()
         .ToArrayAsync(cancellationToken);

      return BuildTree(directories).Select(x => x.Adapt<ManualDirectoryDto>());
   }

   public async Task<ManualDirectoryDto?> GetOrDefaultAsync(string name, int? idParent, CancellationToken cancellationToken)
   {
      var entity = await dbContext.ManualDirectories
         .AsNoTracking()
         .FirstOrDefaultAsync(m => m.Name == name &&
                           m.IdParent == idParent, cancellationToken);

      if (entity is null)
         return null;

      return Convert(entity);
   }

   public Task<bool> IsExistsAsync(int id, CancellationToken cancellationToken) =>
      dbContext.ManualDirectories.AnyAsync(d => d.Id == id, cancellationToken);

   private static IEnumerable<ManualDirectory> BuildTree(IEnumerable<ManualDirectory> directories)
   {
      var directoryDict = directories.ToDictionary(f => f.Id);

      foreach (var directory in directories)
      {
         if (directory.IdParent.HasValue && directoryDict.TryGetValue(directory.IdParent.Value, out var parent))
         {
            parent.Children ??= new List<ManualDirectory>();
            parent.Children.Add(directory);
         }
      }

      return directories.Where(f => f.IdParent == null);
   }
}