// <copyright file="BulkTransactionExtensions.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>

namespace Jellyfin.Database.Providers.Postgres;

using System;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Database.Implementations;

/// <summary>
/// Extension methods for managing bulk operation transactions.
/// </summary>
public static class BulkTransactionExtensions
{
    /// <summary>
    /// Executes a bulk operation within a transaction.
    /// </summary>
    /// <param name="context">The database context.</param>
    /// <param name="operation">The bulk operation to execute.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    public static async Task ExecuteBulkOperationAsync(
        this JellyfinDbContext context,
        Func<Task> operation,
        CancellationToken cancellationToken = default)
    {
        using var transaction = new BulkOperationTransaction(context);
        try
        {
            await transaction.BeginAsync(cancellationToken).ConfigureAwait(false);
            await operation().ConfigureAwait(false);
            await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
        }
        catch
        {
            await transaction.RollbackAsync(cancellationToken).ConfigureAwait(false);
            throw;
        }
    }

    /// <summary>
    /// Executes a bulk operation within a transaction and returns a result.
    /// </summary>
    /// <typeparam name="T">The type of result returned by the operation.</typeparam>
    /// <param name="context">The database context.</param>
    /// <param name="operation">The bulk operation to execute.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The result of the operation.</returns>
    public static async Task<T?> ExecuteBulkOperationAsync<T>(
        this JellyfinDbContext context,
        Func<Task<T?>> operation,
        CancellationToken cancellationToken = default)
    {
        using var transaction = new BulkOperationTransaction(context);
        try
        {
            await transaction.BeginAsync(cancellationToken).ConfigureAwait(false);
            var result = await operation().ConfigureAwait(false);
            await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
            return result;
        }
        catch
        {
            await transaction.RollbackAsync(cancellationToken).ConfigureAwait(false);
            throw;
        }
    }
}
