using System.Linq.Expressions;
using Cassandra.Mapping;
using JiShe.CollectBus.Cassandra.Extensions;
using Volo.Abp.Domain.Entities;

namespace JiShe.CollectBus.Cassandra
{
    public class CassandraRepository<TEntity, TKey>
        : ICassandraRepository<TEntity, TKey>
        where TEntity : class, ICassandraEntity<TKey>
    {
        private readonly ICassandraProvider _cassandraProvider;
        public CassandraRepository(ICassandraProvider cassandraProvider, MappingConfiguration mappingConfig)
        {
            _cassandraProvider = cassandraProvider;
            Mapper = new Mapper(cassandraProvider.Session, mappingConfig);
            cassandraProvider.Session.CreateTable<TEntity>(cassandraProvider.CassandraConfig.Keyspace);
        }

        public readonly IMapper Mapper;

        public virtual async Task<TEntity> GetAsync(TKey id)
        {
            return await GetAsync("WHERE id = ?", id);
        }

        public virtual async Task<TEntity?> GetAsync(string cql, params object[] args)
        {
            return await Mapper.SingleAsync<TEntity?>(cql, args);
        }


        public virtual async Task<TEntity> FirstOrDefaultAsync(TKey id)
        {
            return await FirstOrDefaultAsync("WHERE id = ?", id);
        }

        public virtual async Task<TEntity?> FirstOrDefaultAsync(string cql, params object[] args)
        {
            return await Mapper.FirstOrDefaultAsync<TEntity>(cql, args);
        }


        public virtual async Task<List<TEntity>?> GetListAsync(string? cql = null, params object[] args)
        {
            return cql.IsNullOrWhiteSpace() ? (await Mapper.FetchAsync<TEntity>()).ToList() : (await Mapper.FetchAsync<TEntity>(cql, args)).ToList();
        }

        public virtual async Task<TEntity> InsertAsync(TEntity entity)
        {
            await Mapper.InsertAsync(entity);
            return entity;
        }

        public virtual async Task<TEntity> UpdateAsync(TEntity entity)
        {
            await Mapper.UpdateAsync(entity);
            return entity;
        }

        public virtual async Task DeleteAsync(TEntity entity)
        {
            await Mapper.DeleteAsync(entity);
        }

        public virtual async Task DeleteAsync(TKey id)
        {
            await Mapper.DeleteAsync<TEntity>("WHERE id = ?", id);
        }

        public virtual async Task<List<TEntity>> GetPagedListAsync(
            int skipCount,
            int maxResultCount,
            string sorting)
        {
            var cql = $"SELECT * FROM {typeof(TEntity).Name.ToLower()}";
            if (!string.IsNullOrWhiteSpace(sorting))
            {
                cql += $" ORDER BY {sorting}";
            }
            cql += $" LIMIT {maxResultCount} OFFSET {skipCount}";

            return (await Mapper.FetchAsync<TEntity>(cql)).ToList();
        }
    }
} 