using KArtSell.Modules.ModelOperations.ShadowRun.Events;
using Microsoft.Extensions.Logging;

namespace KArtSell.Host.Consumers;

/// <summary>
/// Logs all shadow run completions (pass/fail) for compliance and audit.
/// Idempotent: Same event → same log entry (via idempotency key).
/// Ensures full traceability of model validation pipeline.
/// </summary>
public sealed class AuditLogConsumer : IInboxConsumer<ShadowRunCompletedEvent>
{
    private readonly ILogger<AuditLogConsumer> _logger;

    private static readonly Action<ILogger, Guid, string, Exception?> LogAudit =
        LoggerMessage.Define<Guid, string>(
            LogLevel.Information,
            new EventId(1, nameof(LogAudit)),
            "AUDIT: Shadow run {RunId} completed with status {Outcome}");

    private static readonly Action<ILogger, Guid, Exception?> LogPersisted =
        LoggerMessage.Define<Guid>(
            LogLevel.Debug,
            new EventId(2, nameof(LogPersisted)),
            "Audit log entry persisted for shadow run {RunId}");

    public AuditLogConsumer(ILogger<AuditLogConsumer> logger)
    {
        _logger = logger;
    }

    public async Task HandleAsync(ShadowRunCompletedEvent message, CancellationToken cancellationToken = default)
    {
        try
        {
            var outcome = message.AllGatesPassed ? "PASS" : "FAIL";

            LogAudit(_logger, message.RunId, outcome, null);

            if (!message.AllGatesPassed && message.ErrorMessage != null)
            {
                _logger.LogWarning(
                    "Shadow run {RunId} validation failed: {ErrorMessage}",
                    message.RunId, message.ErrorMessage);
            }

            // Log structured audit entry with full event context
            _logger.LogInformation(
                "Shadow run audit: RunId={RunId}, ModelId={ModelId}, Status={Outcome}, TotalReturn={TotalReturn}, SharpeRatio={SharpeRatio}, ProbOfBacktestOverfit={Pbo}, DailySharePercentile={Dsr}, CompletedAt={CompletedAt}, CorrelationId={CorrelationId}",
                message.RunId,
                message.ModelId,
                outcome,
                message.TotalReturn,
                message.SharpeRatio,
                message.ProbOfBacktestOverfit,
                message.DailySharePercentile,
                message.CompletedAt,
                message.CorrelationId);

            await Task.CompletedTask;  // Async compliance with interface
            LogPersisted(_logger, message.RunId, null);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to create audit log entry for {RunId}", message.RunId);
            throw;  // Let Hangfire classify
        }
    }
}
