using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Query;
#if NETFRAMEWORK
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
#endif

namespace DigitalData.Core.Abstraction.Application.Repository
{
    public interface IRepository
    {
#if NET
    public
#endif
        Task<int> ExecuteSqlRawAsync([NotParameterized] string sql, IEnumerable<object> parameters, CancellationToken cancel = default);

#if NET
    public
#endif
        Task<int> ExecuteSqlInterpolatedAsync(FormattableString sql, CancellationToken cancel = default);

#if NET
    public
#endif
        int ExecuteSqlRaw([NotParameterized] string sql, params object[] parameters);

#if NET
    public
#endif
        int ExecuteSqlInterpolated(FormattableString sql);
    }

    public interface IRepository<TEntity>
    {
        #region Create
#if NET
    public
#endif
        Task<TEntity> CreateAsync(TEntity entity, CancellationToken cancel = default);

#if NET
    public
#endif
        Task<IEnumerable<TEntity>> CreateAsync(IEnumerable<TEntity> entities, CancellationToken cancel = default);

#if NET
    public
#endif
        Task<TEntity> CreateAsync<TDto>(TDto dto, CancellationToken cancel = default);

#if NET
    public
#endif
        Task<IEnumerable<TEntity>> CreateAsync<TDto>(IEnumerable<TDto> dtos, CancellationToken cancel = default);
        #endregion Create

        #region Read
#if NET
    public
#endif
        IQueryable<TEntity> Query { get; }

#if NET
    public
#endif
        IQueryable<TEntity> QueryRaw([NotParameterized] string sql, params object[] parameters);

#if NET
    public
#endif
        IQueryable<TEntity> QueryInterpolated([NotParameterized] FormattableString sql);

#if NET
    public
#endif
        IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression);

#if NET
    public
#endif
        IEnumerable<TEntity> GetAll();

#if NET
    public
#endif
        Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancel = default);
        #endregion Read

        #region Update
#if NET
    public
#endif
        Task UpdateAsync<TDto>(TDto dto, Expression<Func<TEntity, bool>> expression, CancellationToken cancel = default);

#if NET
    public
#endif
        Task UpdateAsync<TDto>(TDto dto, Func<IQueryable<TEntity>, IQueryable<TEntity>> query, CancellationToken cancel = default);

#if NET
    public
#endif
        Task UpdateAsync(Action<TEntity> modification, Func<IQueryable<TEntity>, IQueryable<TEntity>> query, CancellationToken cancel = default);

#if NET
    public
#endif
        Task UpdateAsync(Action<TEntity> modification, Expression<Func<TEntity, bool>> expression, CancellationToken cancel = default);
        #endregion Update

        #region Delete
#if NET
    public
#endif
        Task DeleteAsync(Expression<Func<TEntity, bool>> expression, CancellationToken cancel = default);

#if NET
    public
#endif
        Task DeleteAsync(Func<IQueryable<TEntity>, IQueryable<TEntity>> query, CancellationToken cancel = default);
        #endregion Delete

        #region Obsolete
        [Obsolete("Use CreateAsync, UpdateAsync or DeleteAsync")]
#if NET
    public
#endif
        IQueryable<TEntity> Read();

        [Obsolete("Use IRepository<TEntity>.Where")]
#if NET
    public
#endif
        IQueryable<TEntity> ReadOnly();
        #endregion
    }
}