using System;
using System.Collections.Generic;
namespace ECMJobRunner.Application.Common.Exceptions
{
///
/// Base exception class for job execution failures
/// Provides a flexible structure for capturing job context and detailed error information
///
///
/// Initializes a new instance of JobException with detailed context information
///
/// Identifier of the profile associated with the job
/// Name of the job that failed (e.g., "SQL Main Query", "ReC Request")
/// Name of the process/stage being executed (e.g., "MainQueryExecution", "CheckQueryValidation")
/// Unique batch identifier for tracking the execution
/// Human-readable reason for the failure (nullable)
/// The underlying exception that caused the failure (nullable)
/// Additional contextual details as name-value pairs with optional null-handling
///
/// The details parameter accepts tuples with:
/// - Name: Display name of the detail
/// - Value: String value of the detail (nullable)
/// - IgnoreIfNull: If true, the detail is omitted from the message when value is null
///
public class JobException(long profileId, string jobName, string processName, string batchId, string? reason, Exception? innerException, params (string Name, string? Value, bool IgnoreIfNull)[] details)
: Exception(
CreateMessage(jobName,
[
("Profile Id", profileId.ToString(), false),
("Job Name", jobName, false),
("Process Name", processName, false),
("Batch Id", batchId, false),
("Reason", reason, true),
..details
]),
innerException)
{
///
/// Gets the profile identifier associated with the job execution
///
public long ProfileId { get; } = profileId;
///
/// Gets the name of the job that failed
///
public string JobName { get; } = jobName;
///
/// Gets the name of the process/stage that was being executed when the failure occurred
///
public string ProcessName { get; } = processName;
///
/// Gets the unique batch identifier for tracking the execution
///
public string BatchId { get; } = batchId;
///
/// Generates a formatted error message with job context and details
///
/// Name of the job that failed
/// Collection of name-value pairs with optional null-handling
/// Formatted multi-line error message with visual separators
///
/// Message format:
///
/// {jobName} could not be completed.
/// Process Name: {processName}
/// Batch Id: {batchId}
/// {additional details...}
///
/// Details with IgnoreIfNull=true are omitted when their value is null.
///
internal static string CreateMessage(string jobName, IEnumerable<(string Name, string? Value, bool IgnoreIfNull)> details)
{
var message = new System.Text.StringBuilder();
message.AppendLine($"{jobName} could not be completed.");
foreach (var (name, value, ignoreNullValue) in details)
{
if (ignoreNullValue && value is null)
continue;
message.AppendLine($" {name}: {value}");
}
return message.ToString();
}
}
}