using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Dapper;
using GB5Shared.DTO.Framework.Login;
using Microsoft.Data.SqlClient;
namespace GB5Shared.QueryExecutor
{
///
/// Defines the contract for executing database queries and commands.
/// This interface supports both automatic connection management (single calls)
/// and explicit transaction management (multiple calls on a single connection).
///
public interface IQueryExecutor
{
#region Transaction Management
///
/// Begins a new database transaction and returns the connection and transaction objects.
///
/// Important: This method creates a new, dedicated connection for this transaction.
/// You must pass the returned object to subsequent Query/Execute calls
/// to ensure they run on this specific connection. This allows multiple transactions to run
/// concurrently on different connections.
///
///
/// The login context containing database connection details.
/// A tuple containing the active and .
Task< DbTransaction> BeginTransactionAsync(LoginDTO LoginDTO);
///
/// Commits the active transaction and disposes the associated connection.
///
/// The connection object returned by .
/// The transaction object returned by .
Task CommitAsync(DbTransaction transaction);
///
/// Rolls back the active transaction and disposes the associated connection.
///
/// The connection object returned by .
/// The transaction object returned by .
Task RollbackAsync( DbTransaction transaction);
#endregion
#region Standard Query & Execute (Automatic Transaction Support)
///
/// Fetches a single record as a DTO based on the SQL query.
///
/// The type of DTO.
/// Login context for connection resolution.
/// The SQL query string.
/// Optional parameters for the SQL query.
///
/// Optional. If provided, the query executes on this specific transaction/connection.
/// If null, a temporary connection is created and closed automatically.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
/// to the query, allowing dirty reads for non-critical, high-throughput read scenarios.
/// WARNING: READ UNCOMMITTED may return dirty reads — uncommitted,
/// potentially rolled-back data from concurrent transactions. Never use for financial,
/// inventory, or any data that must be consistent. Ignored when an external
/// is supplied.
///
/// A single DTO or default(T) if no match is found.
Task QuerySingleAsync(LoginDTO LoginDTO, string sql, object parameters = null!, DbTransaction? transaction = null, bool useReadUncommitted = false, CancellationToken cancellationToken = default);
///
/// Fetches multiple records as a list of DTOs based on the SQL query.
///
/// The type of DTO.
/// Login context for connection resolution.
/// The SQL query string.
/// Optional parameters for the SQL query.
///
/// Optional. If provided, the query executes on this specific transaction/connection.
/// If null, a temporary connection is created and closed automatically.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
/// to the query. See for full dirty-read warning.
/// Ignored when an external is supplied.
///
/// A list of DTOs.
Task> QueryAsync(
LoginDTO LoginDTO,
string sql,
object parameters = null!,
DbTransaction? transaction = null,
bool useReadUncommitted = false,
CancellationToken cancellationToken = default
);
///
/// Executes a SQL command (INSERT, UPDATE, DELETE, etc.) and returns the number of affected rows.
///
/// Login context for connection resolution.
/// The SQL command string.
/// Optional parameters for the SQL command.
///
/// Optional. If provided, the command executes on this specific transaction/connection.
/// If null, a temporary connection is created and closed automatically.
///
/// The number of rows affected.
Task ExecuteAsync(LoginDTO LoginDTO, string sql, object parameters = null!, DbTransaction? transaction = null, CancellationToken cancellationToken = default);
///
/// Executes a SQL command using an explicit transaction and connection,
/// typically used after manually retrieving a transaction.
///
/// The SQL command string.
/// Parameters for the SQL command.
/// The explicit transaction to use.
/// The number of rows affected.
Task ExecuteAsync(string sql, object param, DbTransaction transaction);
///
/// Executes a command and returns the database-generated identity (ID) value (e.g., SCOPE_IDENTITY()).
///
/// Login context for connection resolution.
/// The INSERT SQL statement.
/// Optional parameters.
/// Optional transaction to enlist in.
/// The generated ID of the inserted record.
Task ExecuteIdentityAsync(LoginDTO loginDTO, string sql, object? parameters = null, DbTransaction? transaction = null);
///
/// Executes a query and returns the first column of the first row (e.g., COUNT, SUM).
///
/// The return type.
/// Login context.
/// The SQL query.
/// Optional parameters.
/// Optional transaction to enlist in.
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
/// The scalar value.
Task ExecuteScalarAsync(LoginDTO loginDTO, string sql, object? parameters = null, DbTransaction? transaction = null, bool useReadUncommitted = false, CancellationToken cancellationToken = default);
#endregion
#region Streaming & Bulk Operations
///
/// Streams the results of a query asynchronously, suitable for large datasets.
/// Uses CommandBehavior.SequentialAccess for efficient memory usage.
///
/// The type of DTO.
/// Login context.
/// The SQL query string.
/// Optional parameters.
/// Optional transaction to enlist in.
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
/// An asynchronous stream of DTOs.
///
/// WARNING: This method buffers the full result set in memory before yielding.
/// For true row-by-row streaming on large result sets (>5 000 rows), use
/// which uses a DataReader with SequentialAccess.
///
IAsyncEnumerable StreamAsync(
LoginDTO LoginDTO,
string sql,
object parameters = null!,
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default,
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Streams query results asynchronously using a DataReader, ideal for processing large result sets row-by-row.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
IAsyncEnumerable QueryStreamAsync(
LoginDTO LoginDTO,
string sql,
object parameters = null!,
[EnumeratorCancellation] CancellationToken cancellationToken = default,
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a bulk insert for a collection of DTOs in a single roundtrip if possible.
///
/// The type of DTO.
/// Login context.
/// The SQL insert statement.
/// The collection of items to insert.
/// Optional transaction to enlist in.
/// The number of rows affected.
Task BulkInsertAsync(LoginDTO LoginDTO, string sql, IEnumerable items, DbTransaction? transaction = null);
///
/// Performs a bulk insert using Table-Valued Parameters (TVP). Specific to SQL Server.
///
Task BulkInsertMultipleAsync(
LoginDTO loginDTO,
string commandText,
Dictionary tvpParameters
);
#endregion
#region Specialized Query Methods
///
/// Fetches records in a paginated fashion.
/// Executes the main query and a COUNT query to determine total records.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryPagedAsync(
LoginDTO LoginDTO,
string sql,
object parameters = null!,
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query mapping two related tables (Join) into a single DTO hierarchy.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryMultiMapAsync(
LoginDTO loginDTO,
string sql,
Func map,
object parameters = null!,
string splitOn = "Id",
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query mapping three related tables (Join) into a single DTO hierarchy.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryMultiMapAsync(
LoginDTO loginDTO,
string sql,
Func map,
object parameters = null!,
string splitOn = "Id,Id",
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query mapping five related tables.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryMultiMapAsync(
LoginDTO loginDTO,
string sql,
Func map,
object parameters = null!,
string splitOn = "Id,Id,Id,Id",
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query mapping seven related tables.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryMultiMapAsync(
LoginDTO loginDTO,
string sql,
Func map,
object parameters = null!,
string splitOn = "Id,Id,Id,Id,Id,Id",
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query and maps results to an array structure.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task> QueryAsyncArray(
LoginDTO loginDTO,
string sql,
Func map,
object parameters = null!,
string splitOn = "Id",
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a COUNT query based on a provided SQL query string.
/// Can wrap the query or use the query directly if it is already a count query.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
Task TotalCountSql(
string sqlQuery,
LoginDTO loginDTO,
object? parameters = null,
bool isCountQuery = false,
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
///
/// Executes a query returning an asynchronous enumerable.
///
///
/// Optional. When true, prepends SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
/// See for full dirty-read warning.
/// Ignored when an external is supplied.
///
IAsyncEnumerable ExecuteQueryAsync(
LoginDTO LoginDTO,
string sql,
object parameters = null!,
DbTransaction? transaction = null,
bool useReadUncommitted = false
);
#endregion
#region Connection Name & Procedures
///
/// Fetches data using a specific named connection string (defined in configuration),
/// separate from the default LoginDTO connection.
///
Task> QueryAsync(
string ConnectionName,
string sql,
object parameters = null!
);
///
/// Executes a list of Stored Procedures and returns a list of string status messages.
/// Each procedure execution is treated as a step.
///
Task> ProcedureExecuteAsync(
LoginDTO loginDTO,
IEnumerable<(string ProcedureName, object Param)> procedures
);
///
/// Executes a Count query specifically designed for TVP scenarios.
///
Task ExecuteTvpCountQueryAsync(
LoginDTO loginDTO,
string sqlQuery,
Dictionary tvpParameters
);
#endregion
#region Legacy Session Methods (HttpContext Based)
///
/// Executes a query within a "Session" managed by HttpContext Items.
/// Note: This relies on the HTTP context and may not work in background tasks.
/// Consider using explicit transactions () for better control.
///
Task> SessionQueryAsync(LoginDTO loginDTO, string sql, object param = null!);
///
/// Fetches a single result within a "Session" managed by HttpContext.
///
Task SessionQuerySingleAsync(LoginDTO loginDTO, string sql, object param = null!);
///
/// Executes a command within a "Session" managed by HttpContext.
///
Task SessionExecuteAsync(LoginDTO loginDTO, string sql, object param = null!);
///
/// Commits the transaction stored in the current HttpContext Session.
///
Task SameSessionCommitAsync();
///
/// Rolls back the transaction stored in the current HttpContext Session.
///
Task SameSessionRollbackAsync();
#endregion
#region Helper Methods
///
/// Executes a list of SQL statements inside a single isolated transaction.
/// This method manages the connection and transaction lifecycle internally.
///
Task ExecuteInTransactionAsync(
LoginDTO LoginDTO,
IEnumerable<(string sql, object param)> statements
);
Task QueryMultipleAsync(
LoginDTO loginDTO,
string sql,
object parameters = null!,
DbTransaction? transaction = null
);
Task QueryMultipleAsync(
LoginDTO loginDTO,
string sql,
object parameters = null!,
DbTransaction? transaction = null,
CommandType commandType = CommandType.StoredProcedure);
#endregion
}
}