using System.Security.Claims;
using adas_core.Application.Services.Interfaces;
using audit_logs.Services.Interfaces;
using Microsoft.Extensions.Logging;

namespace adas_core.Application.Services;

public class LocalAuditService(
    IAuditService auditService,
    ILogger<LocalAuditService> logger)
    : ILocalAuditService
{
    /// <summary>
    /// Creates an audit log entry asynchronously, forwarding the provided data to the audit service with a reason when one is supplied, and logging any errors that occur.
    /// </summary>
    /// <param name="user">The claims principal representing the user performing the action; used to attribute the audit log entry.</param>
    /// <param name="dataOriginal">The original data before the change.</param>
    /// <param name="dataModified">The modified data after the change.</param>
    /// <param name="reason">An optional reason for the change; when null, the audit log is created without supplying a reason.</param>
    public async Task CreateAuditLogAsync(ClaimsPrincipal? user, object? dataOriginal, object? dataModified,
            string? reason)
    {
        try
        {
            if (reason != null)
            {
                await auditService.CreateAuditLogAsync(user, dataOriginal!, dataModified!, reason);
            }
            else
            {
                _ = user?.FindFirst(ClaimTypes.Name)?.Value ?? "Not specified";

                await auditService.CreateAuditLogAsync(user, dataOriginal!, dataModified!);
            }
        }
        catch (Exception ex)
        {
            logger.LogError(ex.Message);
        }
    }

    /// <summary>
    /// Asynchronously deep copies the specified data, attempting a primary copy method and falling back to a JSON-based copy if the primary fails. Returns the default value if both copy attempts fail.
    /// </summary>
    /// <param name="data">The data to be deep copied.</param>
    /// <returns>A task representing the asynchronous operation, containing the deep copy of the data, or <c>null</c> if both copy methods fail.</returns>
    public async Task<T?> DeepCopyAsync<T>(T data)
    {
        try
        {
            return await auditService.DeepCopyAsync(data);
        }
        catch (Exception ex)
        {
            logger.LogWarning("Error copying object, trying with JsonDeepCopyAsync. Exception: {Message}", ex.Message);
            try
            {
                var copy = await auditService.JsonDeepCopyAsync(data);
                return copy;
            }
            catch (Exception e)
            {
                logger.LogError(e, "Error in fallback copy method. Exception: {Message}", e.Message);
                return default;
            }
        }
    }
}