using System.Data;
using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW.Core.Tests;

internal sealed record CatalogQueryCall(
    DataSourceKind Source,
    string TableName,
    DataQuerySpec Spec,
    CancellationToken CancellationToken);

internal sealed class CatalogRecordingQueryExecutor(
    Func<CatalogQueryCall, DataTable> handler) : IDataQueryExecutor
{
    internal List<CatalogQueryCall> Calls { get; } = [];

    public DataTable Execute(DataSourceKind source, string tableName, string query) =>
        throw new InvalidOperationException("Synchronous catalog queries are forbidden.");

    public Task<DataTable> ExecuteAsync(
        DataSourceKind source,
        string tableName,
        string query,
        CancellationToken cancellationToken = default) =>
        throw new InvalidOperationException("String SQL catalog queries are forbidden.");

    public Task<DataTable> ExecuteAsync(
        DataSourceKind source,
        string tableName,
        DataQuerySpec query,
        CancellationToken cancellationToken = default)
    {
        var call = new CatalogQueryCall(source, tableName, query, cancellationToken);
        Calls.Add(call);
        return Task.FromResult(handler(call));
    }
}
internal sealed class CatalogRecordingMutationExecutor(
    Func<OperatorCatalogDbTransaction, OperatorCatalogDbTransactionResult>? handler = null)
    : IOperatorCatalogMutationExecutor
{
    internal List<(OperatorCatalogDbTransaction Transaction, CancellationToken Token)> Calls
        { get; } = [];

    internal Exception? Exception { get; set; }

    public Task<OperatorCatalogDbTransactionResult> ExecuteTransactionAsync(
        OperatorCatalogDbTransaction transaction,
        CancellationToken cancellationToken = default)
    {
        Calls.Add((transaction, cancellationToken));
        if (Exception is not null)
        {
            return Task.FromException<OperatorCatalogDbTransactionResult>(Exception);
        }

        var result = handler?.Invoke(transaction) ?? new OperatorCatalogDbTransactionResult(
            transaction.OperationId,
            transaction.Commands.Select(command =>
                command.AffectedRowsRule == OperatorCatalogAffectedRowsRule.ExactlyOne ? 1 : 0)
                .ToArray(),
            DateTimeOffset.Parse("2026-07-11T00:00:00+09:00"));
        return Task.FromResult(result);
    }
}

internal static class OperatorCatalogTestTables
{
    internal static DataTable SingleString(string columnName, string value)
    {
        var table = new DataTable();
        table.Columns.Add(columnName, typeof(string));
        table.Rows.Add(value);
        return table;
    }

    internal static DataTable Empty(params string[] columns)
    {
        var table = new DataTable();
        foreach (var column in columns)
        {
            table.Columns.Add(column, typeof(string));
        }

        return table;
    }
}
