using Dapper;
using Long.Core.Query;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Long.Dapper
{
    /// <summary>
    /// 基础数据库连接类接口
    /// </summary>
    public interface IDatabase<TEntity>
    {
        /// <summary>
        /// 设置 appsettings.json 中的数据库连接字符串
        /// </summary>
        /// <param name="dbKey">数据库配置关键字</param>
        void SetConnectionString(string dbKey);

        /// <summary>
        /// 获取数据库连接
        /// </summary>
        /// <returns></returns>
        /// <exception cref="ApplicationException"></exception>
        IDbConnection GetDbConnection();

        #region 查询

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="sqlString">SQL 查询字符串</param>
        /// <param name="param">SQL 参数对象</param>
        /// <returns>泛型列表</returns>
        IEnumerable<T> Query<T>(string sqlString, object? param = null);

        /// <summary>
        /// 查询列表
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="sqlString">SQL 查询字符串</param>
        /// <param name="param">SQL 参数对象</param>
        /// <returns>泛型列表</returns>
        Task<IEnumerable<T>> QueryAsync<T>(string sqlString, object? param = null);

        /// <summary>
        /// 查询第一条数据
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="sqlString">SQL 查询字符串</param>
        /// <param name="param">SQL 参数对象</param>
        /// <returns>泛型对象</returns>
        T QueryFirst<T>(string sqlString, object? param = null);

        /// <summary>
        /// 查询第一条数据
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="sqlString">SQL 查询字符串</param>
        /// <param name="param">SQL 参数对象</param>
        /// <returns>泛型对象</returns>
        Task<T> QueryFirstAsync<T>(string sqlString, object? param = null);

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns></returns>
        IEnumerable<TEntity> Get();

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAsync();

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        IEnumerable<TEntity> Get(string sql, object param);

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAsync(string sql, object param);

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<IEnumerable<T>> GetAsync<T>(string sql, object param);

        /// <summary>
        /// 通过id获取数据
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns></returns>
        IEnumerable<TEntity> Get(long id);

        /// <summary>
        /// 通过id获取数据
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAsync(long id);

        /// <summary>
        /// 通过一堆id获取数据
        /// </summary>
        /// <param name="ids">内码列表</param>
        /// <returns></returns>
        IEnumerable<TEntity> Get(IEnumerable<long> ids);

        /// <summary>
        /// 通过一堆id获取数据
        /// </summary>
        /// <param name="ids">内码列表</param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAsync(IEnumerable<long> ids);

        /// <summary>
        /// 获取一堆数据
        /// </summary>
        /// <param name="queryParamenter">查询参数</param>
        /// <returns></returns>
        IEnumerable<TEntity> Get(QueryParamenter queryParamenter);

        /// <summary>
        /// 获取一堆数据
        /// </summary>
        /// <param name="queryParamenter">查询参数</param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAsync(QueryParamenter queryParamenter);

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <param name="param">查询参数</param>
        /// <returns></returns>
        Task<IEnumerable<T>> GetAsync<T>(QueryParamenter param);

        /// <summary>
        /// 通过id获取一条数据
        /// </summary>
        /// <returns></returns>
        TEntity GetFirst();

        /// <summary>
        /// 通过id获取一条数据
        /// </summary>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync();

        /// <summary>
        /// 通过id获取一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntity GetFirst(long id);

        /// <summary>
        /// 通过id获取一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync(long id);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        TEntity GetFirst(string sql);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync(string sql);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        TEntity GetFirst(string sql, object param);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync(string sql, object param);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<T> GetFirstAsync<T>(string sql, object param);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        TEntity GetFirst(QueryParamenter queryParamenter, object? param = null);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync(QueryParamenter queryParamenter, object? param = null);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        TEntity GetFirst(QueryParamenter queryParamenter);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        Task<TEntity> GetFirstAsync(QueryParamenter queryParamenter);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        T GetFirst<T>(QueryParamenter queryParamenter);

        /// <summary>
        /// 获取一条数据
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        Task<T> GetFirstAsync<T>(QueryParamenter queryParamenter);

        #endregion

        #region 统计

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <returns>记录数</returns>
        int Count();

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <returns>记录数</returns>
        Task<int> CountAsync();

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <returns>记录数</returns>
        Task<int> CountAsync(QueryParamenter queryParamenter);

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns>记录数</returns>
        int Count(long id);

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns>记录数</returns>
        Task<int> CountAsync(long id);

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns>记录数</returns>
        int Count(string tableName);

        /// <summary>
        /// 统计表记录数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns>记录数</returns>
        Task<int> CountAsync(string tableName);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        int CountByWhere(string where);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        Task<int> CountByWhereAsync(string where);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="id">内码</param>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        int CountByWhere(long id, string where);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="id">内码</param>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        Task<int> CountByWhereAsync(long id, string where);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        int CountByWhere(string tableName, string where);

        /// <summary>
        /// 通过条件统计表记录数
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="where">筛选条件，不包含 WHERE 关键字</param>
        /// <returns>记录数</returns>
        Task<int> CountByWhereAsync(string tableName, string where);

        #endregion

        #region 插入

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="sql">SQL</param>
        /// <param name="insert">插入对象</param>
        /// <returns>插入记录数</returns>
        int Insert(string sql, object insert);

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="sql">SQL</param>
        /// <param name="insert">插入对象</param>
        /// <returns></returns>
        Task<int> InsertAsync(string sql, object insert);

        /// <summary>
        /// 插入数据，自动填入Id
        /// </summary>
        /// <param name="insert">插入对象</param>
        /// <returns>记录内码</returns>
        long Insert(TEntity insert);

        /// <summary>
        /// 插入数据，自动填入Id
        /// </summary>
        /// <param name="insert">插入对象</param>
        /// <returns>记录内码</returns>
        Task<long> InsertAsync(TEntity insert);

        /// <summary>
        /// 插入一堆数据，自动填入Id
        /// </summary>
        /// <param name="inserts">插入对象列表</param>
        /// <returns>记录内码列表</returns>
        IEnumerable<long> Insert(IEnumerable<TEntity> inserts);

        /// <summary>
        /// 插入一堆数据，自动填入Id
        /// </summary>
        /// <param name="inserts">插入对象列表</param>
        /// <returns>记录内码列表</returns>
        Task<IEnumerable<long>> InsertAsync(IEnumerable<TEntity> inserts);

        #endregion

        #region 更新

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="sql">SQL</param>
        /// <param name="update">更新对象</param>
        /// <returns></returns>
        int Update(string sql, object update);

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="sql">SQL</param>
        /// <param name="update">更新对象</param>
        /// <returns></returns>
        Task<int> UpdateAsync(string sql, object update);

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="insert">更新对象</param>
        /// <returns></returns>
        int Update(TEntity update);

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="insert">更新对象</param>
        /// <returns></returns>
        Task<int> UpdateAsync(TEntity update);

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="update">更新对象</param>
        /// <param name="fields">更新字段</param>
        /// <returns></returns>
        int Update(TEntity update, string[] fields);

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="update">更新对象</param>
        /// <param name="fields">更新字段</param>
        /// <returns></returns>
        Task<int> UpdateAsync(TEntity update, string[] fields);

        /// <summary>
        /// 更新一堆数据
        /// </summary>
        /// <param name="inserts">更新对象列表</param>
        /// <returns></returns>
        int Update(IEnumerable<TEntity> updates);

        /// <summary>
        /// 更新一堆数据
        /// </summary>
        /// <param name="inserts">更新对象列表</param>
        /// <returns></returns>
        Task<int> UpdateAsync(IEnumerable<TEntity> updates);

        /// <summary>
        /// 更新一堆数据
        /// </summary>
        /// <param name="inserts">更新对象列表</param>
        /// <param name="fields">更新字段</param>
        /// <returns></returns>
        int Update(IEnumerable<TEntity> updates, string[] fields);

        /// <summary>
        /// 更新一堆数据
        /// </summary>
        /// <param name="inserts">更新对象列表</param>
        /// <param name="fields">更新字段</param>
        /// <returns></returns>
        Task<int> UpdateAsync(IEnumerable<TEntity> updates, string[] fields);

        #endregion

        #region 删除

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns></returns>
        int Delete(long id);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id">内码</param>
        /// <returns></returns>
        Task<int> DeleteAsync(long id);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ids">一堆内码</param>
        /// <returns></returns>
        int Delete(IEnumerable<long> ids);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ids">一堆内码</param>
        /// <returns></returns>
        Task<int> DeleteAsync(IEnumerable<long> ids);

        #endregion

        #region 执行

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <returns></returns>
        int Execute(string sqlString);

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <returns></returns>
        Task<int> ExecuteAsync(string sqlString);

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <returns></returns>
        int Execute(string sqlString, object? param = null);

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <returns></returns>
        Task<int> ExecuteAsync(string sqlString, object? param = null);

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <param name="dbTransaction">数据库事务</param>
        /// <returns></returns>
        int Execute(string sqlString, object? param = null, IDbTransaction? dbTransaction = null);

        /// <summary>
        /// 执行 SQL
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <param name="dbTransaction">数据库事务</param>
        /// <returns></returns>
        Task<int> ExecuteAsync(string sqlString, object? param = null, IDbTransaction? dbTransaction = null);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <returns></returns>
        int ExecuteStoredProcedure(string storedProcedure, object? param = null);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="sqlString">sql字符串</param>
        /// <param name="param">传入参数</param>
        /// <returns></returns>
        Task<int> ExecuteStoredProcedureAsync(string storedProcedure, object? param = null);

        #endregion

        #region 获取SQL

        /// <summary>
        /// 获取SQL
        /// </summary>
        /// <param name="queryParamenter"></param>
        /// <returns></returns>
        string GetSql(QueryParamenter queryParamenter);

        /// <summary>
        /// 查询全部SQL
        /// </summary>
        /// <returns></returns>
        string GetAllSql();

        /// <summary>
        /// 通过id查询SQL
        /// </summary>
        /// <returns></returns>
        string GetByIdSql();

        /// <summary>
        /// 通过一堆id查询SQL
        /// </summary>
        /// <returns></returns>
        string GetByIdsSql();

        /// <summary>
        /// 插入SQL
        /// </summary>
        /// <returns></returns>
        string InsertSql();

        /// <summary>
        /// 更新SQL
        /// </summary>
        /// <returns></returns>
        string UpdateSql();

        /// <summary>
        /// 更新SQL
        /// </summary>
        /// <param name="fields">要更新的字段</param>
        /// <returns></returns>
        string UpdateSql(string[] fields);

        /// <summary>
        /// 更新一堆SQL
        /// </summary>
        /// <returns></returns>
        string UpdatesSql();

        /// <summary>
        /// 更新一堆SQL
        /// </summary>
        /// <param name="fields">要更新的字段</param>
        /// <returns></returns>
        string UpdatesSql(string[] fields);

        /// <summary>
        /// 获取删除SQL
        /// </summary>
        /// <returns></returns>
        string DeleteAllSql();

        /// <summary>
        /// 通过id获取删除SQL
        /// </summary>
        /// <returns></returns>
        string DeleteSql();

        /// <summary>
        /// 通过一堆id获取删除SQL
        /// </summary>
        /// <returns></returns>
        string DeletesSql();

        #endregion

        #region 获取值和编码

        /// <summary>
        /// 设置id
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        long SetId(object param);

        /// <summary>
        /// 设置id
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        Task<long> SetIdAsync(object param);

        /// <summary>
        /// 获取下一个id。请在数据库中建立表（NextValue）,字段有（TableName: varchar, FieldName: varchar, Value: long）
        /// </summary>
        /// <param name="defaultValue">默认值：1</param>
        /// <returns></returns>
        long GetNextValue(long defaultValue = 1);

        /// <summary>
        /// 获取下一个id。请在数据库中建立表（NextValue）,字段有（TableName: varchar, FieldName: varchar, Value: long）
        /// </summary>
        /// <param name="defaultValue">默认值：1</param>
        /// <returns></returns>
        Task<long> GetNextValueAsync(long defaultValue = 1);

        /// <summary>
        /// 获取下一个id。请在数据库中建立表（NextValue）,字段有（TableName: varchar, FieldName: varchar, Value: long）
        /// </summary>
        /// <param name="defaultValue">默认值：1</param>
        /// <returns></returns>
        long GetNextValue(string tableName, string fieldName, long defaultValue = 1);

        /// <summary>
        /// 获取下一个id。请在数据库中建立表（NextValue）,字段有（TableName: varchar, FieldName: varchar, Value: long）
        /// </summary>
        /// <param name="defaultValue">默认值：1</param>
        /// <returns></returns>
        Task<long> GetNextValueAsync(string tableName, string fieldName, long defaultValue = 1);

        #endregion
    }
}
