namespace MyOffice.Data.Repositories;

using Microsoft.EntityFrameworkCore;
using DbContext;

public class RepositoryBase<TEntity> where TEntity : class
{
	protected readonly AppDbContext _context;

	protected RepositoryBase(
		AppDbContext context
	)
	{
		_context = context;
	}

	protected async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
	{
		try
		{
			return await _context.SaveChangesAsync(cancellationToken);
		}
		catch (DbUpdateException updateException)
		{
			throw updateException;
		}
	}

	protected int SaveChanges()
	{
		try
		{
			return _context.SaveChanges();
		}
		catch (DbUpdateException updateException)
		{
			throw updateException;
		}
	}


	protected async Task<TEntity?> GetBaseAsync(Guid id)
	{
		return await _context.Set<TEntity>().FindAsync(id);
	}

	protected TEntity? GetBase(Guid id)
	{
		return _context.Set<TEntity>().Find(id);
	}

	protected int AddBase(TEntity entity)
	{
		_context.Entry(entity).State = EntityState.Added;

		var result = SaveChanges();

		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}

	protected async Task<int> AddBaseAsync(TEntity entity, CancellationToken cancellationToken = default)
	{
		_context.Entry(entity).State = EntityState.Added;
		var result = await SaveChangesAsync(cancellationToken);
		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}

	protected int RemoveBase(TEntity entity)
	{
		_context.Set<TEntity>().Remove(entity);
		
		_context.Entry(entity).State = EntityState.Deleted;

		var result = SaveChanges();

		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}

	protected async Task<int> RemoveBaseAsync(TEntity entity, CancellationToken cancellationToken = default)
	{
		_context.Set<TEntity>().Remove(entity);
		_context.Entry(entity).State = EntityState.Deleted;
		var result = await SaveChangesAsync(cancellationToken);
		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}

	protected int UpdateBase(TEntity entity)
	{
		_context.Entry(entity).State = EntityState.Modified;

		var result = SaveChanges();

		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}

	protected async Task<int> UpdateBaseAsync(TEntity entity, CancellationToken cancellationToken = default)
	{
		_context.Entry(entity).State = EntityState.Modified;
		var result = await SaveChangesAsync(cancellationToken);
		_context.Entry(entity).State = EntityState.Detached;
		return result;
	}
}