using System.Linq.Expressions;
using Marten;

namespace NetinaShop.Repository.Repositories.Entity;

public class MartenRepository : IMartenRepository
{
    private readonly IDocumentStore _documentStore;

    public MartenRepository(IDocumentStore documentStore)
    {
        _documentStore = documentStore;
    }
    public async Task<List<TSetting>> GetEntitiesAsync<TSetting>(CancellationToken cancellation) where TSetting : notnull
    {
        await using var session = _documentStore.QuerySession();
        var entities = await session.Query<TSetting>().ToListAsync(cancellation);
        return entities.ToList();
    }

    public async Task<List<TSetting>> GetEntitiesAsync<TSetting>(Expression<Func<TSetting, bool>> expression, CancellationToken cancellation) where TSetting : notnull
    {
        await using var session = _documentStore.QuerySession();
        var entities = await session.Query<TSetting>().Where(expression).ToListAsync(cancellation);
        return entities.ToList();
    }

    public async Task<TSetting> GetEntityAsync<TSetting>(Guid id,CancellationToken cancellation) where TSetting : notnull
    {
        await using var session = _documentStore.QuerySession();
        var setting = await session.LoadAsync<TSetting>(id,cancellation);
        if (setting == null)
            throw new AppException($"{nameof(setting)} not found", ApiResultStatusCode.NotFound);
        return setting;
    }

    public async Task<TSetting> GetEntityAsync<TSetting>(Expression<Func<TSetting, bool>> expression, CancellationToken cancellation) where TSetting : notnull
    {
        await using var session = _documentStore.QuerySession();
        var entity = await session.Query<TSetting>().FirstOrDefaultAsync(expression,cancellation);
        if (entity == null)
            throw new AppException($"{nameof(entity)} not found", ApiResultStatusCode.NotFound);
        return entity;
    }

    public async Task AddOrUpdateEntityAsync<TSetting>(TSetting setting, CancellationToken cancellation) where TSetting : notnull
    {
        if (setting == null)
            throw new AppException($"{nameof(setting)} is null", ApiResultStatusCode.BadRequest);

        await using var session = _documentStore.LightweightSession();
        session.Store(setting);
        await session.SaveChangesAsync(cancellation);
    }

    public Task RemoveEntityAsync<TSetting>(CancellationToken cancellation)
    {
        throw new NotImplementedException();
    }
}