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);
	}
}