namespace MyOffice.Data.Repositories.Item;

using Microsoft.EntityFrameworkCore;
using MyOffice.Data.Models.Items;
using MyOffice.DbContext;

public class ItemRepository : AppRepository<Item>, IItemRepository
{
	public ItemRepository(AppDbContext context) : base(context)
	{
	}

	public List<Item> GetAll(Guid userId)
	{
		return _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId)
			.ToList();
	}

	public async Task<List<Item>> GetAllAsync(Guid userId, CancellationToken cancellationToken = default)
	{
		return await _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId)
			.ToListAsync(cancellationToken);
	}

	public List<Item> GetByCategory(Guid userId, Guid categoryId)
	{
		return _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId && x.CategoryId == categoryId)
			.ToList();
	}

	public async Task<List<Item>> GetByCategoryAsync(
		Guid userId,
		Guid categoryId,
		CancellationToken cancellationToken = default)
	{
		return await _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId && x.CategoryId == categoryId)
			.ToListAsync(cancellationToken);
	}

	public Item? GetByGlobal(Guid userId, Guid globalItemId)
	{
		return _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.FirstOrDefault(x => x.Category!.UserId == userId && x.ItemGlobalId == globalItemId);
	}

	public Task<Item?> GetByGlobalAsync(Guid userId, Guid globalItemId, CancellationToken cancellationToken = default)
	{
		return _context.Items
			.Include(x => x.Motions)
			.Include(x => x.Category)
			.Include(x => x.ItemGlobal)
			.FirstOrDefaultAsync(
				x => x.Category!.UserId == userId && x.ItemGlobalId == globalItemId,
				cancellationToken);
	}

	public bool Update(Item item)
	{
		return base.UpdateBase(item) > 0;
	}

	public async Task<bool> UpdateAsync(Item item, CancellationToken cancellationToken = default)
	{
		return await UpdateBaseAsync(item, cancellationToken) > 0;
	}

	public bool Add(Item item)
	{
		return base.AddBase(item) > 0;
	}

	public async Task<bool> AddAsync(Item item, CancellationToken cancellationToken = default)
	{
		return await AddBaseAsync(item, cancellationToken) > 0;
	}

	public List<Item> Find(Guid userId, string term, int limit)
	{
		return _context
			.Items
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId && x.ItemGlobal.Name.ToLower().Contains(term.ToLower()))
			.OrderByDescending(x => x!.Motions!.Count())
			.Take(limit)
			.ToList();
	}

	public async Task<List<Item>> FindAsync(
		Guid userId,
		string term,
		int limit,
		CancellationToken cancellationToken = default)
	{
		return await _context
			.Items
			.Include(x => x.ItemGlobal)
			.Where(x => x.Category!.UserId == userId && x.ItemGlobal.Name.ToLower().Contains(term.ToLower()))
			.OrderByDescending(x => x!.Motions!.Count())
			.Take(limit)
			.ToListAsync(cancellationToken);
	}
}