using Sentry;

namespace Managing.Api.Exceptions;

/// <summary>
/// Utility class for capturing errors with Sentry across the application
/// </summary>
public static class SentryErrorCapture
{
    /// <summary>
    /// Captures an exception in Sentry with additional context
    /// </summary>
    /// <param name="exception">The exception to capture</param>
    /// <param name="contextName">A descriptive name for where the error occurred</param>
    /// <param name="extraData">Optional dictionary of additional data to include</param>
    /// <returns>The Sentry event ID</returns>
    public static SentryId CaptureException(Exception exception, string contextName, IDictionary<string, object> extraData = null)
    {
        return SentrySdk.CaptureException(exception, scope =>
        {
            // Add context information
            scope.SetTag("context", contextName);
            scope.SetTag("error_type", exception.GetType().Name);
            
            // Add any extra data provided
            if (extraData != null)
            {
                foreach (var kvp in extraData)
                {
                    scope.SetExtra(kvp.Key, kvp.Value?.ToString() ?? "null");
                }
            }
            
            // Add extra info from the exception's Data dictionary if available
            foreach (var key in exception.Data.Keys)
            {
                if (key is string keyStr && exception.Data[key] != null)
                {
                    scope.SetExtra($"exception_data_{keyStr}", exception.Data[key].ToString());
                }
            }
            
            // Add a breadcrumb for context
            scope.AddBreadcrumb(
                message: $"Exception in {contextName}",
                category: "error",
                level: BreadcrumbLevel.Error
            );
        });
    }
    
    /// <summary>
    /// Enriches an exception with additional context data before throwing
    /// </summary>
    /// <param name="exception">The exception to enrich</param>
    /// <param name="contextData">Dictionary of context data to add</param>
    /// <returns>The enriched exception for chaining</returns>
    public static Exception EnrichException(Exception exception, IDictionary<string, object> contextData)
    {
        if (contextData != null)
        {
            foreach (var item in contextData)
            {
                exception.Data[item.Key] = item.Value;
            }
        }
        
        return exception;
    }
    
    /// <summary>
    /// Captures a message in Sentry with additional context
    /// </summary>
    /// <param name="message">The message to capture</param>
    /// <param name="level">The severity level</param>
    /// <param name="contextName">A descriptive name for where the message originated</param>
    /// <param name="extraData">Optional dictionary of additional data to include</param>
    /// <returns>The Sentry event ID</returns>
    public static SentryId CaptureMessage(string message, SentryLevel level, string contextName, IDictionary<string, object> extraData = null)
    {
        // First capture the message with the specified level
        var id = SentrySdk.CaptureMessage(message, level);
        
        // Then add context via a scope
        SentrySdk.ConfigureScope(scope =>
        {
            // Add context information
            scope.SetTag("context", contextName);
            
            // Add any extra data provided
            if (extraData != null)
            {
                foreach (var kvp in extraData)
                {
                    scope.SetExtra(kvp.Key, kvp.Value?.ToString() ?? "null");
                }
            }
            
            // Add a breadcrumb for context
            scope.AddBreadcrumb(
                message: $"Message from {contextName}",
                category: "message",
                level: BreadcrumbLevel.Info
            );
        });
        
        return id;
    }
} 